u64 csum_found; /* In byte size, sectorsize aligned */
u64 search_start; /* Logical range start we search for csum */
u64 search_len; /* Logical range len we search for csum */
+ u32 max_inline_extent_size = min_t(u32, root->fs_info->sectorsize - 1,
+ BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info));
unsigned int extent_type;
unsigned int is_hole;
int compressed = 0;
root->objectid, fkey->objectid, fkey->offset);
err |= FILE_EXTENT_ERROR;
}
+ if (compressed) {
+ if (extent_num_bytes > root->fs_info->sectorsize) {
+ error(
+"root %llu EXTENT_DATA[%llu %llu] too large inline extent ram size, have %llu, max: %u",
+ root->objectid, fkey->objectid,
+ fkey->offset, extent_num_bytes,
+ root->fs_info->sectorsize - 1);
+ err |= FILE_EXTENT_ERROR;
+ }
+ if (item_inline_len > max_inline_extent_size) {
+ error(
+"root %llu EXTENT_DATA[%llu %llu] too large inline extent on-disk size, have %u, max: %u",
+ root->objectid, fkey->objectid,
+ fkey->offset, item_inline_len,
+ max_inline_extent_size);
+ err |= FILE_EXTENT_ERROR;
+ }
+ } else {
+ if (extent_num_bytes > max_inline_extent_size) {
+ error(
+ "root %llu EXTENT_DATA[%llu %llu] too large inline extent size, have %llu, max: %u",
+ root->objectid, fkey->objectid, fkey->offset,
+ extent_num_bytes, max_inline_extent_size);
+ err |= FILE_EXTENT_ERROR;
+ }
+ }
if (!compressed && extent_num_bytes != item_inline_len) {
error(
"root %llu EXTENT_DATA[%llu %llu] wrong inline size, have: %llu, expected: %u",
csum_found, search_len);
} else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC &&
csum_found > 0) {
- err |= ODD_CSUM_ITEM;
- error("root %llu EXTENT_DATA[%llu %llu] prealloc shouldn't have csum, but has: %llu",
- root->objectid, fkey->objectid, fkey->offset, csum_found);
+ ret = check_prealloc_extent_written(root->fs_info,
+ disk_bytenr, disk_num_bytes);
+ if (ret < 0)
+ return ret;
+ if (ret == 0) {
+ err |= ODD_CSUM_ITEM;
+ error(
+"root %llu EXTENT_DATA[%llu %llu] prealloc shouldn't have csum, but has: %llu",
+ root->objectid, fkey->objectid, fkey->offset,
+ csum_found);
+ }
}
/* Check EXTENT_DATA hole */
return ret;
}
+static bool has_orphan_item(struct btrfs_root *root, u64 ino)
+{
+ struct btrfs_path path;
+ struct btrfs_key key;
+ int ret;
+
+ btrfs_init_path(&path);
+ key.objectid = BTRFS_ORPHAN_OBJECTID;
+ key.type = BTRFS_ORPHAN_ITEM_KEY;
+ key.offset = ino;
+
+ ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
+ btrfs_release_path(&path);
+ if (ret == 0)
+ return true;
+ return false;
+}
+
/*
* Check INODE_ITEM and related ITEMs (the same inode number)
* 1. check link count
u64 extent_size = 0;
unsigned int dir;
unsigned int nodatasum;
+ bool is_orphan = false;
int slot;
int ret;
int err = 0;
root->objectid, inode_id, nlink, refs);
}
} else if (!nlink) {
- if (repair)
+ is_orphan = has_orphan_item(root, inode_id);
+ if (!is_orphan && repair)
ret = repair_inode_orphan_item_lowmem(root,
path, inode_id);
- if (!repair || ret) {
+ if (!is_orphan && (!repair || ret)) {
err |= ORPHAN_ITEM;
error("root %llu INODE[%llu] is orphan item",
root->objectid, inode_id);
if (!(extent_flags & BTRFS_EXTENT_FLAG_DATA)) {
error(
- "extent[%llu %llu] backref type mismatch, wanted bit: %llx",
- disk_bytenr, disk_num_bytes,
- BTRFS_EXTENT_FLAG_DATA);
+"file extent[%llu %llu] root %llu owner %llu backref type mismatch, wanted bit: %llx",
+ fi_key.objectid, fi_key.offset, root->objectid, owner,
+ BTRFS_EXTENT_FLAG_DATA);
err |= BACKREF_MISMATCH;
}
/* Didn't find inlined data backref, try EXTENT_DATA_REF_KEY */
dbref_key.objectid = btrfs_file_extent_disk_bytenr(eb, fi);
dbref_key.type = BTRFS_EXTENT_DATA_REF_KEY;
- dbref_key.offset = hash_extent_data_ref(root->objectid,
- fi_key.objectid, fi_key.offset - offset);
+ dbref_key.offset = hash_extent_data_ref(owner, fi_key.objectid,
+ fi_key.offset - offset);
ret = btrfs_search_slot(NULL, root->fs_info->extent_root,
&dbref_key, &path, 0, 0);
err |= BACKREF_MISSING;
btrfs_release_path(&path);
if (err & BACKREF_MISSING) {
- error("data extent[%llu %llu] backref lost",
- disk_bytenr, disk_num_bytes);
+ error(
+ "file extent[%llu %llu] root %llu owner %llu backref lost",
+ fi_key.objectid, fi_key.offset, root->objectid, owner);
}
return err;
}