Skip to content

Commit ba73ead

Browse files
lostjefflehsiangkao
authored andcommitted
erofs: scan devices from device table
When "-o device" mount option is not specified, scan the device table and instantiate the devices if there's any in the device table. In this case, the tag field of each device slot uniquely specifies a device. Signed-off-by: Jeffle Xu <[email protected]> Reviewed-by: Gao Xiang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Gao Xiang <[email protected]>
1 parent d435d53 commit ba73ead

File tree

2 files changed

+72
-39
lines changed

2 files changed

+72
-39
lines changed

fs/erofs/erofs_fs.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,9 @@
3737
#define EROFS_SB_EXTSLOT_SIZE 16
3838

3939
struct erofs_deviceslot {
40-
union {
41-
u8 uuid[16]; /* used for device manager later */
42-
u8 userdata[64]; /* digest(sha256), etc. */
43-
} u;
44-
__le32 blocks; /* total fs blocks of this device */
45-
__le32 mapped_blkaddr; /* map starting at mapped_blkaddr */
40+
u8 tag[64]; /* digest(sha256), etc. */
41+
__le32 blocks; /* total fs blocks of this device */
42+
__le32 mapped_blkaddr; /* map starting at mapped_blkaddr */
4643
u8 reserved[56];
4744
};
4845
#define EROFS_DEVT_SLOT_SIZE sizeof(struct erofs_deviceslot)

fs/erofs/super.c

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,59 @@ static int erofs_load_compr_cfgs(struct super_block *sb,
220220
}
221221
#endif
222222

223-
static int erofs_init_devices(struct super_block *sb,
223+
static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
224+
struct erofs_device_info *dif, erofs_off_t *pos)
225+
{
226+
struct erofs_sb_info *sbi = EROFS_SB(sb);
227+
struct erofs_deviceslot *dis;
228+
struct block_device *bdev;
229+
void *ptr;
230+
int ret;
231+
232+
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*pos), EROFS_KMAP);
233+
if (IS_ERR(ptr))
234+
return PTR_ERR(ptr);
235+
dis = ptr + erofs_blkoff(*pos);
236+
237+
if (!dif->path) {
238+
if (!dis->tag[0]) {
239+
erofs_err(sb, "empty device tag @ pos %llu", *pos);
240+
return -EINVAL;
241+
}
242+
dif->path = kmemdup_nul(dis->tag, sizeof(dis->tag), GFP_KERNEL);
243+
if (!dif->path)
244+
return -ENOMEM;
245+
}
246+
247+
if (erofs_is_fscache_mode(sb)) {
248+
ret = erofs_fscache_register_cookie(sb, &dif->fscache,
249+
dif->path, false);
250+
if (ret)
251+
return ret;
252+
} else {
253+
bdev = blkdev_get_by_path(dif->path, FMODE_READ | FMODE_EXCL,
254+
sb->s_type);
255+
if (IS_ERR(bdev))
256+
return PTR_ERR(bdev);
257+
dif->bdev = bdev;
258+
dif->dax_dev = fs_dax_get_by_bdev(bdev, &dif->dax_part_off);
259+
}
260+
261+
dif->blocks = le32_to_cpu(dis->blocks);
262+
dif->mapped_blkaddr = le32_to_cpu(dis->mapped_blkaddr);
263+
sbi->total_blocks += dif->blocks;
264+
*pos += EROFS_DEVT_SLOT_SIZE;
265+
return 0;
266+
}
267+
268+
static int erofs_scan_devices(struct super_block *sb,
224269
struct erofs_super_block *dsb)
225270
{
226271
struct erofs_sb_info *sbi = EROFS_SB(sb);
227272
unsigned int ondisk_extradevs;
228273
erofs_off_t pos;
229274
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
230275
struct erofs_device_info *dif;
231-
struct erofs_deviceslot *dis;
232-
void *ptr;
233276
int id, err = 0;
234277

235278
sbi->total_blocks = sbi->primarydevice_blocks;
@@ -238,7 +281,8 @@ static int erofs_init_devices(struct super_block *sb,
238281
else
239282
ondisk_extradevs = le16_to_cpu(dsb->extra_devices);
240283

241-
if (ondisk_extradevs != sbi->devs->extra_devices) {
284+
if (sbi->devs->extra_devices &&
285+
ondisk_extradevs != sbi->devs->extra_devices) {
242286
erofs_err(sb, "extra devices don't match (ondisk %u, given %u)",
243287
ondisk_extradevs, sbi->devs->extra_devices);
244288
return -EINVAL;
@@ -249,39 +293,31 @@ static int erofs_init_devices(struct super_block *sb,
249293
sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1;
250294
pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
251295
down_read(&sbi->devs->rwsem);
252-
idr_for_each_entry(&sbi->devs->tree, dif, id) {
253-
struct block_device *bdev;
254-
255-
ptr = erofs_read_metabuf(&buf, sb, erofs_blknr(pos),
256-
EROFS_KMAP);
257-
if (IS_ERR(ptr)) {
258-
err = PTR_ERR(ptr);
259-
break;
260-
}
261-
dis = ptr + erofs_blkoff(pos);
262-
263-
if (erofs_is_fscache_mode(sb)) {
264-
err = erofs_fscache_register_cookie(sb, &dif->fscache,
265-
dif->path, false);
296+
if (sbi->devs->extra_devices) {
297+
idr_for_each_entry(&sbi->devs->tree, dif, id) {
298+
err = erofs_init_device(&buf, sb, dif, &pos);
266299
if (err)
267300
break;
268-
} else {
269-
bdev = blkdev_get_by_path(dif->path,
270-
FMODE_READ | FMODE_EXCL,
271-
sb->s_type);
272-
if (IS_ERR(bdev)) {
273-
err = PTR_ERR(bdev);
301+
}
302+
} else {
303+
for (id = 0; id < ondisk_extradevs; id++) {
304+
dif = kzalloc(sizeof(*dif), GFP_KERNEL);
305+
if (!dif) {
306+
err = -ENOMEM;
274307
break;
275308
}
276-
dif->bdev = bdev;
277-
dif->dax_dev = fs_dax_get_by_bdev(bdev,
278-
&dif->dax_part_off);
279-
}
280309

281-
dif->blocks = le32_to_cpu(dis->blocks);
282-
dif->mapped_blkaddr = le32_to_cpu(dis->mapped_blkaddr);
283-
sbi->total_blocks += dif->blocks;
284-
pos += EROFS_DEVT_SLOT_SIZE;
310+
err = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
311+
if (err < 0) {
312+
kfree(dif);
313+
break;
314+
}
315+
++sbi->devs->extra_devices;
316+
317+
err = erofs_init_device(&buf, sb, dif, &pos);
318+
if (err)
319+
break;
320+
}
285321
}
286322
up_read(&sbi->devs->rwsem);
287323
erofs_put_metabuf(&buf);
@@ -368,7 +404,7 @@ static int erofs_read_superblock(struct super_block *sb)
368404
goto out;
369405

370406
/* handle multiple devices */
371-
ret = erofs_init_devices(sb, dsb);
407+
ret = erofs_scan_devices(sb, dsb);
372408

373409
if (erofs_sb_has_ztailpacking(sbi))
374410
erofs_info(sb, "EXPERIMENTAL compressed inline data feature in use. Use at your own risk!");

0 commit comments

Comments
 (0)