Btrfs-progs: corrupt-block: add the ability to remove csums
authorJosef Bacik <jbacik@fb.com>
Tue, 19 May 2015 14:21:04 +0000 (10:21 -0400)
committerDavid Sterba <dsterba@suse.cz>
Tue, 26 May 2015 14:38:32 +0000 (16:38 +0200)
Sometimes we need to test what happens when we're missing a csum for a range, so
add an option to btrfs-corrupt-block to be able to remove a csum range.  Thanks,

Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
btrfs-corrupt-block.c

index cf92673..6c335b9 100644 (file)
@@ -110,6 +110,9 @@ static void print_usage(void)
        fprintf(stderr, "\t-D Corrupt a dir item, must specify key and field\n");
        fprintf(stderr, "\t-d Delete this item (must specify -K)\n");
        fprintf(stderr, "\t-r Operate on this root (only works with -d)\n");
+       fprintf(stderr, "\t-C Delete a csum for the specified bytenr.  When "
+               "used with -b it'll delete that many bytes, otherwise it's "
+               "just sectorsize\n");
        exit(1);
 }
 
@@ -843,6 +846,26 @@ out:
        return ret;
 }
 
+static int delete_csum(struct btrfs_root *root, u64 bytenr, u64 bytes)
+{
+       struct btrfs_trans_handle *trans;
+       int ret;
+
+       root = root->fs_info->csum_root;
+       trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               fprintf(stderr, "Couldn't start transaction %ld\n",
+                       PTR_ERR(trans));
+               return PTR_ERR(trans);
+       }
+
+       ret = btrfs_del_csums(trans, root, bytenr, bytes);
+       if (ret)
+               fprintf(stderr, "Error deleting csums %d\n", ret);
+       btrfs_commit_transaction(trans, root);
+       return ret;
+}
+
 /* corrupt item using NO cow.
  * Because chunk recover will recover based on whole partition scaning,
  * If using COW, chunk recover will use the old item to recover,
@@ -1009,6 +1032,7 @@ int main(int ac, char **av)
        u64 inode = 0;
        u64 file_extent = (u64)-1;
        u64 root_objectid = 0;
+       u64 csum_bytenr = 0;
        char field[FIELD_BUF_LEN];
 
        field[0] = '\0';
@@ -1036,10 +1060,11 @@ int main(int ac, char **av)
                        { "dir-item", no_argument, NULL, 'D'},
                        { "delete", no_argument, NULL, 'd'},
                        { "root", no_argument, NULL, 'r'},
+                       { "csum", required_argument, NULL, 'C'},
                        { NULL, 0, NULL, 0 }
                };
 
-               c = getopt_long(ac, av, "l:c:b:eEkuUi:f:x:m:K:IDdr:",
+               c = getopt_long(ac, av, "l:c:b:eEkuUi:f:x:m:K:IDdr:C:",
                                long_options, NULL);
                if (c < 0)
                        break;
@@ -1103,6 +1128,9 @@ int main(int ac, char **av)
                        case 'r':
                                root_objectid = arg_strtou64(optarg);
                                break;
+                       case 'C':
+                               csum_bytenr = arg_strtou64(optarg);
+                               break;
                        default:
                                print_usage();
                }
@@ -1205,6 +1233,10 @@ int main(int ac, char **av)
                ret = corrupt_dir_item(root, &key, field);
                goto out_close;
        }
+       if (csum_bytenr) {
+               ret = delete_csum(root, csum_bytenr, bytes);
+               goto out_close;
+       }
        if (corrupt_item) {
                if (!key.objectid)
                        print_usage();