diff options
author | Anand Jain <Anand.Jain@oracle.com> | 2014-02-24 19:43:38 +0800 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-03-21 06:23:27 -0700 |
commit | 9567dc89521ba83f3dba561c82a3f6b9aff30a02 (patch) | |
tree | d04e7e723c4e7e636bfb7aeeedd333432d1ada39 /utils.c | |
parent | 50275bacab0f62b91453fbfa29e75c2bb77bf9b6 (diff) |
btrfs-progs: latest_devid is not always the probed devid
btrfs-progs picks the latest_dev based on first probed
greatest trans-id. However below test case proofs that
approach is wrong.
$ mkfs.btrfs -d raid1 -m raid1 /dev/sde /dev/sdf
$ modprobe -r btrfs && modprobe btrfs
$ mount -o degraded /dev/sde /btrfs
$ touch /btrfs/testfile && btrfs fi sync /btrfs
The above steps will make /dev/sdf not part of the btrfs.
and as below when you use /dev/sdf the btrfs dev stat
and dev scrub picks up wrong disk
$ btrfs dev stat /dev/sdf
[/dev/sde].write_io_errs 0
[/dev/sde].read_io_errs 0
[/dev/sde].flush_io_errs 0
[/dev/sde].corruption_errs 0
[/dev/sde].generation_errs 0
$ btrfs scrub start -B /dev/sdf
scrub done for 2e99c881-6abd-4f8a-8290-e2f8d0acc575
scrub started at Mon Feb 24 14:45:06 2014 and finished after 0 seconds
total bytes scrubbed: 256.00KiB with 0 errors
Signed-off-by: Anand Jain <Anand.Jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'utils.c')
-rw-r--r-- | utils.c | 18 |
1 files changed, 16 insertions, 2 deletions
@@ -1678,6 +1678,10 @@ int get_fs_info(char *path, struct btrfs_ioctl_fs_info_args *fi_args, memset(fi_args, 0, sizeof(*fi_args)); if (is_block_device(path)) { + struct btrfs_super_block *disk_super; + char buf[BTRFS_SUPER_INFO_SIZE]; + u64 devid; + /* Ensure it's mounted, then set path to the mountpoint */ fd = open(path, O_RDONLY); if (fd < 0) { @@ -1697,8 +1701,18 @@ int get_fs_info(char *path, struct btrfs_ioctl_fs_info_args *fi_args, path = mp; /* Only fill in this one device */ fi_args->num_devices = 1; - fi_args->max_id = fs_devices_mnt->latest_devid; - i = fs_devices_mnt->latest_devid; + + disk_super = (struct btrfs_super_block *)buf; + ret = btrfs_read_dev_super(fd, disk_super, BTRFS_SUPER_INFO_OFFSET); + if (ret < 0) { + ret = -EIO; + goto out; + } + devid = btrfs_stack_device_id(&disk_super->dev_item); + + fi_args->max_id = devid; + i = devid; + memcpy(fi_args->fsid, fs_devices_mnt->fsid, BTRFS_FSID_SIZE); close(fd); } |