]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
btrfs: use btrfs_dev_name() helper to handle missing devices better
authorQu Wenruo <wqu@suse.com>
Sun, 13 Nov 2022 01:32:07 +0000 (09:32 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 5 Dec 2022 17:00:57 +0000 (18:00 +0100)
[BUG]
If dev-replace failed to re-construct its data/metadata, the kernel
message would be incorrect for the missing device:

 BTRFS info (device dm-1): dev_replace from <missing disk> (devid 2) to /dev/mapper/test-scratch2 started
 BTRFS error (device dm-1): failed to rebuild valid logical 38862848 for dev (efault)

Note the above "dev (efault)" of the second line.
While the first line is properly reporting "<missing disk>".

[CAUSE]
Although dev-replace is using btrfs_dev_name(), the heavy lifting work
is still done by scrub (scrub is reused by both dev-replace and regular
scrub).

Unfortunately scrub code never uses btrfs_dev_name() helper, as it's
only declared locally inside dev-replace.c.

[FIX]
Fix the output by:

- Move the btrfs_dev_name() helper to volumes.h

- Use btrfs_dev_name() to replace open-coded rcu_str_deref() calls
  Only zoned code is not touched, as I'm not familiar with degraded
  zoned code.

- Constify return value and parameter

Now the output looks pretty sane:

 BTRFS info (device dm-1): dev_replace from <missing disk> (devid 2) to /dev/mapper/test-scratch2 started
 BTRFS error (device dm-1): failed to rebuild valid logical 38862848 for dev <missing disk>

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/check-integrity.c
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/ioctl.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h

index 7ff0703ef3e4670520731bfd3e1a05541dcabf35..82e49d985019f11ce050b1c1e169b25bc933da86 100644 (file)
@@ -757,7 +757,7 @@ static int btrfsic_process_superblock_dev_mirror(
                        btrfs_info_in_rcu(fs_info,
                        "new initial S-block (bdev %p, %s) @%llu (%pg/%llu/%d)",
                                     superblock_bdev,
-                                    rcu_str_deref(device->name), dev_bytenr,
+                                    btrfs_dev_name(device), dev_bytenr,
                                     dev_state->bdev, dev_bytenr,
                                     superblock_mirror_num);
                list_add(&superblock_tmp->all_blocks_node,
index 9c4a8649a0f4a68233028260a91b4da301e6ccb4..78696d331639bdab8d2e70c49cb289b2f33e384d 100644 (file)
@@ -18,7 +18,6 @@
 #include "volumes.h"
 #include "async-thread.h"
 #include "check-integrity.h"
-#include "rcu-string.h"
 #include "dev-replace.h"
 #include "sysfs.h"
 #include "zoned.h"
@@ -451,14 +450,6 @@ out:
        return ret;
 }
 
-static char* btrfs_dev_name(struct btrfs_device *device)
-{
-       if (!device || test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
-               return "<missing disk>";
-       else
-               return rcu_str_deref(device->name);
-}
-
 static int mark_block_group_to_copy(struct btrfs_fs_info *fs_info,
                                    struct btrfs_device *src_dev)
 {
@@ -674,7 +665,7 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
                      "dev_replace from %s (devid %llu) to %s started",
                      btrfs_dev_name(src_device),
                      src_device->devid,
-                     rcu_str_deref(tgt_device->name));
+                     btrfs_dev_name(tgt_device));
 
        /*
         * from now on, the writes to the srcdev are all duplicated to
@@ -933,7 +924,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
                                 "btrfs_scrub_dev(%s, %llu, %s) failed %d",
                                 btrfs_dev_name(src_device),
                                 src_device->devid,
-                                rcu_str_deref(tgt_device->name), scrub_ret);
+                                btrfs_dev_name(tgt_device), scrub_ret);
 error:
                up_write(&dev_replace->rwsem);
                mutex_unlock(&fs_info->chunk_mutex);
@@ -951,7 +942,7 @@ error:
                          "dev_replace from %s (devid %llu) to %s finished",
                          btrfs_dev_name(src_device),
                          src_device->devid,
-                         rcu_str_deref(tgt_device->name));
+                         btrfs_dev_name(tgt_device));
        clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &tgt_device->dev_state);
        tgt_device->devid = src_device->devid;
        src_device->devid = BTRFS_DEV_REPLACE_DEVID;
index 559e7f3d727e1c4e3078fa6868aa89a28e3b5d0b..91a088210e5ad1944f8f82531619cfc3acb6a647 100644 (file)
@@ -3944,7 +3944,7 @@ static void btrfs_end_super_write(struct bio *bio)
                if (bio->bi_status) {
                        btrfs_warn_rl_in_rcu(device->fs_info,
                                "lost page write due to IO error on %s (%d)",
-                               rcu_str_deref(device->name),
+                               btrfs_dev_name(device),
                                blk_status_to_errno(bio->bi_status));
                        ClearPageUptodate(page);
                        SetPageError(page);
index 10cc757a602b05b88b47c094a6491eebc700e63c..17f599027c3dea3d0d89dc101c09304d2823a828 100644 (file)
@@ -6048,7 +6048,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed)
                        btrfs_warn_in_rcu(fs_info,
 "ignoring attempt to trim beyond device size: offset %llu length %llu device %s device size %llu",
                                          start, end - start + 1,
-                                         rcu_str_deref(device->name),
+                                         btrfs_dev_name(device),
                                          device->total_bytes);
                        mutex_unlock(&fs_info->chunk_mutex);
                        ret = 0;
index 704ae7c088679824fd2cafd4b0ee76489e025004..65ba5c3658cf636964e07b51942478f278f2d102 100644 (file)
@@ -611,8 +611,7 @@ static int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
 
        btrfs_info_rl_in_rcu(fs_info,
                "read error corrected: ino %llu off %llu (dev %s sector %llu)",
-                                 ino, start,
-                                 rcu_str_deref(dev->name), sector);
+                            ino, start, btrfs_dev_name(dev), sector);
        ret = 0;
 
 out_bio_uninit:
index 7a9e697d9931e7d0a92b2f7bc31bf9bd310a55f8..bed74a3ff5744aff96477e9c8de3a982f2d32b7d 100644 (file)
@@ -1228,7 +1228,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
        if (ret == 0 && new_size != old_size)
                btrfs_info_in_rcu(fs_info,
                        "resize device %s (devid %llu) from %llu to %llu",
-                       rcu_str_deref(device->name), device->devid,
+                       btrfs_dev_name(device), device->devid,
                        old_size, new_size);
 out_finish:
        btrfs_exclop_finish(fs_info);
@@ -2860,7 +2860,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
        di_args->total_bytes = btrfs_device_get_total_bytes(dev);
        memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
        if (dev->name) {
-               strncpy(di_args->path, rcu_str_deref(dev->name),
+               strncpy(di_args->path, btrfs_dev_name(dev),
                                sizeof(di_args->path) - 1);
                di_args->path[sizeof(di_args->path) - 1] = 0;
        } else {
index 288a97992aa4273c460e9afd9ffb611a4bab7118..0ce5b773867f8ad1afdfba6082f2cee3f28f813f 100644 (file)
@@ -17,7 +17,6 @@
 #include "extent_io.h"
 #include "dev-replace.h"
 #include "check-integrity.h"
-#include "rcu-string.h"
 #include "raid56.h"
 #include "block-group.h"
 #include "zoned.h"
@@ -877,7 +876,7 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 num_bytes,
                btrfs_warn_in_rcu(fs_info,
 "%s at logical %llu on dev %s, physical %llu, root %llu, inode %llu, offset %llu, length %u, links %u (path: %s)",
                                  swarn->errstr, swarn->logical,
-                                 rcu_str_deref(swarn->dev->name),
+                                 btrfs_dev_name(swarn->dev),
                                  swarn->physical,
                                  root, inum, offset,
                                  fs_info->sectorsize, nlink,
@@ -891,7 +890,7 @@ err:
        btrfs_warn_in_rcu(fs_info,
                          "%s at logical %llu on dev %s, physical %llu, root %llu, inode %llu, offset %llu: path resolving failed with ret=%d",
                          swarn->errstr, swarn->logical,
-                         rcu_str_deref(swarn->dev->name),
+                         btrfs_dev_name(swarn->dev),
                          swarn->physical,
                          root, inum, offset, ret);
 
@@ -922,8 +921,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
        /* Super block error, no need to search extent tree. */
        if (sblock->sectors[0]->flags & BTRFS_EXTENT_FLAG_SUPER) {
                btrfs_warn_in_rcu(fs_info, "%s on device %s, physical %llu",
-                       errstr, rcu_str_deref(dev->name),
-                       sblock->physical);
+                       errstr, btrfs_dev_name(dev), sblock->physical);
                return;
        }
        path = btrfs_alloc_path();
@@ -954,7 +952,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
                        btrfs_warn_in_rcu(fs_info,
 "%s at logical %llu on dev %s, physical %llu: metadata %s (level %d) in tree %llu",
                                errstr, swarn.logical,
-                               rcu_str_deref(dev->name),
+                               btrfs_dev_name(dev),
                                swarn.physical,
                                ref_level ? "node" : "leaf",
                                ret < 0 ? -1 : ref_level,
@@ -1377,7 +1375,7 @@ corrected_error:
                        spin_unlock(&sctx->stat_lock);
                        btrfs_err_rl_in_rcu(fs_info,
                                "fixed up error at logical %llu on dev %s",
-                               logical, rcu_str_deref(dev->name));
+                               logical, btrfs_dev_name(dev));
                }
        } else {
 did_not_correct_error:
@@ -1386,7 +1384,7 @@ did_not_correct_error:
                spin_unlock(&sctx->stat_lock);
                btrfs_err_rl_in_rcu(fs_info,
                        "unable to fixup (regular) error at logical %llu on dev %s",
-                       logical, rcu_str_deref(dev->name));
+                       logical, btrfs_dev_name(dev));
        }
 
 out:
@@ -2332,14 +2330,14 @@ static void scrub_missing_raid56_worker(struct work_struct *work)
                spin_unlock(&sctx->stat_lock);
                btrfs_err_rl_in_rcu(fs_info,
                        "IO error rebuilding logical %llu for dev %s",
-                       logical, rcu_str_deref(dev->name));
+                       logical, btrfs_dev_name(dev));
        } else if (sblock->header_error || sblock->checksum_error) {
                spin_lock(&sctx->stat_lock);
                sctx->stat.uncorrectable_errors++;
                spin_unlock(&sctx->stat_lock);
                btrfs_err_rl_in_rcu(fs_info,
                        "failed to rebuild valid logical %llu for dev %s",
-                       logical, rcu_str_deref(dev->name));
+                       logical, btrfs_dev_name(dev));
        } else {
                scrub_write_block_to_dev_replace(sblock);
        }
@@ -4303,7 +4301,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
                btrfs_err_in_rcu(fs_info,
                        "scrub on devid %llu: filesystem on %s is not writable",
-                                devid, rcu_str_deref(dev->name));
+                                devid, btrfs_dev_name(dev));
                ret = -EROFS;
                goto out;
        }
index d54bfec8e5064d9825a9b911cb4864ccd90b21b8..ea83dd9f735a67bed3f01c935d2cc88d03ca5ef7 100644 (file)
@@ -2336,7 +2336,7 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
         * the end of RCU grace period.
         */
        rcu_read_lock();
-       seq_escape(m, rcu_str_deref(fs_info->fs_devices->latest_dev->name), " \t\n\\");
+       seq_escape(m, btrfs_dev_name(fs_info->fs_devices->latest_dev), " \t\n\\");
        rcu_read_unlock();
 
        return 0;
index 49d6e79d4343bf7386d4a0ecc7141e6665d6d230..2d0950a17f48e153fd207a493bda7a309a490273 100644 (file)
@@ -941,7 +941,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                        }
                        btrfs_info_in_rcu(NULL,
        "devid %llu device path %s changed to %s scanned by %s (%d)",
-                                         devid, rcu_str_deref(device->name),
+                                         devid, btrfs_dev_name(device),
                                          path, current->comm,
                                          task_pid_nr(current));
                }
@@ -2101,7 +2101,7 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info,
        if (btrfs_pinned_by_swapfile(fs_info, device)) {
                btrfs_warn_in_rcu(fs_info,
                  "cannot remove device %s (devid %llu) due to active swapfile",
-                                 rcu_str_deref(device->name), device->devid);
+                                 btrfs_dev_name(device), device->devid);
                return -ETXTBSY;
        }
 
@@ -6827,7 +6827,7 @@ static void btrfs_submit_dev_bio(struct btrfs_device *dev, struct bio *bio)
        btrfs_debug_in_rcu(dev->fs_info,
        "%s: rw %d 0x%x, sector=%llu, dev=%lu (%s id %llu), size=%u",
                __func__, bio_op(bio), bio->bi_opf, bio->bi_iter.bi_sector,
-               (unsigned long)dev->bdev->bd_dev, rcu_str_deref(dev->name),
+               (unsigned long)dev->bdev->bd_dev, btrfs_dev_name(dev),
                dev->devid, bio->bi_iter.bi_size);
 
        btrfsic_check_bio(bio);
@@ -7908,7 +7908,7 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
        if (ret < 0) {
                btrfs_warn_in_rcu(fs_info,
                        "error %d while searching for dev_stats item for device %s",
-                             ret, rcu_str_deref(device->name));
+                                 ret, btrfs_dev_name(device));
                goto out;
        }
 
@@ -7919,7 +7919,7 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
                if (ret != 0) {
                        btrfs_warn_in_rcu(fs_info,
                                "delete too small dev_stats item for device %s failed %d",
-                                     rcu_str_deref(device->name), ret);
+                                         btrfs_dev_name(device), ret);
                        goto out;
                }
                ret = 1;
@@ -7933,7 +7933,7 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
                if (ret < 0) {
                        btrfs_warn_in_rcu(fs_info,
                                "insert dev_stats item for device %s failed %d",
-                               rcu_str_deref(device->name), ret);
+                               btrfs_dev_name(device), ret);
                        goto out;
                }
        }
@@ -7998,7 +7998,7 @@ void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index)
                return;
        btrfs_err_rl_in_rcu(dev->fs_info,
                "bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u",
-                          rcu_str_deref(dev->name),
+                          btrfs_dev_name(dev),
                           btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS),
                           btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS),
                           btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS),
@@ -8018,7 +8018,7 @@ static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev)
 
        btrfs_info_in_rcu(dev->fs_info,
                "bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u",
-              rcu_str_deref(dev->name),
+              btrfs_dev_name(dev),
               btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS),
               btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS),
               btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS),
index efa6a3d48cd8dbd5bec8f7adbda09924dc9edde7..2c90e50c460a30635045d8d62e2495fa61d32e08 100644 (file)
@@ -12,6 +12,7 @@
 #include "async-thread.h"
 #include "messages.h"
 #include "disk-io.h"
+#include "rcu-string.h"
 
 #define BTRFS_MAX_DATA_CHUNK_SIZE      (10ULL * SZ_1G)
 
@@ -770,6 +771,14 @@ static inline void btrfs_dev_stat_set(struct btrfs_device *dev,
        atomic_inc(&dev->dev_stats_ccnt);
 }
 
+static inline const char *btrfs_dev_name(const struct btrfs_device *device)
+{
+       if (!device || test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
+               return "<missing disk>";
+       else
+               return rcu_str_deref(device->name);
+}
+
 void btrfs_commit_device_sizes(struct btrfs_transaction *trans);
 
 struct list_head * __attribute_const__ btrfs_get_fs_uuids(void);