提交 12ce923e 编写于 作者: A Anand Jain 提交者: Jialin Zhang

btrfs: harden identification of a stale device

stable inclusion
from stable-v5.10.142
commit 7f73a9dea00954976999acac5fe9d4932d6e1cd0
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6CSFH

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7f73a9dea00954976999acac5fe9d4932d6e1cd0

--------------------------------

commit 770c79fb upstream.

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: NJosef Bacik <josef@toxicpanda.com>
Signed-off-by: NAnand Jain <anand.jain@oracle.com>
Signed-off-by: NDavid Sterba <dsterba@suse.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NJialin Zhang <zhangjialin11@huawei.com>
Reviewed-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 8a43027e
......@@ -540,15 +540,47 @@ 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 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;
struct block_device *bdev_old;
struct block_device *bdev_new;
/*
* 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;
bdev_old = lookup_bdev(device_name);
kfree(device_name);
if (IS_ERR(bdev_old))
return false;
bdev_new = lookup_bdev(path);
if (IS_ERR(bdev_new))
return false;
if (bdev_old == bdev_new)
return true;
return false;
}
/*
......@@ -581,9 +613,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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册