Commit 16cab91a authored by Anand Jain's avatar Anand Jain Committed by David Sterba
Browse files

btrfs: match stale devices by dev_t



After the commit "btrfs: harden identification of the stale device", we
don't have to match the device path anymore. Instead, we match the dev_t.
So pass in the dev_t instead of the device path, in the call chain
btrfs_forget_devices()->btrfs_free_stale_devices().

Signed-off-by: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 770c79fb
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -2383,6 +2383,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
{
	struct btrfs_ioctl_vol_args *vol;
	struct btrfs_device *device = NULL;
	dev_t devt = 0;
	int ret = -ENOTTY;

	if (!capable(CAP_SYS_ADMIN))
@@ -2402,7 +2403,12 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
		mutex_unlock(&uuid_mutex);
		break;
	case BTRFS_IOC_FORGET_DEV:
		ret = btrfs_forget_devices(vol->name);
		if (vol->name[0] != 0) {
			ret = lookup_bdev(vol->name, &devt);
			if (ret)
				break;
		}
		ret = btrfs_forget_devices(devt);
		break;
	case BTRFS_IOC_DEVICES_READY:
		mutex_lock(&uuid_mutex);
+31 −25
Original line number Diff line number Diff line
@@ -541,11 +541,10 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
 *   true  If it is the same device.
 *   false If it is not the same device or on error.
 */
static bool device_matched(const struct btrfs_device *device, const char *path)
static bool device_matched(const struct btrfs_device *device, dev_t dev_new)
{
	char *device_name;
	dev_t dev_old;
	dev_t dev_new;
	int ret;

	/*
@@ -568,29 +567,26 @@ static bool device_matched(const struct btrfs_device *device, const char *path)
	if (ret)
		return false;

	ret = lookup_bdev(path, &dev_new);
	if (ret)
		return false;

	if (dev_old == dev_new)
		return true;

	return false;
}

/*
 *  Search and remove all stale (devices which are not mounted) devices.
/**
 *  Search and remove all stale devices (which are not mounted).
 *  When both inputs are NULL, it will search and release all stale devices.
 *  path:	Optional. When provided will it release all unmounted devices
 *		matching this path only.
 *  skip_dev:	Optional. Will skip this device when searching for the stale
 *
 *  @devt:	Optional. When provided will it release all unmounted devices
 *		matching this devt only.
 *  @skip_device:  Optional. Will skip this device when searching for the stale
 *		devices.
 *  Return:	0 for success or if @path is NULL.
 * 		-EBUSY if @path is a mounted device.
 * 		-ENOENT if @path does not match any device in the list.
 *
 *  Return:	0 for success or if @devt is 0.
 *		-EBUSY if @devt is a mounted device.
 *		-ENOENT if @devt does not match any device in the list.
 */
static int btrfs_free_stale_devices(const char *path,
				     struct btrfs_device *skip_device)
static int btrfs_free_stale_devices(dev_t devt, struct btrfs_device *skip_device)
{
	struct btrfs_fs_devices *fs_devices, *tmp_fs_devices;
	struct btrfs_device *device, *tmp_device;
@@ -598,7 +594,7 @@ static int btrfs_free_stale_devices(const char *path,

	lockdep_assert_held(&uuid_mutex);

	if (path)
	if (devt)
		ret = -ENOENT;

	list_for_each_entry_safe(fs_devices, tmp_fs_devices, &fs_uuids, fs_list) {
@@ -608,11 +604,11 @@ static int btrfs_free_stale_devices(const char *path,
					 &fs_devices->devices, dev_list) {
			if (skip_device && skip_device == device)
				continue;
			if (path && !device_matched(device, path))
			if (devt && !device_matched(device, devt))
				continue;
			if (fs_devices->opened) {
				/* for an already deleted device return 0 */
				if (path && ret != 0)
				if (devt && ret != 0)
					ret = -EBUSY;
				break;
			}
@@ -1362,12 +1358,12 @@ static struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev
	return disk_super;
}

int btrfs_forget_devices(const char *path)
int btrfs_forget_devices(dev_t devt)
{
	int ret;

	mutex_lock(&uuid_mutex);
	ret = btrfs_free_stale_devices(strlen(path) ? path : NULL, NULL);
	ret = btrfs_free_stale_devices(devt, NULL);
	mutex_unlock(&uuid_mutex);

	return ret;
@@ -1416,9 +1412,15 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
	}

	device = device_list_add(path, disk_super, &new_device_added);
	if (!IS_ERR(device)) {
		if (new_device_added)
			btrfs_free_stale_devices(path, device);
	if (!IS_ERR(device) && new_device_added) {
		dev_t devt;

		/*
		 * It is ok to ignore if we fail to free the stale device (if
		 * any). As there is nothing much that can be done about it.
		 */
		if (lookup_bdev(path, &devt) == 0)
			btrfs_free_stale_devices(devt, device);
	}

	btrfs_release_disk_super(disk_super);
@@ -2650,6 +2652,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
	int ret = 0;
	bool seeding_dev = false;
	bool locked = false;
	dev_t devt;

	if (sb_rdonly(sb) && !fs_devices->seeding)
		return -EROFS;
@@ -2842,10 +2845,13 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
	 * Now that we have written a new super block to this device, check all
	 * other fs_devices list if device_path alienates any other scanned
	 * device.
	 * Skip forget_deivces if lookup_bdev() fails as there is nothing much
	 * that can be done about it.
	 * We can ignore the return value as it typically returns -EINVAL and
	 * only succeeds if the device was an alien.
	 */
	btrfs_forget_devices(device_path);
	if (lookup_bdev(device_path, &devt) == 0)
		btrfs_forget_devices(devt);

	/* Update ctime/mtime for blkid or udev */
	update_dev_time(device_path);
+1 −1
Original line number Diff line number Diff line
@@ -505,7 +505,7 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
		       fmode_t flags, void *holder);
struct btrfs_device *btrfs_scan_one_device(const char *path,
					   fmode_t flags, void *holder);
int btrfs_forget_devices(const char *path);
int btrfs_forget_devices(dev_t devt);
void btrfs_close_devices(struct btrfs_fs_devices *fs_devices);
void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices);
void btrfs_assign_next_active_device(struct btrfs_device *device,