diff options
author | Dimitri John Ledkov <xnox@ubuntu.com> | 2016-07-26 13:30:05 +0100 |
---|---|---|
committer | Dimitri John Ledkov <xnox@ubuntu.com> | 2016-07-26 13:30:05 +0100 |
commit | 33c949697e316f17bb5037ae83509f35ce28f6a9 (patch) | |
tree | 41ea985d7efe7c3c1a2f64326d8de1a45de7af33 /cmds-check.c | |
parent | affaba87a2797d4d468faad268cc5e21c96c6c16 (diff) |
New upstream release
Diffstat (limited to 'cmds-check.c')
-rw-r--r-- | cmds-check.c | 258 |
1 files changed, 143 insertions, 115 deletions
diff --git a/cmds-check.c b/cmds-check.c index 127ac977..9927fce6 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -122,6 +122,9 @@ struct tree_backref { }; }; +/* Explicit initialization for extent_record::flag_block_full_backref */ +enum { FLAG_UNSET = 2 }; + struct extent_record { struct list_head backrefs; struct list_head dups; @@ -138,7 +141,7 @@ struct extent_record { u64 info_objectid; u32 num_duplicates; u8 info_level; - int flag_block_full_backref; + unsigned int flag_block_full_backref:2; unsigned int found_rec:1; unsigned int content_checked:1; unsigned int owner_ref_checked:1; @@ -476,7 +479,7 @@ static int del_file_extent_hole(struct rb_root *holes, return -EEXIST; /* - * Now there will be no overflap, delete the hole and re-add the + * Now there will be no overlap, delete the hole and re-add the * split(s) if they exists. */ if (start > hole->start) { @@ -746,9 +749,9 @@ static void print_ref_error(int errors) if (errors & REF_ERR_DUP_INODE_REF) fprintf(stderr, ", dup inode ref"); if (errors & REF_ERR_INDEX_UNMATCH) - fprintf(stderr, ", index unmatch"); + fprintf(stderr, ", index mismatch"); if (errors & REF_ERR_FILETYPE_UNMATCH) - fprintf(stderr, ", filetype unmatch"); + fprintf(stderr, ", filetype mismatch"); if (errors & REF_ERR_NAME_TOO_LONG) fprintf(stderr, ", name too long"); if (errors & REF_ERR_NO_ROOT_REF) @@ -2689,7 +2692,7 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans, type_recovered = 1; filetype = BTRFS_FT_REG_FILE; } else{ - printf("Can't determint the filetype for inode %llu, assume it is a normal file\n", + printf("Can't determine the filetype for inode %llu, assume it is a normal file\n", rec->ino); type_recovered = 1; filetype = BTRFS_FT_REG_FILE; @@ -2892,7 +2895,7 @@ static int check_inode_recs(struct btrfs_root *root, /* * We need to record the highest inode number for later 'lost+found' * dir creation. - * We must select a ino not used/refered by any existing inode, or + * We must select an ino not used/referred by any existing inode, or * 'lost+found' ino may be a missing ino in a corrupted leaf, * this may cause 'lost+found' dir has wrong nlinks. */ @@ -4323,7 +4326,7 @@ static int check_block(struct btrfs_root *root, } else { /* * Signal to callers we need to start the scan over - * again since we'll have cow'ed blocks. + * again since we'll have cowed blocks. */ ret = -EAGAIN; } @@ -4509,11 +4512,13 @@ static void check_extent_type(struct extent_record *rec) } } +/* + * Allocate a new extent record, fill default values from @tmpl and insert int + * @extent_cache. Caller is supposed to make sure the [start,nr) is not in + * the cache, otherwise it fails. + */ static int add_extent_rec_nolookup(struct cache_tree *extent_cache, - struct btrfs_key *parent_key, u64 parent_gen, - u64 start, u64 nr, u64 extent_item_refs, - int is_root, int inc_ref, int set_checked, - int metadata, int extent_rec, u64 max_size) + struct extent_record *tmpl) { struct extent_record *rec; int ret = 0; @@ -4521,90 +4526,72 @@ static int add_extent_rec_nolookup(struct cache_tree *extent_cache, rec = malloc(sizeof(*rec)); if (!rec) return -ENOMEM; - rec->start = start; - rec->max_size = max_size; - rec->nr = max(nr, max_size); - rec->found_rec = !!extent_rec; - rec->content_checked = 0; - rec->owner_ref_checked = 0; + rec->start = tmpl->start; + rec->max_size = tmpl->max_size; + rec->nr = max(tmpl->nr, tmpl->max_size); + rec->found_rec = tmpl->found_rec; + rec->content_checked = tmpl->content_checked; + rec->owner_ref_checked = tmpl->owner_ref_checked; rec->num_duplicates = 0; - rec->metadata = metadata; - rec->flag_block_full_backref = -1; + rec->metadata = tmpl->metadata; + rec->flag_block_full_backref = FLAG_UNSET; rec->bad_full_backref = 0; rec->crossing_stripes = 0; rec->wrong_chunk_type = 0; + rec->is_root = tmpl->is_root; + rec->refs = tmpl->refs; + rec->extent_item_refs = tmpl->extent_item_refs; + rec->parent_generation = tmpl->parent_generation; INIT_LIST_HEAD(&rec->backrefs); INIT_LIST_HEAD(&rec->dups); INIT_LIST_HEAD(&rec->list); - - if (is_root) - rec->is_root = 1; - else - rec->is_root = 0; - - if (inc_ref) - rec->refs = 1; - else - rec->refs = 0; - - if (extent_item_refs) - rec->extent_item_refs = extent_item_refs; - else - rec->extent_item_refs = 0; - - if (parent_key) - btrfs_cpu_key_to_disk(&rec->parent_key, parent_key); - else - memset(&rec->parent_key, 0, sizeof(*parent_key)); - - if (parent_gen) - rec->parent_generation = parent_gen; - else - rec->parent_generation = 0; - - rec->cache.start = start; - rec->cache.size = nr; + memcpy(&rec->parent_key, &tmpl->parent_key, sizeof(tmpl->parent_key)); + rec->cache.start = tmpl->start; + rec->cache.size = tmpl->nr; ret = insert_cache_extent(extent_cache, &rec->cache); BUG_ON(ret); - bytes_used += nr; - if (set_checked) { - rec->content_checked = 1; - rec->owner_ref_checked = 1; - } + bytes_used += rec->nr; - if (metadata) + if (tmpl->metadata) rec->crossing_stripes = check_crossing_stripes(rec->start, - rec->max_size); + global_info->tree_root->nodesize); check_extent_type(rec); return ret; } +/* + * Lookup and modify an extent, some values of @tmpl are interpreted verbatim, + * some are hints: + * - refs - if found, increase refs + * - is_root - if found, set + * - content_checked - if found, set + * - owner_ref_checked - if found, set + * + * If not found, create a new one, initialize and insert. + */ static int add_extent_rec(struct cache_tree *extent_cache, - struct btrfs_key *parent_key, u64 parent_gen, - u64 start, u64 nr, u64 extent_item_refs, - int is_root, int inc_ref, int set_checked, - int metadata, int extent_rec, u64 max_size) + struct extent_record *tmpl) { struct extent_record *rec; struct cache_extent *cache; int ret = 0; int dup = 0; - cache = lookup_cache_extent(extent_cache, start, nr); + cache = lookup_cache_extent(extent_cache, tmpl->start, tmpl->nr); if (cache) { rec = container_of(cache, struct extent_record, cache); - if (inc_ref) + if (tmpl->refs) rec->refs++; if (rec->nr == 1) - rec->nr = max(nr, max_size); + rec->nr = max(tmpl->nr, tmpl->max_size); /* * We need to make sure to reset nr to whatever the extent * record says was the real size, this way we can compare it to * the backrefs. */ - if (extent_rec) { - if (start != rec->start || rec->found_rec) { + if (tmpl->found_rec) { + if (tmpl->start != rec->start || rec->found_rec) { struct extent_record *tmp; dup = 1; @@ -4621,46 +4608,44 @@ static int add_extent_rec(struct cache_tree *extent_cache, tmp = malloc(sizeof(*tmp)); if (!tmp) return -ENOMEM; - tmp->start = start; - tmp->max_size = max_size; - tmp->nr = nr; + tmp->start = tmpl->start; + tmp->max_size = tmpl->max_size; + tmp->nr = tmpl->nr; tmp->found_rec = 1; - tmp->metadata = metadata; - tmp->extent_item_refs = extent_item_refs; + tmp->metadata = tmpl->metadata; + tmp->extent_item_refs = tmpl->extent_item_refs; INIT_LIST_HEAD(&tmp->list); list_add_tail(&tmp->list, &rec->dups); rec->num_duplicates++; } else { - rec->nr = nr; + rec->nr = tmpl->nr; rec->found_rec = 1; } } - if (extent_item_refs && !dup) { + if (tmpl->extent_item_refs && !dup) { if (rec->extent_item_refs) { fprintf(stderr, "block %llu rec " "extent_item_refs %llu, passed %llu\n", - (unsigned long long)start, + (unsigned long long)tmpl->start, (unsigned long long) rec->extent_item_refs, - (unsigned long long)extent_item_refs); + (unsigned long long)tmpl->extent_item_refs); } - rec->extent_item_refs = extent_item_refs; + rec->extent_item_refs = tmpl->extent_item_refs; } - if (is_root) + if (tmpl->is_root) rec->is_root = 1; - if (set_checked) { + if (tmpl->content_checked) rec->content_checked = 1; + if (tmpl->owner_ref_checked) rec->owner_ref_checked = 1; - } - - if (parent_key) - btrfs_cpu_key_to_disk(&rec->parent_key, parent_key); - if (parent_gen) - rec->parent_generation = parent_gen; - - if (rec->max_size < max_size) - rec->max_size = max_size; + memcpy(&rec->parent_key, &tmpl->parent_key, + sizeof(tmpl->parent_key)); + if (tmpl->parent_generation) + rec->parent_generation = tmpl->parent_generation; + if (rec->max_size < tmpl->max_size) + rec->max_size = tmpl->max_size; /* * A metadata extent can't cross stripe_len boundary, otherwise @@ -4668,17 +4653,15 @@ static int add_extent_rec(struct cache_tree *extent_cache, * As now stripe_len is fixed to BTRFS_STRIPE_LEN, just check * it. */ - if (metadata) + if (tmpl->metadata) rec->crossing_stripes = check_crossing_stripes( - rec->start, rec->max_size); + rec->start, global_info->tree_root->nodesize); check_extent_type(rec); maybe_free_extent_rec(extent_cache, rec); return ret; } - ret = add_extent_rec_nolookup(extent_cache, parent_key, parent_gen, - start, nr, extent_item_refs, is_root, inc_ref, - set_checked, metadata, extent_rec, max_size); + ret = add_extent_rec_nolookup(extent_cache, tmpl); return ret; } @@ -4692,8 +4675,15 @@ static int add_tree_backref(struct cache_tree *extent_cache, u64 bytenr, cache = lookup_cache_extent(extent_cache, bytenr, 1); if (!cache) { - add_extent_rec_nolookup(extent_cache, NULL, 0, bytenr, - 1, 0, 0, 0, 0, 1, 0, 0); + struct extent_record tmpl; + + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.start = bytenr; + tmpl.nr = 1; + tmpl.metadata = 1; + + add_extent_rec_nolookup(extent_cache, &tmpl); + cache = lookup_cache_extent(extent_cache, bytenr, 1); if (!cache) abort(); @@ -4744,8 +4734,15 @@ static int add_data_backref(struct cache_tree *extent_cache, u64 bytenr, cache = lookup_cache_extent(extent_cache, bytenr, 1); if (!cache) { - add_extent_rec_nolookup(extent_cache, NULL, 0, bytenr, 1, 0, 0, - 0, 0, 0, 0, max_size); + struct extent_record tmpl; + + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.start = bytenr; + tmpl.nr = 1; + tmpl.max_size = max_size; + + add_extent_rec_nolookup(extent_cache, &tmpl); + cache = lookup_cache_extent(extent_cache, bytenr, 1); if (!cache) abort(); @@ -5210,6 +5207,7 @@ static int process_extent_item(struct btrfs_root *root, struct btrfs_extent_data_ref *dref; struct btrfs_shared_data_ref *sref; struct btrfs_key key; + struct extent_record tmpl; unsigned long end; unsigned long ptr; int type; @@ -5237,9 +5235,15 @@ static int process_extent_item(struct btrfs_root *root, #else BUG(); #endif - return add_extent_rec(extent_cache, NULL, 0, key.objectid, - num_bytes, refs, 0, 0, 0, metadata, 1, - num_bytes); + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.start = key.objectid; + tmpl.nr = num_bytes; + tmpl.extent_item_refs = refs; + tmpl.metadata = metadata; + tmpl.found_rec = 1; + tmpl.max_size = num_bytes; + + return add_extent_rec(extent_cache, &tmpl); } ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item); @@ -5249,8 +5253,14 @@ static int process_extent_item(struct btrfs_root *root, else metadata = 0; - add_extent_rec(extent_cache, NULL, 0, key.objectid, num_bytes, - refs, 0, 0, 0, metadata, 1, num_bytes); + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.start = key.objectid; + tmpl.nr = num_bytes; + tmpl.extent_item_refs = refs; + tmpl.metadata = metadata; + tmpl.found_rec = 1; + tmpl.max_size = num_bytes; + add_extent_rec(extent_cache, &tmpl); ptr = (unsigned long)(ei + 1); if (btrfs_extent_flags(eb, ei) & BTRFS_EXTENT_FLAG_TREE_BLOCK && @@ -5539,7 +5549,7 @@ static int check_space_cache(struct btrfs_root *root) ret = verify_space_cache(root, cache); if (ret) { - fprintf(stderr, "cache appears valid but isnt %Lu\n", + fprintf(stderr, "cache appears valid but isn't %Lu\n", cache->key.objectid); error++; } @@ -5629,7 +5639,7 @@ static int check_extent_exists(struct btrfs_root *root, u64 bytenr, path = btrfs_alloc_path(); if (!path) { - fprintf(stderr, "Error allocing path\n"); + fprintf(stderr, "Error allocating path\n"); return -ENOMEM; } @@ -5662,7 +5672,7 @@ again: /* * Block group items come before extent items if they have the same - * bytenr, so walk back one more just in case. Dear future traveler, + * bytenr, so walk back one more just in case. Dear future traveller, * first congrats on mastering time travel. Now if it's not too much * trouble could you go back to 2006 and tell Chris to make the * BLOCK_GROUP_ITEM_KEY (and BTRFS_*_REF_KEY) lower than the @@ -5871,7 +5881,7 @@ static int is_dropped_key(struct btrfs_key *key, * 1) If BTRFS_HEADER_FLAG_RELOC is set then we have FULL_BACKREF set. * 2) If btrfs_header_owner(buf) no longer points to buf then we have * FULL_BACKREF set. - * 3) We cow'ed the block walking down a reloc tree. This is impossible to tell + * 3) We cowed the block walking down a reloc tree. This is impossible to tell * if it happened after the relocation occurred since we'll have dropped the * reloc root, so it's entirely possible to have FULL_BACKREF set on buf and * have no real way to know for sure. @@ -5925,13 +5935,13 @@ static int calc_extent_flag(struct btrfs_root *root, goto full_backref; normal: *flags = 0; - if (rec->flag_block_full_backref != -1 && + if (rec->flag_block_full_backref != FLAG_UNSET && rec->flag_block_full_backref != 0) rec->bad_full_backref = 1; return 0; full_backref: *flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; - if (rec->flag_block_full_backref != -1 && + if (rec->flag_block_full_backref != FLAG_UNSET && rec->flag_block_full_backref != 1) rec->bad_full_backref = 1; return 0; @@ -6213,6 +6223,8 @@ static int run_next_block(struct btrfs_root *root, btrfs_item_key_to_cpu(buf, &first_key, 0); level = btrfs_header_level(buf); for (i = 0; i < nritems; i++) { + struct extent_record tmpl; + ptr = btrfs_node_blockptr(buf, i); size = root->nodesize; btrfs_node_key_to_cpu(buf, &key, i); @@ -6222,10 +6234,16 @@ static int run_next_block(struct btrfs_root *root, continue; } } - ret = add_extent_rec(extent_cache, &key, - btrfs_node_ptr_generation(buf, i), - ptr, size, 0, 0, 1, 0, 1, 0, - size); + + memset(&tmpl, 0, sizeof(tmpl)); + btrfs_cpu_key_to_disk(&tmpl.parent_key, &key); + tmpl.parent_generation = btrfs_node_ptr_generation(buf, i); + tmpl.start = ptr; + tmpl.nr = size; + tmpl.refs = 1; + tmpl.metadata = 1; + tmpl.max_size = size; + ret = add_extent_rec(extent_cache, &tmpl); BUG_ON(ret); add_tree_backref(extent_cache, ptr, parent, owner, 1); @@ -6261,12 +6279,21 @@ static int add_root_to_pending(struct extent_buffer *buf, struct cache_tree *nodes, u64 objectid) { + struct extent_record tmpl; + if (btrfs_header_level(buf) > 0) add_pending(nodes, seen, buf->start, buf->len); else add_pending(pending, seen, buf->start, buf->len); - add_extent_rec(extent_cache, NULL, 0, buf->start, buf->len, - 0, 1, 1, 0, 1, 0, buf->len); + + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.start = buf->start; + tmpl.nr = buf->len; + tmpl.is_root = 1; + tmpl.refs = 1; + tmpl.metadata = 1; + tmpl.max_size = buf->len; + add_extent_rec(extent_cache, &tmpl); if (objectid == BTRFS_TREE_RELOC_OBJECTID || btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV) @@ -7063,7 +7090,7 @@ static int delete_duplicate_records(struct btrfs_root *root, if (tmp->start + tmp->nr < good->start + good->nr) { fprintf(stderr, "Ok we have overlapping extents that " - "aren't completely covered by eachother, this " + "aren't completely covered by each other, this " "is going to require more careful thought. " "The extents are [%Lu-%Lu] and [%Lu-%Lu]\n", tmp->start, tmp->nr, good->start, good->nr); @@ -8797,7 +8824,7 @@ static int reinit_extent_tree(struct btrfs_trans_handle *trans, ret = reset_balance(trans, fs_info); if (ret) - fprintf(stderr, "error reseting the pending balance\n"); + fprintf(stderr, "error resetting the pending balance\n"); return ret; } @@ -9479,8 +9506,8 @@ out: const char * const cmd_check_usage[] = { "btrfs check [options] <device>", - "Check structural inegrity of a filesystem (unmounted).", - "Check structural inegrity of an unmounted filesystem. Verify internal", + "Check structural integrity of a filesystem (unmounted).", + "Check structural integrity of an unmounted filesystem. Verify internal", "trees' consistency and item connectivity. In the repair mode try to", "fix the problems found.", "WARNING: the repair mode is considered dangerous", @@ -9491,7 +9518,7 @@ const char * const cmd_check_usage[] = { "--readonly run in read-only mode (default)", "--init-csum-tree create a new CRC tree", "--init-extent-tree create a new extent tree", - "--check-data-csum verify checkums of data blocks", + "--check-data-csum verify checksums of data blocks", "-Q|--qgroup-report print a report on qgroup consistency", "-E|--subvol-extents <subvolid>", " print subvolume extents and sharing state", @@ -9863,6 +9890,7 @@ out: (unsigned long long)data_bytes_allocated, (unsigned long long)data_bytes_referenced); + free_qgroup_counts(); free_root_recs_tree(&root_cache); close_out: close_ctree(root); |