mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-04 01:24:12 +08:00
btrfs: harden identification of a stale device
Identifying and removing the stale device from the fs_uuids list is done by btrfs_free_stale_devices(). btrfs_free_stale_devices() in turn depends on device_path_matched() to check if the device appears in more than one btrfs_device structure. The matching of the device happens by its path, the device path. However, when device 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 string compare of the device paths. Reported-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Anand Jain <anand.jain@oracle.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
bef16b5298
commit
770c79fb65
@ -534,15 +534,48 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool device_path_matched(const char *path, struct btrfs_device *device)
|
||||
/*
|
||||
* Check if the device in the path matches the device in the given struct device.
|
||||
*
|
||||
* Returns:
|
||||
* 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)
|
||||
{
|
||||
int found;
|
||||
char *device_name;
|
||||
dev_t dev_old;
|
||||
dev_t dev_new;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If we are looking for a device with the matching dev_t, then skip
|
||||
* device without a name (a missing device).
|
||||
*/
|
||||
if (!device->name)
|
||||
return false;
|
||||
|
||||
device_name = kzalloc(BTRFS_PATH_NAME_MAX, GFP_KERNEL);
|
||||
if (!device_name)
|
||||
return false;
|
||||
|
||||
rcu_read_lock();
|
||||
found = strcmp(rcu_str_deref(device->name), path);
|
||||
scnprintf(device_name, BTRFS_PATH_NAME_MAX, "%s", rcu_str_deref(device->name));
|
||||
rcu_read_unlock();
|
||||
|
||||
return found == 0;
|
||||
ret = lookup_bdev(device_name, &dev_old);
|
||||
kfree(device_name);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
ret = lookup_bdev(path, &dev_new);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
if (dev_old == dev_new)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -575,9 +608,7 @@ static int btrfs_free_stale_devices(const char *path,
|
||||
&fs_devices->devices, dev_list) {
|
||||
if (skip_device && skip_device == device)
|
||||
continue;
|
||||
if (path && !device->name)
|
||||
continue;
|
||||
if (path && !device_path_matched(path, device))
|
||||
if (path && !device_matched(device, path))
|
||||
continue;
|
||||
if (fs_devices->opened) {
|
||||
/* for an already deleted device return 0 */
|
||||
|
Loading…
Reference in New Issue
Block a user