btrfs-progs: check: original mode: Check inline extent size
authorQu Wenruo <wqu@suse.com>
Tue, 20 Mar 2018 06:42:26 +0000 (14:42 +0800)
committerDavid Sterba <dsterba@suse.com>
Fri, 30 Mar 2018 20:15:54 +0000 (22:15 +0200)
For inline compressed file extent, kernel doesn't allow inline extent
ram size larger than sector size and on-disk inline extent size should
not exceed BTRFS_MAX_INLINE_DATA_SIZE().

For inline uncompressed file extent, kernel doesn't allow inline extent
ram and on-disk size larger than either BTRFS_MAX_INLINE_DATA_SIZE() or
sector size.

Check it in original mode.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
check/main.c
check/mode-original.h

index 5fa09ab..b476e07 100644 (file)
@@ -560,6 +560,8 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
                fprintf(stderr, ", bad file extent");
        if (errors & I_ERR_FILE_EXTENT_OVERLAP)
                fprintf(stderr, ", file extent overlap");
+       if (errors & I_ERR_FILE_EXTENT_TOO_LARGE)
+               fprintf(stderr, ", inline file extent too large");
        if (errors & I_ERR_FILE_EXTENT_DISCOUNT)
                fprintf(stderr, ", file extent discount");
        if (errors & I_ERR_DIR_ISIZE_WRONG)
@@ -1433,6 +1435,8 @@ static int process_file_extent(struct btrfs_root *root,
        u64 disk_bytenr = 0;
        u64 extent_offset = 0;
        u64 mask = root->fs_info->sectorsize - 1;
+       u32 max_inline_size = min_t(u32, mask,
+                               BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info));
        int extent_type;
        int ret;
 
@@ -1458,9 +1462,21 @@ static int process_file_extent(struct btrfs_root *root,
        extent_type = btrfs_file_extent_type(eb, fi);
 
        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+               u8 compression = btrfs_file_extent_compression(eb, fi);
+               struct btrfs_item *item = btrfs_item_nr(slot);
+
                num_bytes = btrfs_file_extent_inline_len(eb, slot, fi);
                if (num_bytes == 0)
                        rec->errors |= I_ERR_BAD_FILE_EXTENT;
+               if (compression) {
+                       if (btrfs_file_extent_inline_item_len(eb, item) >
+                           max_inline_size ||
+                           num_bytes > root->fs_info->sectorsize)
+                               rec->errors |= I_ERR_FILE_EXTENT_TOO_LARGE;
+               } else {
+                       if (num_bytes > max_inline_size)
+                               rec->errors |= I_ERR_FILE_EXTENT_TOO_LARGE;
+               }
                rec->found_size += num_bytes;
                num_bytes = (num_bytes + mask) & ~mask;
        } else if (extent_type == BTRFS_FILE_EXTENT_REG ||
index f859af4..368de69 100644 (file)
@@ -185,6 +185,7 @@ struct file_extent_hole {
 #define I_ERR_SOME_CSUM_MISSING                (1 << 12)
 #define I_ERR_LINK_COUNT_WRONG         (1 << 13)
 #define I_ERR_FILE_EXTENT_ORPHAN       (1 << 14)
+#define I_ERR_FILE_EXTENT_TOO_LARGE    (1 << 15)
 
 struct inode_record {
        struct list_head backrefs;