To corrupt holes/prealloc/inline extents, we need to mess with
extent data items. This patch makes it possible to modify
disk_bytenr with a specific value (useful for hole corruptions)
and to modify the type field (useful for prealloc corruptions)

Signed-off-by: Boris Burkov <bo...@bur.io>
---
 btrfs-corrupt-block.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
index bf1ce9c5..40d8ad8e 100644
--- a/btrfs-corrupt-block.c
+++ b/btrfs-corrupt-block.c
@@ -323,6 +323,7 @@ enum btrfs_inode_field {
 
 enum btrfs_file_extent_field {
        BTRFS_FILE_EXTENT_DISK_BYTENR,
+       BTRFS_FILE_EXTENT_TYPE,
        BTRFS_FILE_EXTENT_BAD,
 };
 
@@ -377,6 +378,8 @@ static enum btrfs_file_extent_field 
convert_file_extent_field(char *field)
 {
        if (!strncmp(field, "disk_bytenr", FIELD_BUF_LEN))
                return BTRFS_FILE_EXTENT_DISK_BYTENR;
+       if (!strncmp(field, "type", FIELD_BUF_LEN))
+               return BTRFS_FILE_EXTENT_TYPE;
        return BTRFS_FILE_EXTENT_BAD;
 }
 
@@ -673,14 +676,14 @@ out:
 
 static int corrupt_file_extent(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root, u64 inode, u64 extent,
-                              char *field)
+                              char *field, u64 bogus)
 {
        struct btrfs_file_extent_item *fi;
        struct btrfs_path *path;
        struct btrfs_key key;
        enum btrfs_file_extent_field corrupt_field;
-       u64 bogus;
        u64 orig;
+       u8 bogus_type = bogus;
        int ret = 0;
 
        corrupt_field = convert_file_extent_field(field);
@@ -712,9 +715,18 @@ static int corrupt_file_extent(struct btrfs_trans_handle 
*trans,
        switch (corrupt_field) {
        case BTRFS_FILE_EXTENT_DISK_BYTENR:
                orig = btrfs_file_extent_disk_bytenr(path->nodes[0], fi);
-               bogus = generate_u64(orig);
+               if (bogus == (u64)-1)
+                       bogus = generate_u64(orig);
                btrfs_set_file_extent_disk_bytenr(path->nodes[0], fi, bogus);
                break;
+       case BTRFS_FILE_EXTENT_TYPE:
+               if (bogus == (u64)-1) {
+                       fprintf(stderr, "Specify a new extent type value 
(-v)\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+               btrfs_set_file_extent_type(path->nodes[0], fi, bogus_type);
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -1394,9 +1406,9 @@ int main(int argc, char **argv)
                        printf("corrupting inode\n");
                        ret = corrupt_inode(trans, root, inode, field);
                } else {
-                       printf("corrupting file extent\n");
                        ret = corrupt_file_extent(trans, root, inode,
-                                                 file_extent, field);
+                                                 file_extent, field,
+                                                 bogus_value);
                }
                btrfs_commit_transaction(trans, root);
                goto out_close;
-- 
2.24.1

Reply via email to