#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,
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)
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;
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 ||
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;
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;
}
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);
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);
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);
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 ?
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);
}
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);
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);
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);
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;
}
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)
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)
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;
}
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);
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);
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,
struct cache_tree *seen, u64 bytenr, u32 size)
{
int ret;
+
ret = add_cache_extent(seen, bytenr, size);
if (ret)
return ret;
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;
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;
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",
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;
}
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;
}
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++;
}
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);
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;
}
int ret;
u64 data_len;
unsigned long leaf_offset;
+ bool verify_csum = !!check_data_csum;
root = root->fs_info->csum_root;
if (!extent_buffer_uptodate(root->node)) {
path.slots[0]--;
ret = 0;
+ /*
+ * For metadata dump (btrfs-image) all data is wiped so verifying data
+ * csum is meaningless and will always report csum error.
+ */
+ if (check_data_csum && (btrfs_super_flags(root->fs_info->super_copy) &
+ (BTRFS_SUPER_FLAG_METADUMP | BTRFS_SUPER_FLAG_METADUMP_V2))) {
+ printf("skip data csum verification for metadata dump\n");
+ verify_csum = false;
+ }
+
while (1) {
if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
ret = btrfs_next_leaf(root, &path);
data_len = (btrfs_item_size_nr(leaf, path.slots[0]) /
csum_size) * root->fs_info->sectorsize;
- if (!check_data_csum)
+ if (!verify_csum)
goto skip_csum_check;
leaf_offset = btrfs_item_ptr_offset(leaf, path.slots[0]);
ret = check_extent_csums(root, key.offset, data_len,
} 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++;
}
}
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) {
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)
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.
}
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,
}
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,
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,
}
} 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;
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;
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);
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)
}
} else {
struct tree_backref *back;
+
back = find_tree_backref(rec, parent, root_objectid);
if (!back)
goto out;
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)
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);
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,
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);
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;
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:
*/
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;
}
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;
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;
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;
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
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;
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;
}
* 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;
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();
}
/* 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();
}
cache = lookup_cache_extent(extent_cache, bytenr, 1);
if (cache) {
struct extent_record *tmp;
+
tmp = container_of(cache, struct extent_record, cache);
/*
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)
out:
if (trans) {
int err = btrfs_commit_transaction(trans, info->extent_root);
+
if (!ret)
ret = err;
}
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;
}
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:
* 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,
/* 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);
if (had_dups)
return -EAGAIN;
- while(1) {
+ while (1) {
int cur_err = 0;
int fix = 0;
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;
}
}
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;
}
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.
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;
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;
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])) {
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);
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;
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))
}
/*
+ * 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.
*/