btrfs-progs: fix duplicate missing device

btrfs_read_sys_array() adds a missing device with its devid only.  So,
any subsequent btrfs_find_device(..devid, uuid) call in the
open_ctree_fd() still fails resulting in addition of duplicate struct
btrfs_device to the list, as shown below.

  open_ctree_fd()
  ::
   btrfs_setup_chunk_tree_and_device_map()
    btrfs_read_sys_array()
     read_one_chunk()
      btrfs_find_device()
      fill_missing_device() <--- dev_uuid wasn't updated
      list_add()
    btrfs_read_chunk_tree
      read_one_dev()
	 btrfs_find_device(..,devid, dev_uuid,..); <-- fails
	 list_add
	 fill_device_from_item(leaf, dev_item, device);

This ends up having two btrfs_device for the same missing devid.

For example:

(btrfstune is compiled with a boilerplate code to dump the device list,
as in the mailing list).

Before:

There are two device with devid 1.

$ btrfstune -m ./disk4.raw
warning, device 1 is missing
[fsid: 95bbc163-671a-4a0a-bd34-03a65e4b338c]
	size:			120
	metadata_uuid:		95bbc163-671a-4a0a-bd34-03a65e4b338c
	fs_devs_addr:		0xdb64e0
	total_rw_bytes:		1048576000
	[[UUID: 703a4cac-bca0-47e4-98f6-55e530800172]]
		sb_flags: 0x0
		sb_incompact_flags: 0x0
		dev_addr:	0xdb69a0
		device:		(null)
		devid:		1
		generation:	0
		total_bytes:	524288000
		bytes_used:	127926272
		type:		0
		io_align:	4096
		io_width:	4096
		sector_size:	4096
	[[UUID: 00000000-0000-0000-0000-000000000000]]
		sb_flags: 0x0
		sb_incompact_flags: 0x0
		dev_addr:	0xdb3060
		device:		(null)
		devid:		1
		generation:	0
		total_bytes:	0
		bytes_used:	0
		type:		0
		io_align:	0
		io_width:	0
		sector_size:	0
	[[UUID: 1db7564f-e53b-46ff-8a33-a8b2d00d86d1]]
		sb_flags: 0x1000000001
		sb_incompact_flags: 0x141
		dev_addr:	0xdb6e90
		device:		/tdev/disk4.raw
		devid:		2
		generation:	6
		total_bytes:	524288000
		bytes_used:	127926272
		type:		0
		io_align:	4096
		io_width:	4096
		sector_size:	4096

Fix this issue by adding the UUID to the missing device created in
fill_missing_device().

After:

$ btrfstune -m /tdev/disk4.raw
warning, device 1 is missing
[fsid: 95bbc163-671a-4a0a-bd34-03a65e4b338c]
        size:                   120
        metadata_uuid:          95bbc163-671a-4a0a-bd34-03a65e4b338c
        fs_devs_addr:           0x161f380
        total_rw_bytes:         1048576000
        [[UUID: 703a4cac-bca0-47e4-98f6-55e530800172]]
                sb_flags: 0x0
                sb_incompact_flags: 0x0
                dev_addr:       0x161c060
                device:         (null)
                devid:          1
                generation:     0
                total_bytes:    524288000
                bytes_used:     127926272
                type:           0
                io_align:       4096
                io_width:       4096
                sector_size:    4096
        [[UUID: 1db7564f-e53b-46ff-8a33-a8b2d00d86d1]]
                sb_flags: 0x1000000001
                sb_incompact_flags: 0x141
                dev_addr:       0x161fe90
                device:         /tdev/disk4.raw
                devid:          2
                generation:     6
                total_bytes:    524288000
                bytes_used:     127926272
                type:           0
                io_align:       4096
                io_width:       4096
                sector_size:    4096

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Anand Jain 2023-08-03 07:29:39 +08:00 committed by David Sterba
parent 57cd29c895
commit b8b0f1ec41
1 changed files with 3 additions and 2 deletions

View File

@ -2077,12 +2077,13 @@ int btrfs_chunk_readonly(struct btrfs_fs_info *fs_info, u64 chunk_offset)
return readonly;
}
static struct btrfs_device *fill_missing_device(u64 devid)
static struct btrfs_device *fill_missing_device(u64 devid, const u8 *uuid)
{
struct btrfs_device *device;
device = kzalloc(sizeof(*device), GFP_NOFS);
device->devid = devid;
memcpy(device->uuid, uuid, BTRFS_UUID_SIZE);
device->fd = -1;
return device;
}
@ -2150,7 +2151,7 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
map->stripes[i].dev = btrfs_find_device(fs_info, devid, uuid,
NULL);
if (!map->stripes[i].dev) {
map->stripes[i].dev = fill_missing_device(devid);
map->stripes[i].dev = fill_missing_device(devid, uuid);
printf("warning, device %llu is missing\n",
(unsigned long long)devid);
list_add(&map->stripes[i].dev->dev_list,