X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=check%2Fmain.c;h=891a6d797756c53f4e9f717d901caec25e91360f;hb=7cdd58b2e92863f055c70ef7134d3a70760473c7;hp=98e24afb42b51e58f12a9db984a31c96b3fa6b24;hpb=b8d706e58e69a4782cae111049636e439db86f44;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/check/main.c b/check/main.c index 98e24af..891a6d7 100644 --- a/check/main.c +++ b/check/main.c @@ -43,9 +43,9 @@ #include "kernel-shared/ulist.h" #include "hash.h" #include "help.h" -#include "check/original.h" -#include "check/lowmem.h" -#include "check/common.h" +#include "check/mode-common.h" +#include "check/mode-original.h" +#include "check/mode-lowmem.h" enum task_position { TASK_EXTENTS, @@ -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 || @@ -1511,8 +1527,15 @@ static int process_file_extent(struct btrfs_root *root, if (found < num_bytes) rec->some_csum_missing = 1; } else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { - if (found > 0) - rec->errors |= I_ERR_ODD_CSUM_ITEM; + if (found > 0) { + ret = check_prealloc_extent_written(root->fs_info, + disk_bytenr, + num_bytes); + if (ret < 0) + return ret; + if (ret == 0) + rec->errors |= I_ERR_ODD_CSUM_ITEM; + } } } return 0; @@ -1720,14 +1743,13 @@ static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, path->slots[i]++; *level = i; return 0; - } else { - free_extent_buffer(path->nodes[*level]); - path->nodes[*level] = NULL; - BUG_ON(*level > wc->active_node); - if (*level == wc->active_node) - leave_shared_node(root, wc, *level); - *level = i + 1; } + free_extent_buffer(path->nodes[*level]); + path->nodes[*level] = NULL; + BUG_ON(*level > wc->active_node); + if (*level == wc->active_node) + leave_shared_node(root, wc, *level); + *level = i + 1; } return 1; } @@ -1790,7 +1812,7 @@ static int repair_inode_isize(struct btrfs_trans_handle *trans, btrfs_set_inode_size(path->nodes[0], ei, rec->found_size); btrfs_mark_buffer_dirty(path->nodes[0]); rec->errors &= ~I_ERR_DIR_ISIZE_WRONG; - printf("reset isize for dir %Lu root %Lu\n", rec->ino, + printf("reset isize for dir %llu root %llu\n", rec->ino, root->root_key.objectid); out: btrfs_release_path(path); @@ -3465,7 +3487,7 @@ static int do_check_fs_roots(struct btrfs_fs_info *fs_info, if (!ctx.progress_enabled) fprintf(stderr, "checking fs roots\n"); if (check_mode == CHECK_MODE_LOWMEM) - ret = check_fs_roots_v2(fs_info); + ret = check_fs_roots_lowmem(fs_info); else ret = check_fs_roots(fs_info, root_cache); @@ -3488,22 +3510,21 @@ static int all_backpointers_checked(struct extent_record *rec, int print_errs) goto out; if (back->is_data) { dback = to_data_backref(back); - fprintf(stderr, "Data backref %llu %s %llu" - " owner %llu offset %llu num_refs %lu" - " not found in extent tree\n", + fprintf(stderr, +"data backref %llu %s %llu owner %llu offset %llu num_refs %lu not found in extent tree\n", (unsigned long long)rec->start, back->full_backref ? "parent" : "root", back->full_backref ? - (unsigned long long)dback->parent: + (unsigned long long)dback->parent : (unsigned long long)dback->root, (unsigned long long)dback->owner, (unsigned long long)dback->offset, (unsigned long)dback->num_refs); } else { tback = to_tree_backref(back); - fprintf(stderr, "Tree backref %llu parent %llu" - " root %llu not found in extent tree\n", + fprintf(stderr, +"tree backref %llu parent %llu root %llu not found in extent tree\n", (unsigned long long)rec->start, (unsigned long long)tback->parent, (unsigned long long)tback->root); @@ -3514,7 +3535,8 @@ static int all_backpointers_checked(struct extent_record *rec, int print_errs) if (!print_errs) goto out; tback = to_tree_backref(back); - fprintf(stderr, "Backref %llu %s %llu not referenced back %p\n", + fprintf(stderr, + "backref %llu %s %llu not referenced back %p\n", (unsigned long long)rec->start, back->full_backref ? "parent" : "root", back->full_backref ? @@ -3527,26 +3549,25 @@ static int all_backpointers_checked(struct extent_record *rec, int print_errs) err = 1; if (!print_errs) goto out; - fprintf(stderr, "Incorrect local backref count" - " on %llu %s %llu owner %llu" - " offset %llu found %u wanted %u back %p\n", + fprintf(stderr, +"incorrect local backref count on %llu %s %llu owner %llu offset %llu found %u wanted %u back %p\n", (unsigned long long)rec->start, back->full_backref ? "parent" : "root", back->full_backref ? - (unsigned long long)dback->parent: + (unsigned long long)dback->parent : (unsigned long long)dback->root, (unsigned long long)dback->owner, (unsigned long long)dback->offset, - dback->found_ref, dback->num_refs, back); + dback->found_ref, dback->num_refs, + back); } if (dback->disk_bytenr != rec->start) { err = 1; if (!print_errs) goto out; - fprintf(stderr, "Backref disk bytenr does not" - " match extent record, bytenr=%llu, " - "ref bytenr=%llu\n", + fprintf(stderr, +"backref disk bytenr does not match extent record, bytenr=%llu, ref bytenr=%llu\n", (unsigned long long)rec->start, (unsigned long long)dback->disk_bytenr); } @@ -3555,9 +3576,8 @@ static int all_backpointers_checked(struct extent_record *rec, int print_errs) err = 1; if (!print_errs) goto out; - fprintf(stderr, "Backref bytes do not match " - "extent backref, bytenr=%llu, ref " - "bytes=%llu, backref bytes=%llu\n", + fprintf(stderr, +"backref bytes do not match extent backref, bytenr=%llu, ref bytes=%llu, backref bytes=%llu\n", (unsigned long long)rec->start, (unsigned long long)rec->nr, (unsigned long long)dback->bytes); @@ -3574,8 +3594,8 @@ static int all_backpointers_checked(struct extent_record *rec, int print_errs) err = 1; if (!print_errs) goto out; - fprintf(stderr, "Incorrect global backref count " - "on %llu found %llu wanted %llu\n", + fprintf(stderr, + "incorrect global backref count on %llu found %llu wanted %llu\n", (unsigned long long)rec->start, (unsigned long long)found, (unsigned long long)rec->refs); @@ -3745,6 +3765,7 @@ static int swap_values(struct btrfs_root *root, struct btrfs_path *path, sizeof(struct btrfs_key_ptr)); if (slot == 0) { struct btrfs_disk_key key; + btrfs_node_key(buf, &key, 0); btrfs_fixup_low_keys(root, path, &key, btrfs_header_level(buf) + 1); @@ -3877,8 +3898,8 @@ again: ret = delete_bogus_item(root, path, buf, i); if (!ret) goto again; - fprintf(stderr, "item is off the end of the " - "leaf, can't fix\n"); + fprintf(stderr, + "item is off the end of the leaf, can't fix\n"); ret = -EIO; break; } @@ -4066,7 +4087,7 @@ static struct tree_backref *find_tree_backref(struct extent_record *rec, struct extent_backref *node; struct tree_backref *back; - while(cur != &rec->backrefs) { + while (cur != &rec->backrefs) { node = to_extent_backref(cur); cur = cur->next; if (node->is_data) @@ -4118,7 +4139,7 @@ static struct data_backref *find_data_backref(struct extent_record *rec, struct extent_backref *node; struct data_backref *back; - while(cur != &rec->backrefs) { + while (cur != &rec->backrefs) { node = to_extent_backref(cur); cur = cur->next; if (!node->is_data) @@ -4344,12 +4365,13 @@ static int add_extent_rec(struct cache_tree *extent_cache, if (tmpl->extent_item_refs && !dup) { if (rec->extent_item_refs) { - fprintf(stderr, "block %llu rec " - "extent_item_refs %llu, passed %llu\n", + fprintf(stderr, + "block %llu rec extent_item_refs %llu, passed %llu\n", (unsigned long long)tmpl->start, (unsigned long long) rec->extent_item_refs, - (unsigned long long)tmpl->extent_item_refs); + (unsigned long long) + tmpl->extent_item_refs); } rec->extent_item_refs = tmpl->extent_item_refs; } @@ -4433,8 +4455,8 @@ static int add_tree_backref(struct cache_tree *extent_cache, u64 bytenr, if (found_ref) { if (back->node.found_ref) { - fprintf(stderr, "Extent back ref already exists " - "for %llu parent %llu root %llu \n", + fprintf(stderr, + "Extent back ref already exists for %llu parent %llu root %llu\n", (unsigned long long)bytenr, (unsigned long long)parent, (unsigned long long)root); @@ -4442,8 +4464,8 @@ static int add_tree_backref(struct cache_tree *extent_cache, u64 bytenr, back->node.found_ref = 1; } else { if (back->node.found_extent_tree) { - fprintf(stderr, "Extent back ref already exists " - "for %llu parent %llu root %llu \n", + fprintf(stderr, + "extent back ref already exists for %llu parent %llu root %llu\n", (unsigned long long)bytenr, (unsigned long long)parent, (unsigned long long)root); @@ -4530,9 +4552,8 @@ static int add_data_backref(struct cache_tree *extent_cache, u64 bytenr, rec->owner_ref_checked = 1; } else { if (back->node.found_extent_tree) { - fprintf(stderr, "Extent back ref already exists " - "for %llu parent %llu root %llu " - "owner %llu offset %llu num_refs %lu\n", + fprintf(stderr, +"Extent back ref already exists for %llu parent %llu root %llu owner %llu offset %llu num_refs %lu\n", (unsigned long long)bytenr, (unsigned long long)parent, (unsigned long long)root, @@ -4555,6 +4576,7 @@ static int add_pending(struct cache_tree *pending, struct cache_tree *seen, u64 bytenr, u32 size) { int ret; + ret = add_cache_extent(seen, bytenr, size); if (ret) return ret; @@ -4588,17 +4610,17 @@ static int pick_next_pending(struct cache_tree *pending, cache = search_cache_extent(nodes, 0); if (!cache) { - cache = search_cache_extent(pending, 0); - if (!cache) - return 0; - ret = 0; - do { - bits[ret].start = cache->start; - bits[ret].size = cache->size; - cache = next_cache_extent(cache); - ret++; - } while (cache && ret < bits_nr); - return ret; + cache = search_cache_extent(pending, 0); + if (!cache) + return 0; + ret = 0; + do { + bits[ret].start = cache->start; + bits[ret].size = cache->size; + cache = next_cache_extent(cache); + ret++; + } while (cache && ret < bits_nr); + return ret; } ret = 0; @@ -4612,8 +4634,9 @@ static int pick_next_pending(struct cache_tree *pending, if (bits_nr - ret > 8) { u64 lookup = bits[0].start + bits[0].size; struct cache_extent *next; + next = search_cache_extent(pending, lookup); - while(next) { + while (next) { if (next->start - lookup > 32768) break; bits[ret].start = next->start; @@ -5004,6 +5027,7 @@ static int process_extent_item(struct btrfs_root *root, if (item_size < sizeof(*ei)) { #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 struct btrfs_extent_item_v0 *ei0; + if (item_size != sizeof(*ei0)) { error( "invalid extent item format: ITEM[%llu %u %llu] leaf: %llu slot: %d", @@ -5098,7 +5122,8 @@ static int process_extent_item(struct btrfs_root *root, 0, num_bytes); break; default: - fprintf(stderr, "corrupt extent record: key %Lu %u %Lu\n", + fprintf(stderr, + "corrupt extent record: key [%llu,%u,%llu]\n", key.objectid, key.type, num_bytes); goto out; } @@ -5181,19 +5206,19 @@ static int check_cache_range(struct btrfs_root *root, entry = btrfs_find_free_space(cache->free_space_ctl, offset, bytes); if (!entry) { - fprintf(stderr, "There is no free space entry for %Lu-%Lu\n", + fprintf(stderr, "there is no free space entry for %llu-%llu\n", offset, offset+bytes); return -EINVAL; } if (entry->offset != offset) { - fprintf(stderr, "Wanted offset %Lu, found %Lu\n", offset, + fprintf(stderr, "wanted offset %llu, found %llu\n", offset, entry->offset); return -EINVAL; } if (entry->bytes != bytes) { - fprintf(stderr, "Wanted bytes %Lu, found %Lu for off %Lu\n", + fprintf(stderr, "wanted bytes %llu, found %llu for off %llu\n", bytes, entry->bytes, offset); return -EINVAL; } @@ -5337,13 +5362,15 @@ static int check_space_cache(struct btrfs_root *root) error += ret; } else { ret = load_free_space_cache(root->fs_info, cache); - if (!ret) + if (ret < 0) + error++; + if (ret <= 0) continue; } ret = verify_space_cache(root, cache); if (ret) { - fprintf(stderr, "cache appears valid but isn't %Lu\n", + fprintf(stderr, "cache appears valid but isn't %llu\n", cache->key.objectid); error++; } @@ -5356,8 +5383,8 @@ static int check_space_cache(struct btrfs_root *root) static int check_extent_csums(struct btrfs_root *root, u64 bytenr, u64 num_bytes, unsigned long leaf_offset, - struct extent_buffer *eb) { - + struct extent_buffer *eb) +{ struct btrfs_fs_info *fs_info = root->fs_info; u64 offset = 0; u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); @@ -5553,8 +5580,9 @@ again: out: if (num_bytes && !ret) { - fprintf(stderr, "There are no extents for csum range " - "%Lu-%Lu\n", bytenr, bytenr+num_bytes); + fprintf(stderr, + "there are no extents for csum range %llu-%llu\n", + bytenr, bytenr+num_bytes); ret = 1; } @@ -5629,8 +5657,8 @@ skip_csum_check: } else if (key.offset != offset + num_bytes) { ret = check_extent_exists(root, offset, num_bytes); if (ret) { - fprintf(stderr, "Csum exists for %Lu-%Lu but " - "there is no extent record\n", + fprintf(stderr, + "csum exists for %llu-%llu but there is no extent record\n", offset, offset+num_bytes); errors++; } @@ -5646,7 +5674,8 @@ skip_csum_check: } static int is_dropped_key(struct btrfs_key *key, - struct btrfs_key *drop_key) { + struct btrfs_key *drop_key) +{ if (key->objectid < drop_key->objectid) return 1; else if (key->objectid == drop_key->objectid) { @@ -5823,7 +5852,7 @@ static int run_next_block(struct btrfs_root *root, return 1; if (!reada_bits) { - for(i = 0; i < nritems; i++) { + for (i = 0; i < nritems; i++) { ret = add_cache_extent(reada, bits[i].start, bits[i].size); if (ret == -EEXIST) @@ -5933,6 +5962,7 @@ static int run_next_block(struct btrfs_root *root, btree_space_waste += btrfs_leaf_free_space(root, buf); for (i = 0; i < nritems; i++) { struct btrfs_file_extent_item *fi; + btrfs_item_key_to_cpu(buf, &key, i); /* * Check key type against the leaf owner. @@ -6007,6 +6037,7 @@ static int run_next_block(struct btrfs_root *root, } if (key.type == BTRFS_EXTENT_DATA_REF_KEY) { struct btrfs_extent_data_ref *ref; + ref = btrfs_item_ptr(buf, i, struct btrfs_extent_data_ref); add_data_backref(extent_cache, @@ -6021,6 +6052,7 @@ static int run_next_block(struct btrfs_root *root, } if (key.type == BTRFS_SHARED_DATA_REF_KEY) { struct btrfs_shared_data_ref *ref; + ref = btrfs_item_ptr(buf, i, struct btrfs_shared_data_ref); add_data_backref(extent_cache, @@ -6058,9 +6090,9 @@ static int run_next_block(struct btrfs_root *root, data_bytes_allocated += btrfs_file_extent_disk_num_bytes(buf, fi); - if (data_bytes_allocated < root->fs_info->sectorsize) { + if (data_bytes_allocated < root->fs_info->sectorsize) abort(); - } + data_bytes_referenced += btrfs_file_extent_num_bytes(buf, fi); add_data_backref(extent_cache, @@ -6071,12 +6103,7 @@ static int run_next_block(struct btrfs_root *root, } } else { int level; - struct btrfs_key first_key; - - first_key.objectid = 0; - if (nritems > 0) - btrfs_item_key_to_cpu(buf, &first_key, 0); level = btrfs_header_level(buf); for (i = 0; i < nritems; i++) { struct extent_record tmpl; @@ -6093,7 +6120,8 @@ static int run_next_block(struct btrfs_root *root, memset(&tmpl, 0, sizeof(tmpl)); btrfs_cpu_key_to_disk(&tmpl.parent_key, &key); - tmpl.parent_generation = btrfs_node_ptr_generation(buf, i); + tmpl.parent_generation = + btrfs_node_ptr_generation(buf, i); tmpl.start = ptr; tmpl.nr = size; tmpl.refs = 1; @@ -6112,11 +6140,10 @@ static int run_next_block(struct btrfs_root *root, continue; } - if (level > 1) { + if (level > 1) add_pending(nodes, seen, ptr, size); - } else { + else add_pending(pending, seen, ptr, size); - } } btree_space_waste += (BTRFS_NODEPTRS_PER_BLOCK(fs_info) - nritems) * sizeof(struct btrfs_key_ptr); @@ -6188,6 +6215,7 @@ static int free_extent_hook(struct btrfs_trans_handle *trans, rec = container_of(cache, struct extent_record, cache); if (is_data) { struct data_backref *back; + back = find_data_backref(rec, parent, root_objectid, owner, offset, 1, bytenr, num_bytes); if (!back) @@ -6213,6 +6241,7 @@ static int free_extent_hook(struct btrfs_trans_handle *trans, } } else { struct tree_backref *back; + back = find_tree_backref(rec, parent, root_objectid); if (!back) goto out; @@ -6252,7 +6281,7 @@ static int delete_extent_records(struct btrfs_trans_handle *trans, key.type = (u8)-1; key.offset = (u64)-1; - while(1) { + while (1) { ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, 0, 1); if (ret < 0) @@ -6292,7 +6321,8 @@ static int delete_extent_records(struct btrfs_trans_handle *trans, continue; } - fprintf(stderr, "repair deleting extent record: key %Lu %u %Lu\n", + fprintf(stderr, + "repair deleting extent record: key [%llu,%u,%llu]\n", found_key.objectid, found_key.type, found_key.offset); ret = btrfs_del_item(trans, root->fs_info->extent_root, path); @@ -6365,7 +6395,7 @@ static int record_extent(struct btrfs_trans_handle *trans, btrfs_set_extent_flags(leaf, ei, BTRFS_EXTENT_FLAG_DATA); } else { - struct btrfs_disk_key copy_key;; + struct btrfs_disk_key copy_key; bi = (struct btrfs_tree_block_info *)(ei + 1); memset_extent_buffer(leaf, 0, (unsigned long)bi, @@ -6380,7 +6410,7 @@ static int record_extent(struct btrfs_trans_handle *trans, btrfs_set_tree_block_key(leaf, bi, ©_key); btrfs_set_extent_flags(leaf, ei, - BTRFS_EXTENT_FLAG_TREE_BLOCK | flags); + flags | BTRFS_EXTENT_FLAG_TREE_BLOCK); } btrfs_mark_buffer_dirty(leaf); @@ -6418,18 +6448,14 @@ static int record_extent(struct btrfs_trans_handle *trans, if (ret) break; } - fprintf(stderr, "adding new data backref" - " on %llu %s %llu owner %llu" - " offset %llu found %d\n", - (unsigned long long)rec->start, - back->full_backref ? - "parent" : "root", - back->full_backref ? - (unsigned long long)parent : - (unsigned long long)dback->root, - (unsigned long long)dback->owner, - (unsigned long long)dback->offset, - dback->found_ref); + fprintf(stderr, +"adding new data backref on %llu %s %llu owner %llu offset %llu found %d\n", + (unsigned long long)rec->start, + back->full_backref ? "parent" : "root", + back->full_backref ? (unsigned long long)parent : + (unsigned long long)dback->root, + (unsigned long long)dback->owner, + (unsigned long long)dback->offset, dback->found_ref); } else { u64 parent; struct tree_backref *tback; @@ -6443,8 +6469,8 @@ static int record_extent(struct btrfs_trans_handle *trans, ret = btrfs_inc_extent_ref(trans, info->extent_root, rec->start, rec->max_size, parent, tback->root, 0, 0); - fprintf(stderr, "adding new tree backref on " - "start %llu len %llu parent %llu root %llu\n", + fprintf(stderr, +"adding new tree backref on start %llu len %llu parent %llu root %llu\n", rec->start, rec->max_size, parent, tback->root); } fail: @@ -6582,14 +6608,14 @@ static int repair_ref(struct btrfs_fs_info *info, struct btrfs_path *path, */ ret = btrfs_search_slot(trans, root, &key, path, 0, 1); if (ret < 0) { - fprintf(stderr, "Error cowing down to ref [%Lu, %u, %Lu]: %d\n", + fprintf(stderr, "error cowing down to ref [%llu,%u,%llu]: %d\n", key.objectid, key.type, key.offset, ret); goto out; } if (ret > 0) { - fprintf(stderr, "Well that's odd, we just found this key " - "[%Lu, %u, %Lu]\n", key.objectid, key.type, - key.offset); + fprintf(stderr, + "well that's odd, we just found this key [%llu,%u,%llu]\n", + key.objectid, key.type, key.offset); ret = -EINVAL; goto out; } @@ -6599,10 +6625,8 @@ static int repair_ref(struct btrfs_fs_info *info, struct btrfs_path *path, if (btrfs_file_extent_compression(leaf, fi) && dback->disk_bytenr != entry->bytenr) { - fprintf(stderr, "Ref doesn't match the record start and is " - "compressed, please take a btrfs-image of this file " - "system and send it to a btrfs developer so they can " - "complete this functionality for bytenr %Lu\n", + fprintf(stderr, +"ref doesn't match the record start and is compressed, please take a btrfs-image of this file system and send it to a btrfs developer so they can complete this functionality for bytenr %llu\n", dback->disk_bytenr); ret = -EINVAL; goto out; @@ -6618,9 +6642,8 @@ static int repair_ref(struct btrfs_fs_info *info, struct btrfs_path *path, if (dback->disk_bytenr + offset + btrfs_file_extent_num_bytes(leaf, fi) > entry->bytenr + entry->bytes) { - fprintf(stderr, "Ref is past the entry end, please " - "take a btrfs-image of this file system and " - "send it to a btrfs developer, ref %Lu\n", + fprintf(stderr, +"ref is past the entry end, please take a btrfs-image of this file system and send it to a btrfs developer, ref %llu\n", dback->disk_bytenr); ret = -EINVAL; goto out; @@ -6633,9 +6656,8 @@ static int repair_ref(struct btrfs_fs_info *info, struct btrfs_path *path, offset = btrfs_file_extent_offset(leaf, fi); if (dback->disk_bytenr + offset < entry->bytenr) { - fprintf(stderr, "Ref is before the entry start, please" - " take a btrfs-image of this file system and " - "send it to a btrfs developer, ref %Lu\n", + fprintf(stderr, +"ref is before the entry start, please take a btrfs-image of this file system and send it to a btrfs developer, ref %llu\n", dback->disk_bytenr); ret = -EINVAL; goto out; @@ -6741,8 +6763,9 @@ static int verify_backrefs(struct btrfs_fs_info *info, struct btrfs_path *path, if (nr_entries <= 1 && !mismatch) goto out; - fprintf(stderr, "attempting to repair backref discrepency for bytenr " - "%Lu\n", rec->start); + fprintf(stderr, + "attempting to repair backref discrepency for bytenr %llu\n", + rec->start); /* * First we want to see if the backrefs can agree amongst themselves who @@ -6758,9 +6781,8 @@ static int verify_backrefs(struct btrfs_fs_info *info, struct btrfs_path *path, if (!best) { entry = find_entry(&entries, rec->start, rec->nr); if (!entry && (!broken_entries || !rec->found_rec)) { - fprintf(stderr, "Backrefs don't agree with each other " - "and extent record doesn't agree with anybody," - " so we can't fix bytenr %Lu bytes %Lu\n", + fprintf(stderr, +"backrefs don't agree with each other and extent record doesn't agree with anybody, so we can't fix bytenr %llu bytes %llu\n", rec->start, rec->nr); ret = -EINVAL; goto out; @@ -6783,10 +6805,9 @@ static int verify_backrefs(struct btrfs_fs_info *info, struct btrfs_path *path, entry->count++; best = find_most_right_entry(&entries); if (!best) { - fprintf(stderr, "Backrefs and extent record evenly " - "split on who is right, this is going to " - "require user input to fix bytenr %Lu bytes " - "%Lu\n", rec->start, rec->nr); + fprintf(stderr, +"backrefs and extent record evenly split on who is right, this is going to require user input to fix bytenr %llu bytes %llu\n", + rec->start, rec->nr); ret = -EINVAL; goto out; } @@ -6798,10 +6819,8 @@ static int verify_backrefs(struct btrfs_fs_info *info, struct btrfs_path *path, * deal with it properly here yet, so just bail out of that's the case. */ if (best->bytenr != rec->start) { - fprintf(stderr, "Extent start and backref starts don't match, " - "please use btrfs-image on this file system and send " - "it to a btrfs developer so they can make fsck fix " - "this particular case. bytenr is %Lu, bytes is %Lu\n", + fprintf(stderr, +"extent start and backref starts don't match, please use btrfs-image on this file system and send it to a btrfs developer so they can make fsck fix this particular case. bytenr is %llu, bytes is %llu\n", rec->start, rec->nr); ret = -EINVAL; goto out; @@ -6951,10 +6970,8 @@ static int delete_duplicate_records(struct btrfs_root *root, continue; if (tmp->start + tmp->nr < good->start + good->nr) { - fprintf(stderr, "Ok we have overlapping extents that " - "aren't completely covered by each other, this " - "is going to require more careful thought. " - "The extents are [%Lu-%Lu] and [%Lu-%Lu]\n", + fprintf(stderr, +"Ok we have overlapping extents that aren't completely covered by each other, this is going to require more careful thought. The extents are [%llu-%llu] and [%llu-%llu]\n", tmp->start, tmp->nr, good->start, good->nr); abort(); } @@ -6986,9 +7003,9 @@ static int delete_duplicate_records(struct btrfs_root *root, /* Shouldn't happen but just in case */ if (tmp->metadata) { - fprintf(stderr, "Well this shouldn't happen, extent " - "record overlaps but is metadata? " - "[%Lu, %Lu]\n", tmp->start, tmp->nr); + fprintf(stderr, +"well this shouldn't happen, extent record overlaps but is metadata? [%llu, %llu]\n", + tmp->start, tmp->nr); abort(); } @@ -7090,6 +7107,7 @@ static int find_possible_backrefs(struct btrfs_fs_info *info, cache = lookup_cache_extent(extent_cache, bytenr, 1); if (cache) { struct extent_record *tmp; + tmp = container_of(cache, struct extent_record, cache); /* @@ -7271,7 +7289,8 @@ static int fixup_extent_refs(struct btrfs_fs_info *info, continue; rec->bad_full_backref = 0; - ret = record_extent(trans, info, &path, rec, back, allocated, flags); + ret = record_extent(trans, info, &path, rec, back, allocated, + flags); allocated = 1; if (ret) @@ -7280,6 +7299,7 @@ static int fixup_extent_refs(struct btrfs_fs_info *info, out: if (trans) { int err = btrfs_commit_transaction(trans, info->extent_root); + if (!ret) ret = err; } @@ -7401,8 +7421,8 @@ again: goto del_ptr; } /* - * we couldn't find the bad block. TODO, search all the nodes for pointers - * to this block + * We couldn't find the bad block. + * TODO: search all the nodes for pointers to this block */ if (eb == info->extent_root->node) { ret = -ENOENT; @@ -7414,7 +7434,7 @@ again: } del_ptr: - printk("deleting pointer to block %Lu\n", corrupt->cache.start); + printk("deleting pointer to block %llu\n", corrupt->cache.start); ret = btrfs_del_ptr(info->extent_root, &path, level, slot); out: @@ -7463,7 +7483,7 @@ static int check_extent_refs(struct btrfs_root *root, * extents in the FS */ cache = search_cache_extent(extent_cache, 0); - while(cache) { + while (cache) { rec = container_of(cache, struct extent_record, cache); set_extent_dirty(root->fs_info->excluded_extents, rec->start, @@ -7473,7 +7493,7 @@ static int check_extent_refs(struct btrfs_root *root, /* pin down all the corrupted blocks too */ cache = search_cache_extent(root->fs_info->corrupt_blocks, 0); - while(cache) { + while (cache) { set_extent_dirty(root->fs_info->excluded_extents, cache->start, cache->start + cache->size - 1); @@ -7518,7 +7538,7 @@ static int check_extent_refs(struct btrfs_root *root, if (had_dups) return -EAGAIN; - while(1) { + while (1) { int cur_err = 0; int fix = 0; @@ -7527,8 +7547,9 @@ static int check_extent_refs(struct btrfs_root *root, break; rec = container_of(cache, struct extent_record, cache); if (rec->num_duplicates) { - fprintf(stderr, "extent item %llu has multiple extent " - "items\n", (unsigned long long)rec->start); + fprintf(stderr, + "extent item %llu has multiple extent items\n", + (unsigned long long)rec->start); cur_err = 1; } @@ -7561,7 +7582,8 @@ static int check_extent_refs(struct btrfs_root *root, } if (repair && fix) { - ret = fixup_extent_refs(root->fs_info, extent_cache, rec); + ret = fixup_extent_refs(root->fs_info, extent_cache, + rec); if (ret) goto repair_abort; } @@ -7636,28 +7658,6 @@ repair_abort: return err; } -u64 calc_stripe_length(u64 type, u64 length, int num_stripes) -{ - u64 stripe_size; - - if (type & BTRFS_BLOCK_GROUP_RAID0) { - stripe_size = length; - stripe_size /= num_stripes; - } else if (type & BTRFS_BLOCK_GROUP_RAID10) { - stripe_size = length * 2; - stripe_size /= num_stripes; - } else if (type & BTRFS_BLOCK_GROUP_RAID5) { - stripe_size = length; - stripe_size /= (num_stripes - 1); - } else if (type & BTRFS_BLOCK_GROUP_RAID6) { - stripe_size = length; - stripe_size /= (num_stripes - 2); - } else { - stripe_size = length; - } - return stripe_size; -} - /* * Check the chunk with its block group/dev list ref: * Return 0 if all refs seems valid. @@ -7943,8 +7943,8 @@ static int add_root_item_to_list(struct list_head *head, u8 level, u8 drop_level, struct btrfs_key *drop_key) { - struct root_item_record *ri_rec; + ri_rec = malloc(sizeof(*ri_rec)); if (!ri_rec) return -ENOMEM; @@ -7992,6 +7992,7 @@ static int deal_root_from_list(struct list_head *list, while (!list_empty(list)) { struct root_item_record *rec; struct extent_buffer *buf; + rec = list_entry(list->next, struct root_item_record, list); last = 0; @@ -8123,7 +8124,7 @@ again: ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0, 0); if (ret < 0) goto out; - while(1) { + while (1) { leaf = path.nodes[0]; slot = path.slots[0]; if (slot >= btrfs_header_nritems(path.nodes[0])) { @@ -8257,7 +8258,7 @@ static int do_check_chunks_and_extents(struct btrfs_fs_info *fs_info) if (!ctx.progress_enabled) fprintf(stderr, "checking extents\n"); if (check_mode == CHECK_MODE_LOWMEM) - ret = check_chunks_and_extents_v2(fs_info); + ret = check_chunks_and_extents_lowmem(fs_info); else ret = check_chunks_and_extents(fs_info); @@ -9051,6 +9052,7 @@ static int build_roots_info_cache(struct btrfs_fs_info *info) struct btrfs_key found_key; struct btrfs_extent_item *ei; struct btrfs_extent_inline_ref *iref; + unsigned long item_end; int slot = path.slots[0]; int type; u64 flags; @@ -9079,6 +9081,7 @@ static int build_roots_info_cache(struct btrfs_fs_info *info) ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); flags = btrfs_extent_flags(leaf, ei); + item_end = (unsigned long)ei + btrfs_item_size_nr(leaf, slot); if (found_key.type == BTRFS_EXTENT_ITEM_KEY && !(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)) @@ -9096,6 +9099,15 @@ static int build_roots_info_cache(struct btrfs_fs_info *info) } /* + * It's a valid extent/metadata item that has no inline ref, + * but SHARED_BLOCK_REF or other shared references. + * So we need to do extra check to avoid reading beyond leaf + * boudnary. + */ + if ((unsigned long)iref >= item_end) + goto next; + + /* * For a root extent, it must be of the following type and the * first (and only one) iref in the item. */