]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/scrub.c
staging: nvec: drop owner assignment from platform_drivers
[karo-tx-linux.git] / fs / btrfs / scrub.c
index f4a41f37be229b555fb2e26993aff7055ee7fff1..efa08311382725c6770f3899033778ba8e3129ac 100644 (file)
@@ -137,7 +137,6 @@ struct scrub_ctx {
        int                     pages_per_rd_bio;
        u32                     sectorsize;
        u32                     nodesize;
-       u32                     leafsize;
 
        int                     is_dev_replace;
        struct scrub_wr_ctx     wr_ctx;
@@ -178,17 +177,12 @@ struct scrub_copy_nocow_ctx {
 struct scrub_warning {
        struct btrfs_path       *path;
        u64                     extent_item_size;
-       char                    *scratch_buf;
-       char                    *msg_buf;
        const char              *errstr;
        sector_t                sector;
        u64                     logical;
        struct btrfs_device     *dev;
-       int                     msg_bufsize;
-       int                     scratch_bufsize;
 };
 
-
 static void scrub_pending_bio_inc(struct scrub_ctx *sctx);
 static void scrub_pending_bio_dec(struct scrub_ctx *sctx);
 static void scrub_pending_trans_workers_inc(struct scrub_ctx *sctx);
@@ -438,7 +432,6 @@ struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev, int is_dev_replace)
        }
        sctx->first_free = 0;
        sctx->nodesize = dev->dev_root->nodesize;
-       sctx->leafsize = dev->dev_root->leafsize;
        sctx->sectorsize = dev->dev_root->sectorsize;
        atomic_set(&sctx->bios_in_flight, 0);
        atomic_set(&sctx->workers_pending, 0);
@@ -553,7 +546,6 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
        u64 ref_root;
        u32 item_size;
        u8 ref_level;
-       const int bufsize = 4096;
        int ret;
 
        WARN_ON(sblock->page_count < 1);
@@ -561,18 +553,13 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
        fs_info = sblock->sctx->dev_root->fs_info;
 
        path = btrfs_alloc_path();
+       if (!path)
+               return;
 
-       swarn.scratch_buf = kmalloc(bufsize, GFP_NOFS);
-       swarn.msg_buf = kmalloc(bufsize, GFP_NOFS);
        swarn.sector = (sblock->pagev[0]->physical) >> 9;
        swarn.logical = sblock->pagev[0]->logical;
        swarn.errstr = errstr;
        swarn.dev = NULL;
-       swarn.msg_bufsize = bufsize;
-       swarn.scratch_bufsize = bufsize;
-
-       if (!path || !swarn.scratch_buf || !swarn.msg_buf)
-               goto out;
 
        ret = extent_from_logical(fs_info, swarn.logical, path, &found_key,
                                  &flags);
@@ -613,8 +600,6 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
 
 out:
        btrfs_free_path(path);
-       kfree(swarn.scratch_buf);
-       kfree(swarn.msg_buf);
 }
 
 static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)
@@ -681,9 +666,9 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)
                        ret = -EIO;
                        goto out;
                }
-               fs_info = BTRFS_I(inode)->root->fs_info;
-               ret = repair_io_failure(fs_info, offset, PAGE_SIZE,
+               ret = repair_io_failure(inode, offset, PAGE_SIZE,
                                        fixup->logical, page,
+                                       offset - page_offset(page),
                                        fixup->mirror_num);
                unlock_page(page);
                corrected = !ret;
@@ -1361,6 +1346,16 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
        return;
 }
 
+static inline int scrub_check_fsid(u8 fsid[],
+                                  struct scrub_page *spage)
+{
+       struct btrfs_fs_devices *fs_devices = spage->dev->fs_devices;
+       int ret;
+
+       ret = memcmp(fsid, fs_devices->fsid, BTRFS_UUID_SIZE);
+       return !ret;
+}
+
 static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                                         struct scrub_block *sblock,
                                         int is_metadata, int have_csum,
@@ -1380,7 +1375,7 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                h = (struct btrfs_header *)mapped_buffer;
 
                if (sblock->pagev[0]->logical != btrfs_stack_header_bytenr(h) ||
-                   memcmp(h->fsid, fs_info->fsid, BTRFS_UUID_SIZE) ||
+                   !scrub_check_fsid(h->fsid, sblock->pagev[0]) ||
                    memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid,
                           BTRFS_UUID_SIZE)) {
                        sblock->header_error = 1;
@@ -1751,14 +1746,13 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock)
        if (sblock->pagev[0]->generation != btrfs_stack_header_generation(h))
                ++fail;
 
-       if (memcmp(h->fsid, fs_info->fsid, BTRFS_UUID_SIZE))
+       if (!scrub_check_fsid(h->fsid, sblock->pagev[0]))
                ++fail;
 
        if (memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid,
                   BTRFS_UUID_SIZE))
                ++fail;
 
-       WARN_ON(sctx->nodesize != sctx->leafsize);
        len = sctx->nodesize - BTRFS_CSUM_SIZE;
        mapped_size = PAGE_SIZE - BTRFS_CSUM_SIZE;
        p = ((u8 *)mapped_buffer) + BTRFS_CSUM_SIZE;
@@ -1791,8 +1785,6 @@ static int scrub_checksum_super(struct scrub_block *sblock)
 {
        struct btrfs_super_block *s;
        struct scrub_ctx *sctx = sblock->sctx;
-       struct btrfs_root *root = sctx->dev_root;
-       struct btrfs_fs_info *fs_info = root->fs_info;
        u8 calculated_csum[BTRFS_CSUM_SIZE];
        u8 on_disk_csum[BTRFS_CSUM_SIZE];
        struct page *page;
@@ -1817,7 +1809,7 @@ static int scrub_checksum_super(struct scrub_block *sblock)
        if (sblock->pagev[0]->generation != btrfs_super_generation(s))
                ++fail_gen;
 
-       if (memcmp(s->fsid, fs_info->fsid, BTRFS_UUID_SIZE))
+       if (!scrub_check_fsid(s->fsid, sblock->pagev[0]))
                ++fail_cor;
 
        len = BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE;
@@ -2196,7 +2188,6 @@ static int scrub_extent(struct scrub_ctx *sctx, u64 logical, u64 len,
                sctx->stat.data_bytes_scrubbed += len;
                spin_unlock(&sctx->stat_lock);
        } else if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
-               WARN_ON(sctx->nodesize != sctx->leafsize);
                blocksize = sctx->nodesize;
                spin_lock(&sctx->stat_lock);
                sctx->stat.tree_extents_scrubbed++;
@@ -2487,7 +2478,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
                        btrfs_item_key_to_cpu(l, &key, slot);
 
                        if (key.type == BTRFS_METADATA_ITEM_KEY)
-                               bytes = root->leafsize;
+                               bytes = root->nodesize;
                        else
                                bytes = key.offset;
 
@@ -2714,7 +2705,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
                if (found_key.objectid != scrub_dev->devid)
                        break;
 
-               if (btrfs_key_type(&found_key) != BTRFS_DEV_EXTENT_KEY)
+               if (found_key.type != BTRFS_DEV_EXTENT_KEY)
                        break;
 
                if (found_key.offset >= end)
@@ -2828,11 +2819,16 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
        if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
                return -EIO;
 
-       gen = root->fs_info->last_trans_committed;
+       /* Seed devices of a new filesystem has their own generation. */
+       if (scrub_dev->fs_devices != root->fs_info->fs_devices)
+               gen = scrub_dev->generation;
+       else
+               gen = root->fs_info->last_trans_committed;
 
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
                bytenr = btrfs_sb_offset(i);
-               if (bytenr + BTRFS_SUPER_INFO_SIZE > scrub_dev->total_bytes)
+               if (bytenr + BTRFS_SUPER_INFO_SIZE >
+                   scrub_dev->commit_total_bytes)
                        break;
 
                ret = scrub_pages(sctx, bytenr, BTRFS_SUPER_INFO_SIZE, bytenr,
@@ -2910,17 +2906,6 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
        if (btrfs_fs_closing(fs_info))
                return -EINVAL;
 
-       /*
-        * check some assumptions
-        */
-       if (fs_info->chunk_root->nodesize != fs_info->chunk_root->leafsize) {
-               btrfs_err(fs_info,
-                          "scrub: size assumption nodesize == leafsize (%d == %d) fails",
-                      fs_info->chunk_root->nodesize,
-                      fs_info->chunk_root->leafsize);
-               return -EINVAL;
-       }
-
        if (fs_info->chunk_root->nodesize > BTRFS_STRIPE_LEN) {
                /*
                 * in this case scrub is unable to calculate the checksum