fs/btrfs/tree-checker.c

Source file repositories/reference/linux-study-clean/fs/btrfs/tree-checker.c

File Facts

System
Linux kernel
Corpus path
fs/btrfs/tree-checker.c
Extension
.c
Size
86375 bytes
Lines
2737
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (unlikely(key->offset)) {
			file_extent_err(leaf, slot,
		"invalid file_offset for inline file extent, have %llu expect 0",
				key->offset);
			return -EUCLEAN;
		}

		/* Compressed inline extent has no on-disk size, skip it */
		if (btrfs_file_extent_compression(leaf, fi) !=
		    BTRFS_COMPRESS_NONE)
			return 0;

		/* Uncompressed inline extent size must match item size */
		if (unlikely(item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START +
					  btrfs_file_extent_ram_bytes(leaf, fi))) {
			file_extent_err(leaf, slot,
	"invalid ram_bytes for uncompressed inline extent, have %u expect %llu",
				item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START +
				btrfs_file_extent_ram_bytes(leaf, fi));
			return -EUCLEAN;
		}
		return 0;
	}

	/*
	 * For the data reloc tree, file extent items are written by
	 * relocation's own paths. The data reloc inode is created with
	 * BTRFS_INODE_NOCOMPRESS, so insert_ordered_extent_file_extent()
	 * always leaves the compression field at 0. Encryption and
	 * other_encoding are reserved-and-zero in btrfs. A non-zero value
	 * for any of these means the leaf decoded from disk does not match
	 * what the kernel wrote, i.e. on-disk corruption.
	 *
	 * The file_extent_item's offset field is NOT a universal invariant
	 * here: partial-PREALLOC writebacks legitimately produce REG items
	 * with non-zero offset at non-boundary keys. The offset check is
	 * performed at the call site in get_new_location(), which only
	 * inspects cluster-boundary keys where offset is always 0.
	 */
	if (unlikely(btrfs_header_owner(leaf) == BTRFS_DATA_RELOC_TREE_OBJECTID &&
		     (btrfs_file_extent_compression(leaf, fi) ||
		      btrfs_file_extent_encryption(leaf, fi) ||
		      btrfs_file_extent_other_encoding(leaf, fi)))) {
		file_extent_err(leaf, slot,
"invalid encoding fields for data reloc tree, compression=%u encryption=%u other_encoding=%u",
				btrfs_file_extent_compression(leaf, fi),
				btrfs_file_extent_encryption(leaf, fi),
				btrfs_file_extent_other_encoding(leaf, fi));
		return -EUCLEAN;
	}

	/* Regular or preallocated extent has fixed item size */
	if (unlikely(item_size != sizeof(*fi))) {
		file_extent_err(leaf, slot,
	"invalid item size for reg/prealloc file extent, have %u expect %zu",
			item_size, sizeof(*fi));
		return -EUCLEAN;
	}
	if (unlikely(CHECK_FE_ALIGNED(leaf, slot, fi, ram_bytes, sectorsize) ||
		     CHECK_FE_ALIGNED(leaf, slot, fi, disk_bytenr, sectorsize) ||
		     CHECK_FE_ALIGNED(leaf, slot, fi, disk_num_bytes, sectorsize) ||
		     CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) ||
		     CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize)))
		return -EUCLEAN;

	/* Catch extent end overflow */
	if (unlikely(check_add_overflow(btrfs_file_extent_num_bytes(leaf, fi),
					key->offset, &extent_end))) {
		file_extent_err(leaf, slot,
	"extent end overflow, have file offset %llu extent num bytes %llu",
				key->offset,
				btrfs_file_extent_num_bytes(leaf, fi));
		return -EUCLEAN;
	}

	/*
	 * Check that no two consecutive file extent items, in the same leaf,
	 * present ranges that overlap each other.
	 */
	if (slot > 0 &&
	    prev_key->objectid == key->objectid &&
	    prev_key->type == BTRFS_EXTENT_DATA_KEY) {
		struct btrfs_file_extent_item *prev_fi;
		u64 prev_end;

		prev_fi = btrfs_item_ptr(leaf, slot - 1,
					 struct btrfs_file_extent_item);
		prev_end = file_extent_end(leaf, prev_key, prev_fi);
		if (unlikely(prev_end > key->offset)) {
			file_extent_err(leaf, slot - 1,

Annotation

Implementation Notes