Commit 7bb3a371 authored by Masato Suzuki's avatar Masato Suzuki Committed by Jaegeuk Kim

f2fs: Fix zoned block device support

The introduction of the multi-device feature partially broke the support
for zoned block devices. In the function f2fs_scan_devices, sbi->devs
allocation and initialization is skipped in the case of a single device
mount. This result in no device information structure being allocated
for the device. This is fine if the device is a regular device, but in
the case of a zoned block device, the device zone type array is not
initialized, which causes the function __f2fs_issue_discard_zone to fail
as get_blkz_type is unable to determine the zone type of a section.

Fix this by always allocating and initializing the sbi->devs device
information array even in the case of a single device if that device is
zoned. For this particular case, make sure to obtain a reference on the
single device so that the call to blkdev_put() in destroy_device_list
operates as expected.

Fixes: 3c62be17 ("f2fs: support multiple devices")
Cc: <stable@vger.kernel.org> # v4.10
Signed-off-by: default avatarMasato Suzuki <masato.suzuki@wdc.com>
Acked-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 4fcf589a
...@@ -1743,21 +1743,40 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) ...@@ -1743,21 +1743,40 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
static int f2fs_scan_devices(struct f2fs_sb_info *sbi) static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
{ {
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
unsigned int max_devices = MAX_DEVICES;
int i; int i;
for (i = 0; i < MAX_DEVICES; i++) { /* Initialize single device information */
if (!RDEV(i).path[0]) if (!RDEV(0).path[0]) {
if (!bdev_is_zoned(sbi->sb->s_bdev))
return 0; return 0;
max_devices = 1;
}
if (i == 0) { /*
sbi->devs = kzalloc(sizeof(struct f2fs_dev_info) * * Initialize multiple devices information, or single
MAX_DEVICES, GFP_KERNEL); * zoned block device information.
*/
sbi->devs = kcalloc(max_devices, sizeof(struct f2fs_dev_info),
GFP_KERNEL);
if (!sbi->devs) if (!sbi->devs)
return -ENOMEM; return -ENOMEM;
}
for (i = 0; i < max_devices; i++) {
if (i > 0 && !RDEV(i).path[0])
break;
if (max_devices == 1) {
/* Single zoned block device mount */
FDEV(0).bdev =
blkdev_get_by_dev(sbi->sb->s_bdev->bd_dev,
sbi->sb->s_mode, sbi->sb->s_type);
} else {
/* Multi-device mount */
memcpy(FDEV(i).path, RDEV(i).path, MAX_PATH_LEN); memcpy(FDEV(i).path, RDEV(i).path, MAX_PATH_LEN);
FDEV(i).total_segments = le32_to_cpu(RDEV(i).total_segments); FDEV(i).total_segments =
le32_to_cpu(RDEV(i).total_segments);
if (i == 0) { if (i == 0) {
FDEV(i).start_blk = 0; FDEV(i).start_blk = 0;
FDEV(i).end_blk = FDEV(i).start_blk + FDEV(i).end_blk = FDEV(i).start_blk +
...@@ -1770,9 +1789,9 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) ...@@ -1770,9 +1789,9 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
(FDEV(i).total_segments << (FDEV(i).total_segments <<
sbi->log_blocks_per_seg) - 1; sbi->log_blocks_per_seg) - 1;
} }
FDEV(i).bdev = blkdev_get_by_path(FDEV(i).path, FDEV(i).bdev = blkdev_get_by_path(FDEV(i).path,
sbi->sb->s_mode, sbi->sb->s_type); sbi->sb->s_mode, sbi->sb->s_type);
}
if (IS_ERR(FDEV(i).bdev)) if (IS_ERR(FDEV(i).bdev))
return PTR_ERR(FDEV(i).bdev); return PTR_ERR(FDEV(i).bdev);
...@@ -1792,6 +1811,8 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) ...@@ -1792,6 +1811,8 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
"Failed to initialize F2FS blkzone information"); "Failed to initialize F2FS blkzone information");
return -EINVAL; return -EINVAL;
} }
if (max_devices == 1)
break;
f2fs_msg(sbi->sb, KERN_INFO, f2fs_msg(sbi->sb, KERN_INFO,
"Mount Device [%2d]: %20s, %8u, %8x - %8x (zone: %s)", "Mount Device [%2d]: %20s, %8u, %8x - %8x (zone: %s)",
i, FDEV(i).path, i, FDEV(i).path,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment