mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	btrfs: tree-checker: Add EXTENT_DATA_REF check
EXTENT_DATA_REF is a little like DIR_ITEM which contains hash in its key->offset. This patch will check the following contents: - Key->objectid Basic alignment check. - Hash Hash of each extent_data_ref item must match key->offset. - Offset Basic alignment check. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									e2406a6f13
								
							
						
					
					
						commit
						0785a9aacf
					
				
					 3 changed files with 50 additions and 1 deletions
				
			
		| 
						 | 
					@ -2447,6 +2447,7 @@ enum btrfs_inline_ref_type {
 | 
				
			||||||
int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
 | 
					int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
 | 
				
			||||||
				     struct btrfs_extent_inline_ref *iref,
 | 
									     struct btrfs_extent_inline_ref *iref,
 | 
				
			||||||
				     enum btrfs_inline_ref_type is_data);
 | 
									     enum btrfs_inline_ref_type is_data);
 | 
				
			||||||
 | 
					u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes);
 | 
					u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -438,7 +438,7 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
 | 
				
			||||||
	return BTRFS_REF_TYPE_INVALID;
 | 
						return BTRFS_REF_TYPE_INVALID;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset)
 | 
					u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 high_crc = ~(u32)0;
 | 
						u32 high_crc = ~(u32)0;
 | 
				
			||||||
	u32 low_crc = ~(u32)0;
 | 
						u32 low_crc = ~(u32)0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1187,6 +1187,51 @@ static int check_simple_keyed_refs(struct extent_buffer *leaf,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int check_extent_data_ref(struct extent_buffer *leaf,
 | 
				
			||||||
 | 
									 struct btrfs_key *key, int slot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct btrfs_extent_data_ref *dref;
 | 
				
			||||||
 | 
						unsigned long ptr = btrfs_item_ptr_offset(leaf, slot);
 | 
				
			||||||
 | 
						const unsigned long end = ptr + btrfs_item_size_nr(leaf, slot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (btrfs_item_size_nr(leaf, slot) % sizeof(*dref) != 0) {
 | 
				
			||||||
 | 
							generic_err(leaf, slot,
 | 
				
			||||||
 | 
						"invalid item size, have %u expect aligned to %zu for key type %u",
 | 
				
			||||||
 | 
								    btrfs_item_size_nr(leaf, slot),
 | 
				
			||||||
 | 
								    sizeof(*dref), key->type);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) {
 | 
				
			||||||
 | 
							generic_err(leaf, slot,
 | 
				
			||||||
 | 
					"invalid key objectid for shared block ref, have %llu expect aligned to %u",
 | 
				
			||||||
 | 
								    key->objectid, leaf->fs_info->sectorsize);
 | 
				
			||||||
 | 
							return -EUCLEAN;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (; ptr < end; ptr += sizeof(*dref)) {
 | 
				
			||||||
 | 
							u64 root_objectid;
 | 
				
			||||||
 | 
							u64 owner;
 | 
				
			||||||
 | 
							u64 offset;
 | 
				
			||||||
 | 
							u64 hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							dref = (struct btrfs_extent_data_ref *)ptr;
 | 
				
			||||||
 | 
							root_objectid = btrfs_extent_data_ref_root(leaf, dref);
 | 
				
			||||||
 | 
							owner = btrfs_extent_data_ref_objectid(leaf, dref);
 | 
				
			||||||
 | 
							offset = btrfs_extent_data_ref_offset(leaf, dref);
 | 
				
			||||||
 | 
							hash = hash_extent_data_ref(root_objectid, owner, offset);
 | 
				
			||||||
 | 
							if (hash != key->offset) {
 | 
				
			||||||
 | 
								extent_err(leaf, slot,
 | 
				
			||||||
 | 
						"invalid extent data ref hash, item has 0x%016llx key has 0x%016llx",
 | 
				
			||||||
 | 
									   hash, key->offset);
 | 
				
			||||||
 | 
								return -EUCLEAN;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (!IS_ALIGNED(offset, leaf->fs_info->sectorsize)) {
 | 
				
			||||||
 | 
								extent_err(leaf, slot,
 | 
				
			||||||
 | 
						"invalid extent data backref offset, have %llu expect aligned to %u",
 | 
				
			||||||
 | 
									   offset, leaf->fs_info->sectorsize);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Common point to switch the item-specific validation.
 | 
					 * Common point to switch the item-specific validation.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -1234,6 +1279,9 @@ static int check_leaf_item(struct extent_buffer *leaf,
 | 
				
			||||||
	case BTRFS_SHARED_BLOCK_REF_KEY:
 | 
						case BTRFS_SHARED_BLOCK_REF_KEY:
 | 
				
			||||||
		ret = check_simple_keyed_refs(leaf, key, slot);
 | 
							ret = check_simple_keyed_refs(leaf, key, slot);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case BTRFS_EXTENT_DATA_REF_KEY:
 | 
				
			||||||
 | 
							ret = check_extent_data_ref(leaf, key, slot);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue