[PATCH] btrfs: free unlinked replace target on initialization failure

Guanghui Yang <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
btrfs_init_dev_replace_tgtdev() allocates the replacement target before
looking up its dev_t and initializing its zoned device information. If
either lookup_bdev() or btrfs_get_dev_zone_info() fails, the device has
not been linked into fs_devices->devices yet, but the error path only
drops the block device file reference.

Free the allocated device on this error path to release its name,
allocation state, zone info, and the device itself.

Signed-off-by: Guanghui Yang <[email protected]>
---
 fs/btrfs/dev-replace.c | 4 ++++
 fs/btrfs/volumes.c     | 2 +-
 fs/btrfs/volumes.h     | 1 +
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 318ddb790..3c17481c9 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -240,6 +240,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 	struct block_device *bdev;
 	u64 devid = BTRFS_DEV_REPLACE_DEVID;
 	int ret = 0;
+	bool device_allocated = false;
 
 	*device_out = NULL;
 	if (srcdev->fs_devices->seeding) {
@@ -287,6 +288,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 		ret = PTR_ERR(device);
 		goto error;
 	}
+	device_allocated = true;
 
 	ret = lookup_bdev(device_path, &device->devt);
 	if (ret)
@@ -327,6 +329,8 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 	return 0;
 
 error:
+	if (device_allocated)
+		btrfs_free_device(device);
 	bdev_fput(bdev_file);
 	return ret;
 }
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a8e27db8e..c479f268a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -402,7 +402,7 @@ static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid)
 	return fs_devs;
 }
 
-static void btrfs_free_device(struct btrfs_device *device)
+void btrfs_free_device(struct btrfs_device *device)
 {
 	WARN_ON(!list_empty(&device->post_commit_list));
 	/*
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index eaf23c0dc..ecab3ce3c 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -795,6 +795,7 @@ int btrfs_run_dev_stats(struct btrfs_trans_handle *trans);
 void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_device *srcdev);
 void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev);
 void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev);
+void btrfs_free_device(struct btrfs_device *device);
 unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
 				    u64 logical);
 u64 btrfs_calc_stripe_length(const struct btrfs_chunk_map *map);
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.