Skip to content
Permalink
Browse files
btrfs: harden identification of the stale device
Identifying and removing the stale device from the fs_uuids list is done
by the function btrfs_free_stale_devices().
btrfs_free_stale_devices() in turn depends on the function
device_path_matched() to check if the device repeats in more than one
btrfs_device structure.

The matching of the device happens by its path, the device path. However,
when dm mapper is in use, the dm device paths are nothing but a link to
the actual block device, which leads to the device_path_matched() failing
to match.

Fix this by matching the dev_t as provided by lookup_bdev() instead of
plain strcmp() the device paths.

Reported-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Anand Jain <anand.jain@oracle.com>
  • Loading branch information
asj authored and intel-lab-lkp committed Dec 8, 2021
1 parent 279373d commit 03b597640967afb3d37dc37f0a685fed95594b83
Showing 1 changed file with 26 additions and 7 deletions.
@@ -530,15 +530,34 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
return ret;
}

static bool device_path_matched(const char *path, struct btrfs_device *device)
/*
* Check if the device in the 'path' matches with the device in the given
* struct btrfs_device '*device'.
* Returns:
* 0 If it is the same device.
* 1 If it is not the same device.
* -errno For error.
*/
static int device_matched(struct btrfs_device *device, const char *path)
{
int found;
dev_t dev_old;
dev_t dev_new;
int error;

rcu_read_lock();
found = strcmp(rcu_str_deref(device->name), path);
rcu_read_unlock();
lockdep_assert_held(&device->fs_devices->device_list_mutex);
/* rcu is not required as we are inside the device_list_mutex */
error = lookup_bdev(device->name->str, &dev_old);
if (error)
return error;

return found == 0;
error = lookup_bdev(path, &dev_new);
if (error)
return error;

if (dev_old == dev_new)
return 0;

return 1;
}

/*
@@ -573,7 +592,7 @@ static int btrfs_free_stale_devices(const char *path,
continue;
if (path && !device->name)
continue;
if (path && !device_path_matched(path, device))
if (path && device_matched(device, path) != 0)
continue;
if (fs_devices->opened) {
/* for an already deleted device return 0 */

0 comments on commit 03b5976

Please sign in to comment.