Blame view

fs/btrfs/tree-checker.c 52.1 KB
c1d7c514f   David Sterba   btrfs: replace GP...
1
  // SPDX-License-Identifier: GPL-2.0
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
2
3
  /*
   * Copyright (C) Qu Wenruo 2017.  All rights reserved.
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
4
5
6
7
8
9
10
11
12
13
14
15
16
   */
  
  /*
   * The module is used to catch unexpected/corrupted tree block data.
   * Such behavior can be caused either by a fuzzed image or bugs.
   *
   * The objective is to do leaf/node validation checks when tree block is read
   * from disk, and check *every* possible member, so other code won't
   * need to checking them again.
   *
   * Due to the potential and unwanted damage, every checker needs to be
   * carefully reviewed otherwise so it does not prevent mount of valid images.
   */
02529d7a1   Qu Wenruo   btrfs: tree-check...
17
18
19
  #include <linux/types.h>
  #include <linux/stddef.h>
  #include <linux/error-injection.h>
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
20
21
22
23
  #include "ctree.h"
  #include "tree-checker.h"
  #include "disk-io.h"
  #include "compression.h"
fce466eab   Qu Wenruo   btrfs: tree-check...
24
  #include "volumes.h"
c1499166d   David Sterba   btrfs: use has_si...
25
  #include "misc.h"
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
26

bba4f2989   Qu Wenruo   btrfs: tree-check...
27
28
29
30
31
32
  /*
   * Error message should follow the following format:
   * corrupt <type>: <identifier>, <reason>[, <bad_value>]
   *
   * @type:	leaf or node
   * @identifier:	the necessary info to locate the leaf/node.
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
33
   * 		It's recommended to decode key.objecitd/offset if it's
bba4f2989   Qu Wenruo   btrfs: tree-check...
34
35
   * 		meaningful.
   * @reason:	describe the error
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
36
   * @bad_value:	optional, it's recommended to output bad value and its
bba4f2989   Qu Wenruo   btrfs: tree-check...
37
38
39
40
41
42
43
44
45
46
   *		expected value (range).
   *
   * Since comma is used to separate the components, only space is allowed
   * inside each component.
   */
  
  /*
   * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt.
   * Allows callers to customize the output.
   */
86a6be3ab   David Sterba   btrfs: tree-check...
47
  __printf(3, 4)
e67c718b5   David Sterba   btrfs: add more _...
48
  __cold
86a6be3ab   David Sterba   btrfs: tree-check...
49
  static void generic_err(const struct extent_buffer *eb, int slot,
bba4f2989   Qu Wenruo   btrfs: tree-check...
50
51
  			const char *fmt, ...)
  {
86a6be3ab   David Sterba   btrfs: tree-check...
52
  	const struct btrfs_fs_info *fs_info = eb->fs_info;
bba4f2989   Qu Wenruo   btrfs: tree-check...
53
54
55
56
57
58
59
  	struct va_format vaf;
  	va_list args;
  
  	va_start(args, fmt);
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
2f659546c   Qu Wenruo   btrfs: tree-check...
60
  	btrfs_crit(fs_info,
bba4f2989   Qu Wenruo   btrfs: tree-check...
61
62
  		"corrupt %s: root=%llu block=%llu slot=%d, %pV",
  		btrfs_header_level(eb) == 0 ? "leaf" : "node",
2f659546c   Qu Wenruo   btrfs: tree-check...
63
  		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, &vaf);
bba4f2989   Qu Wenruo   btrfs: tree-check...
64
65
  	va_end(args);
  }
8806d7185   Qu Wenruo   btrfs: tree-check...
66
67
68
69
  /*
   * Customized reporter for extent data item, since its key objectid and
   * offset has its own meaning.
   */
1fd715ffd   David Sterba   btrfs: tree-check...
70
  __printf(3, 4)
e67c718b5   David Sterba   btrfs: add more _...
71
  __cold
1fd715ffd   David Sterba   btrfs: tree-check...
72
  static void file_extent_err(const struct extent_buffer *eb, int slot,
8806d7185   Qu Wenruo   btrfs: tree-check...
73
74
  			    const char *fmt, ...)
  {
1fd715ffd   David Sterba   btrfs: tree-check...
75
  	const struct btrfs_fs_info *fs_info = eb->fs_info;
8806d7185   Qu Wenruo   btrfs: tree-check...
76
77
78
79
80
81
82
83
84
  	struct btrfs_key key;
  	struct va_format vaf;
  	va_list args;
  
  	btrfs_item_key_to_cpu(eb, &key, slot);
  	va_start(args, fmt);
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
2f659546c   Qu Wenruo   btrfs: tree-check...
85
  	btrfs_crit(fs_info,
8806d7185   Qu Wenruo   btrfs: tree-check...
86
  	"corrupt %s: root=%llu block=%llu slot=%d ino=%llu file_offset=%llu, %pV",
2f659546c   Qu Wenruo   btrfs: tree-check...
87
88
89
  		btrfs_header_level(eb) == 0 ? "leaf" : "node",
  		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
  		key.objectid, key.offset, &vaf);
8806d7185   Qu Wenruo   btrfs: tree-check...
90
91
92
93
94
95
96
  	va_end(args);
  }
  
  /*
   * Return 0 if the btrfs_file_extent_##name is aligned to @alignment
   * Else return 1
   */
033774dc5   David Sterba   btrfs: remove unu...
97
  #define CHECK_FE_ALIGNED(leaf, slot, fi, name, alignment)		      \
8806d7185   Qu Wenruo   btrfs: tree-check...
98
99
  ({									      \
  	if (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))) \
1fd715ffd   David Sterba   btrfs: tree-check...
100
  		file_extent_err((leaf), (slot),				      \
8806d7185   Qu Wenruo   btrfs: tree-check...
101
102
103
104
105
  	"invalid %s for file extent, have %llu, should be aligned to %u",     \
  			(#name), btrfs_file_extent_##name((leaf), (fi)),      \
  			(alignment));					      \
  	(!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment)));   \
  })
4e9845eff   Filipe Manana   Btrfs: tree-check...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  static u64 file_extent_end(struct extent_buffer *leaf,
  			   struct btrfs_key *key,
  			   struct btrfs_file_extent_item *extent)
  {
  	u64 end;
  	u64 len;
  
  	if (btrfs_file_extent_type(leaf, extent) == BTRFS_FILE_EXTENT_INLINE) {
  		len = btrfs_file_extent_ram_bytes(leaf, extent);
  		end = ALIGN(key->offset + len, leaf->fs_info->sectorsize);
  	} else {
  		len = btrfs_file_extent_num_bytes(leaf, extent);
  		end = key->offset + len;
  	}
  	return end;
  }
80d7fd1e0   Qu Wenruo   btrfs: tree-check...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  /*
   * Customized report for dir_item, the only new important information is
   * key->objectid, which represents inode number
   */
  __printf(3, 4)
  __cold
  static void dir_item_err(const struct extent_buffer *eb, int slot,
  			 const char *fmt, ...)
  {
  	const struct btrfs_fs_info *fs_info = eb->fs_info;
  	struct btrfs_key key;
  	struct va_format vaf;
  	va_list args;
  
  	btrfs_item_key_to_cpu(eb, &key, slot);
  	va_start(args, fmt);
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	btrfs_crit(fs_info,
  		"corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV",
  		btrfs_header_level(eb) == 0 ? "leaf" : "node",
  		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
  		key.objectid, &vaf);
  	va_end(args);
  }
  
  /*
   * This functions checks prev_key->objectid, to ensure current key and prev_key
   * share the same objectid as inode number.
   *
   * This is to detect missing INODE_ITEM in subvolume trees.
   *
   * Return true if everything is OK or we don't need to check.
   * Return false if anything is wrong.
   */
  static bool check_prev_ino(struct extent_buffer *leaf,
  			   struct btrfs_key *key, int slot,
  			   struct btrfs_key *prev_key)
  {
  	/* No prev key, skip check */
  	if (slot == 0)
  		return true;
  
  	/* Only these key->types needs to be checked */
  	ASSERT(key->type == BTRFS_XATTR_ITEM_KEY ||
  	       key->type == BTRFS_INODE_REF_KEY ||
  	       key->type == BTRFS_DIR_INDEX_KEY ||
  	       key->type == BTRFS_DIR_ITEM_KEY ||
  	       key->type == BTRFS_EXTENT_DATA_KEY);
  
  	/*
  	 * Only subvolume trees along with their reloc trees need this check.
  	 * Things like log tree doesn't follow this ino requirement.
  	 */
  	if (!is_fstree(btrfs_header_owner(leaf)))
  		return true;
  
  	if (key->objectid == prev_key->objectid)
  		return true;
  
  	/* Error found */
  	dir_item_err(leaf, slot,
  		"invalid previous key objectid, have %llu expect %llu",
  		prev_key->objectid, key->objectid);
  	return false;
  }
ae2a19d8a   David Sterba   btrfs: tree-check...
190
  static int check_extent_data_item(struct extent_buffer *leaf,
4e9845eff   Filipe Manana   Btrfs: tree-check...
191
192
  				  struct btrfs_key *key, int slot,
  				  struct btrfs_key *prev_key)
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
193
  {
ae2a19d8a   David Sterba   btrfs: tree-check...
194
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
195
  	struct btrfs_file_extent_item *fi;
2f659546c   Qu Wenruo   btrfs: tree-check...
196
  	u32 sectorsize = fs_info->sectorsize;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
197
  	u32 item_size = btrfs_item_size_nr(leaf, slot);
4c094c33c   Qu Wenruo   btrfs: tree-check...
198
  	u64 extent_end;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
199
200
  
  	if (!IS_ALIGNED(key->offset, sectorsize)) {
1fd715ffd   David Sterba   btrfs: tree-check...
201
  		file_extent_err(leaf, slot,
8806d7185   Qu Wenruo   btrfs: tree-check...
202
203
  "unaligned file_offset for file extent, have %llu should be aligned to %u",
  			key->offset, sectorsize);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
204
205
  		return -EUCLEAN;
  	}
c18679ebd   Qu Wenruo   btrfs: tree-check...
206
207
208
209
210
211
  	/*
  	 * Previous key must have the same key->objectid (ino).
  	 * It can be XATTR_ITEM, INODE_ITEM or just another EXTENT_DATA.
  	 * But if objectids mismatch, it means we have a missing
  	 * INODE_ITEM.
  	 */
80d7fd1e0   Qu Wenruo   btrfs: tree-check...
212
  	if (!check_prev_ino(leaf, key, slot, prev_key))
c18679ebd   Qu Wenruo   btrfs: tree-check...
213
  		return -EUCLEAN;
c18679ebd   Qu Wenruo   btrfs: tree-check...
214

557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
215
  	fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
153a6d299   Qu Wenruo   btrfs: tree-check...
216
217
218
219
220
221
  	/*
  	 * Make sure the item contains at least inline header, so the file
  	 * extent type is not some garbage.
  	 */
  	if (item_size < BTRFS_FILE_EXTENT_INLINE_DATA_START) {
  		file_extent_err(leaf, slot,
994bf9cd7   Andreas Färber   btrfs: tree-check...
222
  				"invalid item size, have %u expect [%zu, %u)",
153a6d299   Qu Wenruo   btrfs: tree-check...
223
224
225
226
  				item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START,
  				SZ_4K);
  		return -EUCLEAN;
  	}
b9b1a53e1   Chengguang Xu   btrfs: use enum f...
227
  	if (btrfs_file_extent_type(leaf, fi) >= BTRFS_NR_FILE_EXTENT_TYPES) {
1fd715ffd   David Sterba   btrfs: tree-check...
228
  		file_extent_err(leaf, slot,
8806d7185   Qu Wenruo   btrfs: tree-check...
229
230
  		"invalid type for file extent, have %u expect range [0, %u]",
  			btrfs_file_extent_type(leaf, fi),
b9b1a53e1   Chengguang Xu   btrfs: use enum f...
231
  			BTRFS_NR_FILE_EXTENT_TYPES - 1);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
232
233
234
235
  		return -EUCLEAN;
  	}
  
  	/*
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
236
  	 * Support for new compression/encryption must introduce incompat flag,
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
237
238
  	 * and must be caught in open_ctree().
  	 */
ce96b7ffd   Chengguang Xu   btrfs: use better...
239
  	if (btrfs_file_extent_compression(leaf, fi) >= BTRFS_NR_COMPRESS_TYPES) {
1fd715ffd   David Sterba   btrfs: tree-check...
240
  		file_extent_err(leaf, slot,
8806d7185   Qu Wenruo   btrfs: tree-check...
241
242
  	"invalid compression for file extent, have %u expect range [0, %u]",
  			btrfs_file_extent_compression(leaf, fi),
ce96b7ffd   Chengguang Xu   btrfs: use better...
243
  			BTRFS_NR_COMPRESS_TYPES - 1);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
244
245
246
  		return -EUCLEAN;
  	}
  	if (btrfs_file_extent_encryption(leaf, fi)) {
1fd715ffd   David Sterba   btrfs: tree-check...
247
  		file_extent_err(leaf, slot,
8806d7185   Qu Wenruo   btrfs: tree-check...
248
249
  			"invalid encryption for file extent, have %u expect 0",
  			btrfs_file_extent_encryption(leaf, fi));
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
250
251
252
253
254
  		return -EUCLEAN;
  	}
  	if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) {
  		/* Inline extent must have 0 as key offset */
  		if (key->offset) {
1fd715ffd   David Sterba   btrfs: tree-check...
255
  			file_extent_err(leaf, slot,
8806d7185   Qu Wenruo   btrfs: tree-check...
256
257
  		"invalid file_offset for inline file extent, have %llu expect 0",
  				key->offset);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
258
259
260
261
262
263
264
265
266
267
268
  			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 (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START +
  		    btrfs_file_extent_ram_bytes(leaf, fi)) {
1fd715ffd   David Sterba   btrfs: tree-check...
269
  			file_extent_err(leaf, slot,
8806d7185   Qu Wenruo   btrfs: tree-check...
270
271
272
  	"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));
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
273
274
275
276
277
278
279
  			return -EUCLEAN;
  		}
  		return 0;
  	}
  
  	/* Regular or preallocated extent has fixed item size */
  	if (item_size != sizeof(*fi)) {
1fd715ffd   David Sterba   btrfs: tree-check...
280
  		file_extent_err(leaf, slot,
709a95c3e   Arnd Bergmann   btrfs: tree-check...
281
  	"invalid item size for reg/prealloc file extent, have %u expect %zu",
8806d7185   Qu Wenruo   btrfs: tree-check...
282
  			item_size, sizeof(*fi));
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
283
284
  		return -EUCLEAN;
  	}
033774dc5   David Sterba   btrfs: remove unu...
285
286
287
288
289
  	if (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))
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
290
  		return -EUCLEAN;
4e9845eff   Filipe Manana   Btrfs: tree-check...
291

4c094c33c   Qu Wenruo   btrfs: tree-check...
292
293
294
295
296
297
298
299
300
  	/* Catch extent end overflow */
  	if (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;
  	}
4e9845eff   Filipe Manana   Btrfs: tree-check...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  	/*
  	 * 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 (prev_end > key->offset) {
  			file_extent_err(leaf, slot - 1,
  "file extent end range (%llu) goes beyond start offset (%llu) of the next file extent",
  					prev_end, key->offset);
  			return -EUCLEAN;
  		}
  	}
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
321
322
  	return 0;
  }
68128ce75   David Sterba   btrfs: tree-check...
323
  static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key,
ad1d8c439   Filipe Manana   Btrfs: make tree ...
324
  			   int slot, struct btrfs_key *prev_key)
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
325
  {
68128ce75   David Sterba   btrfs: tree-check...
326
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
2f659546c   Qu Wenruo   btrfs: tree-check...
327
328
  	u32 sectorsize = fs_info->sectorsize;
  	u32 csumsize = btrfs_super_csum_size(fs_info->super_copy);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
329
330
  
  	if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) {
86a6be3ab   David Sterba   btrfs: tree-check...
331
  		generic_err(leaf, slot,
d508c5f07   Qu Wenruo   btrfs: tree-check...
332
333
  		"invalid key objectid for csum item, have %llu expect %llu",
  			key->objectid, BTRFS_EXTENT_CSUM_OBJECTID);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
334
335
336
  		return -EUCLEAN;
  	}
  	if (!IS_ALIGNED(key->offset, sectorsize)) {
86a6be3ab   David Sterba   btrfs: tree-check...
337
  		generic_err(leaf, slot,
d508c5f07   Qu Wenruo   btrfs: tree-check...
338
339
  	"unaligned key offset for csum item, have %llu should be aligned to %u",
  			key->offset, sectorsize);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
340
341
342
  		return -EUCLEAN;
  	}
  	if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) {
86a6be3ab   David Sterba   btrfs: tree-check...
343
  		generic_err(leaf, slot,
d508c5f07   Qu Wenruo   btrfs: tree-check...
344
345
  	"unaligned item size for csum item, have %u should be aligned to %u",
  			btrfs_item_size_nr(leaf, slot), csumsize);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
346
347
  		return -EUCLEAN;
  	}
ad1d8c439   Filipe Manana   Btrfs: make tree ...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  	if (slot > 0 && prev_key->type == BTRFS_EXTENT_CSUM_KEY) {
  		u64 prev_csum_end;
  		u32 prev_item_size;
  
  		prev_item_size = btrfs_item_size_nr(leaf, slot - 1);
  		prev_csum_end = (prev_item_size / csumsize) * sectorsize;
  		prev_csum_end += prev_key->offset;
  		if (prev_csum_end > key->offset) {
  			generic_err(leaf, slot - 1,
  "csum end range (%llu) goes beyond the start range (%llu) of the next csum item",
  				    prev_csum_end, key->offset);
  			return -EUCLEAN;
  		}
  	}
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
362
363
  	return 0;
  }
c23c77b09   Qu Wenruo   btrfs: tree-check...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  /* Inode item error output has the same format as dir_item_err() */
  #define inode_item_err(eb, slot, fmt, ...)			\
  	dir_item_err(eb, slot, fmt, __VA_ARGS__)
  
  static int check_inode_key(struct extent_buffer *leaf, struct btrfs_key *key,
  			   int slot)
  {
  	struct btrfs_key item_key;
  	bool is_inode_item;
  
  	btrfs_item_key_to_cpu(leaf, &item_key, slot);
  	is_inode_item = (item_key.type == BTRFS_INODE_ITEM_KEY);
  
  	/* For XATTR_ITEM, location key should be all 0 */
  	if (item_key.type == BTRFS_XATTR_ITEM_KEY) {
  		if (key->type != 0 || key->objectid != 0 || key->offset != 0)
  			return -EUCLEAN;
  		return 0;
  	}
  
  	if ((key->objectid < BTRFS_FIRST_FREE_OBJECTID ||
  	     key->objectid > BTRFS_LAST_FREE_OBJECTID) &&
  	    key->objectid != BTRFS_ROOT_TREE_DIR_OBJECTID &&
  	    key->objectid != BTRFS_FREE_INO_OBJECTID) {
  		if (is_inode_item) {
  			generic_err(leaf, slot,
  	"invalid key objectid: has %llu expect %llu or [%llu, %llu] or %llu",
  				key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID,
  				BTRFS_FIRST_FREE_OBJECTID,
  				BTRFS_LAST_FREE_OBJECTID,
  				BTRFS_FREE_INO_OBJECTID);
  		} else {
  			dir_item_err(leaf, slot,
  "invalid location key objectid: has %llu expect %llu or [%llu, %llu] or %llu",
  				key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID,
  				BTRFS_FIRST_FREE_OBJECTID,
  				BTRFS_LAST_FREE_OBJECTID,
  				BTRFS_FREE_INO_OBJECTID);
  		}
  		return -EUCLEAN;
  	}
  	if (key->offset != 0) {
  		if (is_inode_item)
  			inode_item_err(leaf, slot,
  				       "invalid key offset: has %llu expect 0",
  				       key->offset);
  		else
  			dir_item_err(leaf, slot,
  				"invalid location key offset:has %llu expect 0",
  				key->offset);
  		return -EUCLEAN;
  	}
  	return 0;
  }
57a0e6749   Qu Wenruo   btrfs: tree-check...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
  static int check_root_key(struct extent_buffer *leaf, struct btrfs_key *key,
  			  int slot)
  {
  	struct btrfs_key item_key;
  	bool is_root_item;
  
  	btrfs_item_key_to_cpu(leaf, &item_key, slot);
  	is_root_item = (item_key.type == BTRFS_ROOT_ITEM_KEY);
  
  	/* No such tree id */
  	if (key->objectid == 0) {
  		if (is_root_item)
  			generic_err(leaf, slot, "invalid root id 0");
  		else
  			dir_item_err(leaf, slot,
  				     "invalid location key root id 0");
  		return -EUCLEAN;
  	}
  
  	/* DIR_ITEM/INDEX/INODE_REF is not allowed to point to non-fs trees */
  	if (!is_fstree(key->objectid) && !is_root_item) {
  		dir_item_err(leaf, slot,
  		"invalid location key objectid, have %llu expect [%llu, %llu]",
  				key->objectid, BTRFS_FIRST_FREE_OBJECTID,
  				BTRFS_LAST_FREE_OBJECTID);
  		return -EUCLEAN;
  	}
  
  	/*
  	 * ROOT_ITEM with non-zero offset means this is a snapshot, created at
  	 * @offset transid.
  	 * Furthermore, for location key in DIR_ITEM, its offset is always -1.
  	 *
  	 * So here we only check offset for reloc tree whose key->offset must
  	 * be a valid tree.
  	 */
  	if (key->objectid == BTRFS_TREE_RELOC_OBJECTID && key->offset == 0) {
  		generic_err(leaf, slot, "invalid root id 0 for reloc tree");
  		return -EUCLEAN;
  	}
  	return 0;
  }
ce4252c04   David Sterba   btrfs: tree-check...
460
  static int check_dir_item(struct extent_buffer *leaf,
c18679ebd   Qu Wenruo   btrfs: tree-check...
461
462
  			  struct btrfs_key *key, struct btrfs_key *prev_key,
  			  int slot)
ad7b0368f   Qu Wenruo   btrfs: tree-check...
463
  {
ce4252c04   David Sterba   btrfs: tree-check...
464
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
ad7b0368f   Qu Wenruo   btrfs: tree-check...
465
466
467
  	struct btrfs_dir_item *di;
  	u32 item_size = btrfs_item_size_nr(leaf, slot);
  	u32 cur = 0;
80d7fd1e0   Qu Wenruo   btrfs: tree-check...
468
  	if (!check_prev_ino(leaf, key, slot, prev_key))
c18679ebd   Qu Wenruo   btrfs: tree-check...
469
  		return -EUCLEAN;
ad7b0368f   Qu Wenruo   btrfs: tree-check...
470
471
  	di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
  	while (cur < item_size) {
147a097cf   Qu Wenruo   btrfs: tree-check...
472
  		struct btrfs_key location_key;
ad7b0368f   Qu Wenruo   btrfs: tree-check...
473
474
475
476
477
478
  		u32 name_len;
  		u32 data_len;
  		u32 max_name_len;
  		u32 total_size;
  		u32 name_hash;
  		u8 dir_type;
147a097cf   Qu Wenruo   btrfs: tree-check...
479
  		int ret;
ad7b0368f   Qu Wenruo   btrfs: tree-check...
480
481
482
  
  		/* header itself should not cross item boundary */
  		if (cur + sizeof(*di) > item_size) {
d98ced688   David Sterba   btrfs: tree-check...
483
  			dir_item_err(leaf, slot,
7cfad6529   Arnd Bergmann   btrfs: tree-check...
484
  		"dir item header crosses item boundary, have %zu boundary %u",
ad7b0368f   Qu Wenruo   btrfs: tree-check...
485
486
487
  				cur + sizeof(*di), item_size);
  			return -EUCLEAN;
  		}
147a097cf   Qu Wenruo   btrfs: tree-check...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  		/* Location key check */
  		btrfs_dir_item_key_to_cpu(leaf, di, &location_key);
  		if (location_key.type == BTRFS_ROOT_ITEM_KEY) {
  			ret = check_root_key(leaf, &location_key, slot);
  			if (ret < 0)
  				return ret;
  		} else if (location_key.type == BTRFS_INODE_ITEM_KEY ||
  			   location_key.type == 0) {
  			ret = check_inode_key(leaf, &location_key, slot);
  			if (ret < 0)
  				return ret;
  		} else {
  			dir_item_err(leaf, slot,
  			"invalid location key type, have %u, expect %u or %u",
  				     location_key.type, BTRFS_ROOT_ITEM_KEY,
  				     BTRFS_INODE_ITEM_KEY);
  			return -EUCLEAN;
  		}
ad7b0368f   Qu Wenruo   btrfs: tree-check...
506
507
508
  		/* dir type check */
  		dir_type = btrfs_dir_type(leaf, di);
  		if (dir_type >= BTRFS_FT_MAX) {
d98ced688   David Sterba   btrfs: tree-check...
509
  			dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
510
511
512
513
514
515
516
  			"invalid dir item type, have %u expect [0, %u)",
  				dir_type, BTRFS_FT_MAX);
  			return -EUCLEAN;
  		}
  
  		if (key->type == BTRFS_XATTR_ITEM_KEY &&
  		    dir_type != BTRFS_FT_XATTR) {
d98ced688   David Sterba   btrfs: tree-check...
517
  			dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
518
519
520
521
522
523
  		"invalid dir item type for XATTR key, have %u expect %u",
  				dir_type, BTRFS_FT_XATTR);
  			return -EUCLEAN;
  		}
  		if (dir_type == BTRFS_FT_XATTR &&
  		    key->type != BTRFS_XATTR_ITEM_KEY) {
d98ced688   David Sterba   btrfs: tree-check...
524
  			dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
525
526
527
528
529
530
531
532
533
534
535
536
  			"xattr dir type found for non-XATTR key");
  			return -EUCLEAN;
  		}
  		if (dir_type == BTRFS_FT_XATTR)
  			max_name_len = XATTR_NAME_MAX;
  		else
  			max_name_len = BTRFS_NAME_LEN;
  
  		/* Name/data length check */
  		name_len = btrfs_dir_name_len(leaf, di);
  		data_len = btrfs_dir_data_len(leaf, di);
  		if (name_len > max_name_len) {
d98ced688   David Sterba   btrfs: tree-check...
537
  			dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
538
539
540
541
  			"dir item name len too long, have %u max %u",
  				name_len, max_name_len);
  			return -EUCLEAN;
  		}
2f659546c   Qu Wenruo   btrfs: tree-check...
542
  		if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(fs_info)) {
d98ced688   David Sterba   btrfs: tree-check...
543
  			dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
544
545
  			"dir item name and data len too long, have %u max %u",
  				name_len + data_len,
2f659546c   Qu Wenruo   btrfs: tree-check...
546
  				BTRFS_MAX_XATTR_SIZE(fs_info));
ad7b0368f   Qu Wenruo   btrfs: tree-check...
547
548
549
550
  			return -EUCLEAN;
  		}
  
  		if (data_len && dir_type != BTRFS_FT_XATTR) {
d98ced688   David Sterba   btrfs: tree-check...
551
  			dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
552
553
554
555
556
557
558
559
560
  			"dir item with invalid data len, have %u expect 0",
  				data_len);
  			return -EUCLEAN;
  		}
  
  		total_size = sizeof(*di) + name_len + data_len;
  
  		/* header and name/data should not cross item boundary */
  		if (cur + total_size > item_size) {
d98ced688   David Sterba   btrfs: tree-check...
561
  			dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
562
563
564
565
566
567
568
569
570
571
572
  		"dir item data crosses item boundary, have %u boundary %u",
  				cur + total_size, item_size);
  			return -EUCLEAN;
  		}
  
  		/*
  		 * Special check for XATTR/DIR_ITEM, as key->offset is name
  		 * hash, should match its name
  		 */
  		if (key->type == BTRFS_DIR_ITEM_KEY ||
  		    key->type == BTRFS_XATTR_ITEM_KEY) {
e2683fc9d   David Sterba   btrfs: tree-check...
573
  			char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
ad7b0368f   Qu Wenruo   btrfs: tree-check...
574
575
576
577
  			read_extent_buffer(leaf, namebuf,
  					(unsigned long)(di + 1), name_len);
  			name_hash = btrfs_name_hash(namebuf, name_len);
  			if (key->offset != name_hash) {
d98ced688   David Sterba   btrfs: tree-check...
578
  				dir_item_err(leaf, slot,
ad7b0368f   Qu Wenruo   btrfs: tree-check...
579
580
581
582
583
584
585
586
587
588
  		"name hash mismatch with key, have 0x%016x expect 0x%016llx",
  					name_hash, key->offset);
  				return -EUCLEAN;
  			}
  		}
  		cur += total_size;
  		di = (struct btrfs_dir_item *)((void *)di + total_size);
  	}
  	return 0;
  }
4806bd886   David Sterba   btrfs: tree-check...
589
  __printf(3, 4)
fce466eab   Qu Wenruo   btrfs: tree-check...
590
  __cold
4806bd886   David Sterba   btrfs: tree-check...
591
  static void block_group_err(const struct extent_buffer *eb, int slot,
fce466eab   Qu Wenruo   btrfs: tree-check...
592
593
  			    const char *fmt, ...)
  {
4806bd886   David Sterba   btrfs: tree-check...
594
  	const struct btrfs_fs_info *fs_info = eb->fs_info;
fce466eab   Qu Wenruo   btrfs: tree-check...
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
  	struct btrfs_key key;
  	struct va_format vaf;
  	va_list args;
  
  	btrfs_item_key_to_cpu(eb, &key, slot);
  	va_start(args, fmt);
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	btrfs_crit(fs_info,
  	"corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV",
  		btrfs_header_level(eb) == 0 ? "leaf" : "node",
  		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
  		key.objectid, key.offset, &vaf);
  	va_end(args);
  }
af60ce2b9   David Sterba   btrfs: tree-check...
612
  static int check_block_group_item(struct extent_buffer *leaf,
fce466eab   Qu Wenruo   btrfs: tree-check...
613
614
615
616
617
618
619
620
621
  				  struct btrfs_key *key, int slot)
  {
  	struct btrfs_block_group_item bgi;
  	u32 item_size = btrfs_item_size_nr(leaf, slot);
  	u64 flags;
  	u64 type;
  
  	/*
  	 * Here we don't really care about alignment since extent allocator can
10950929e   Qu Wenruo   btrfs: tree-check...
622
  	 * handle it.  We care more about the size.
fce466eab   Qu Wenruo   btrfs: tree-check...
623
  	 */
10950929e   Qu Wenruo   btrfs: tree-check...
624
  	if (key->offset == 0) {
4806bd886   David Sterba   btrfs: tree-check...
625
  		block_group_err(leaf, slot,
10950929e   Qu Wenruo   btrfs: tree-check...
626
  				"invalid block group size 0");
fce466eab   Qu Wenruo   btrfs: tree-check...
627
628
629
630
  		return -EUCLEAN;
  	}
  
  	if (item_size != sizeof(bgi)) {
4806bd886   David Sterba   btrfs: tree-check...
631
  		block_group_err(leaf, slot,
fce466eab   Qu Wenruo   btrfs: tree-check...
632
633
634
635
636
637
638
  			"invalid item size, have %u expect %zu",
  				item_size, sizeof(bgi));
  		return -EUCLEAN;
  	}
  
  	read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot),
  			   sizeof(bgi));
de0dc456f   David Sterba   btrfs: rename blo...
639
  	if (btrfs_stack_block_group_chunk_objectid(&bgi) !=
fce466eab   Qu Wenruo   btrfs: tree-check...
640
  	    BTRFS_FIRST_CHUNK_TREE_OBJECTID) {
4806bd886   David Sterba   btrfs: tree-check...
641
  		block_group_err(leaf, slot,
fce466eab   Qu Wenruo   btrfs: tree-check...
642
  		"invalid block group chunk objectid, have %llu expect %llu",
de0dc456f   David Sterba   btrfs: rename blo...
643
  				btrfs_stack_block_group_chunk_objectid(&bgi),
fce466eab   Qu Wenruo   btrfs: tree-check...
644
645
646
  				BTRFS_FIRST_CHUNK_TREE_OBJECTID);
  		return -EUCLEAN;
  	}
de0dc456f   David Sterba   btrfs: rename blo...
647
  	if (btrfs_stack_block_group_used(&bgi) > key->offset) {
4806bd886   David Sterba   btrfs: tree-check...
648
  		block_group_err(leaf, slot,
fce466eab   Qu Wenruo   btrfs: tree-check...
649
  			"invalid block group used, have %llu expect [0, %llu)",
de0dc456f   David Sterba   btrfs: rename blo...
650
  				btrfs_stack_block_group_used(&bgi), key->offset);
fce466eab   Qu Wenruo   btrfs: tree-check...
651
652
  		return -EUCLEAN;
  	}
de0dc456f   David Sterba   btrfs: rename blo...
653
  	flags = btrfs_stack_block_group_flags(&bgi);
fce466eab   Qu Wenruo   btrfs: tree-check...
654
  	if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) {
4806bd886   David Sterba   btrfs: tree-check...
655
  		block_group_err(leaf, slot,
fce466eab   Qu Wenruo   btrfs: tree-check...
656
657
658
659
660
661
662
663
664
665
666
667
  "invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set",
  			flags & BTRFS_BLOCK_GROUP_PROFILE_MASK,
  			hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK));
  		return -EUCLEAN;
  	}
  
  	type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
  	if (type != BTRFS_BLOCK_GROUP_DATA &&
  	    type != BTRFS_BLOCK_GROUP_METADATA &&
  	    type != BTRFS_BLOCK_GROUP_SYSTEM &&
  	    type != (BTRFS_BLOCK_GROUP_METADATA |
  			   BTRFS_BLOCK_GROUP_DATA)) {
4806bd886   David Sterba   btrfs: tree-check...
668
  		block_group_err(leaf, slot,
761333f2f   Shaokun Zhang   btrfs: tree-check...
669
  "invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx",
fce466eab   Qu Wenruo   btrfs: tree-check...
670
671
672
673
674
675
676
  			type, hweight64(type),
  			BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA,
  			BTRFS_BLOCK_GROUP_SYSTEM,
  			BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA);
  		return -EUCLEAN;
  	}
  	return 0;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
677
  }
d001e4a3f   David Sterba   btrfs: tree-check...
678
  __printf(4, 5)
f11402437   Qu Wenruo   btrfs: tree-check...
679
  __cold
d001e4a3f   David Sterba   btrfs: tree-check...
680
  static void chunk_err(const struct extent_buffer *leaf,
f11402437   Qu Wenruo   btrfs: tree-check...
681
682
683
  		      const struct btrfs_chunk *chunk, u64 logical,
  		      const char *fmt, ...)
  {
d001e4a3f   David Sterba   btrfs: tree-check...
684
  	const struct btrfs_fs_info *fs_info = leaf->fs_info;
f11402437   Qu Wenruo   btrfs: tree-check...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
  	bool is_sb;
  	struct va_format vaf;
  	va_list args;
  	int i;
  	int slot = -1;
  
  	/* Only superblock eb is able to have such small offset */
  	is_sb = (leaf->start == BTRFS_SUPER_INFO_OFFSET);
  
  	if (!is_sb) {
  		/*
  		 * Get the slot number by iterating through all slots, this
  		 * would provide better readability.
  		 */
  		for (i = 0; i < btrfs_header_nritems(leaf); i++) {
  			if (btrfs_item_ptr_offset(leaf, i) ==
  					(unsigned long)chunk) {
  				slot = i;
  				break;
  			}
  		}
  	}
  	va_start(args, fmt);
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	if (is_sb)
  		btrfs_crit(fs_info,
  		"corrupt superblock syschunk array: chunk_start=%llu, %pV",
  			   logical, &vaf);
  	else
  		btrfs_crit(fs_info,
  	"corrupt leaf: root=%llu block=%llu slot=%d chunk_start=%llu, %pV",
  			   BTRFS_CHUNK_TREE_OBJECTID, leaf->start, slot,
  			   logical, &vaf);
  	va_end(args);
  }
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
722
723
724
  /*
   * The common chunk check which could also work on super block sys chunk array.
   *
bf871c3b4   Qu Wenruo   btrfs: tree-check...
725
   * Return -EUCLEAN if anything is corrupted.
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
726
727
   * Return 0 if everything is OK.
   */
ddaf1d5ae   David Sterba   btrfs: get fs_inf...
728
  int btrfs_check_chunk_valid(struct extent_buffer *leaf,
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
729
730
  			    struct btrfs_chunk *chunk, u64 logical)
  {
ddaf1d5ae   David Sterba   btrfs: get fs_inf...
731
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
732
  	u64 length;
41b5ec745   Su Yue   btrfs: tree-check...
733
  	u64 chunk_end;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
734
735
736
737
738
739
  	u64 stripe_len;
  	u16 num_stripes;
  	u16 sub_stripes;
  	u64 type;
  	u64 features;
  	bool mixed = false;
85d07fbe0   Daniel Xu   btrfs: tree-check...
740
741
742
  	int raid_index;
  	int nparity;
  	int ncopies;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
743
744
745
746
747
748
  
  	length = btrfs_chunk_length(leaf, chunk);
  	stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
  	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
  	sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
  	type = btrfs_chunk_type(leaf, chunk);
85d07fbe0   Daniel Xu   btrfs: tree-check...
749
750
751
  	raid_index = btrfs_bg_flags_to_raid_index(type);
  	ncopies = btrfs_raid_array[raid_index].ncopies;
  	nparity = btrfs_raid_array[raid_index].nparity;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
752
753
  
  	if (!num_stripes) {
d001e4a3f   David Sterba   btrfs: tree-check...
754
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
755
  			  "invalid chunk num_stripes, have %u", num_stripes);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
756
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
757
  	}
85d07fbe0   Daniel Xu   btrfs: tree-check...
758
759
760
761
762
763
764
765
766
767
768
769
  	if (num_stripes < ncopies) {
  		chunk_err(leaf, chunk, logical,
  			  "invalid chunk num_stripes < ncopies, have %u < %d",
  			  num_stripes, ncopies);
  		return -EUCLEAN;
  	}
  	if (nparity && num_stripes == nparity) {
  		chunk_err(leaf, chunk, logical,
  			  "invalid chunk num_stripes == nparity, have %u == %d",
  			  num_stripes, nparity);
  		return -EUCLEAN;
  	}
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
770
  	if (!IS_ALIGNED(logical, fs_info->sectorsize)) {
d001e4a3f   David Sterba   btrfs: tree-check...
771
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
772
773
  		"invalid chunk logical, have %llu should aligned to %u",
  			  logical, fs_info->sectorsize);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
774
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
775
776
  	}
  	if (btrfs_chunk_sector_size(leaf, chunk) != fs_info->sectorsize) {
d001e4a3f   David Sterba   btrfs: tree-check...
777
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
778
779
780
  			  "invalid chunk sectorsize, have %u expect %u",
  			  btrfs_chunk_sector_size(leaf, chunk),
  			  fs_info->sectorsize);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
781
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
782
783
  	}
  	if (!length || !IS_ALIGNED(length, fs_info->sectorsize)) {
d001e4a3f   David Sterba   btrfs: tree-check...
784
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
785
  			  "invalid chunk length, have %llu", length);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
786
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
787
  	}
41b5ec745   Su Yue   btrfs: tree-check...
788
789
790
791
792
793
  	if (unlikely(check_add_overflow(logical, length, &chunk_end))) {
  		chunk_err(leaf, chunk, logical,
  "invalid chunk logical start and length, have logical start %llu length %llu",
  			  logical, length);
  		return -EUCLEAN;
  	}
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
794
  	if (!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN) {
d001e4a3f   David Sterba   btrfs: tree-check...
795
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
796
  			  "invalid chunk stripe length: %llu",
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
797
  			  stripe_len);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
798
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
799
800
801
  	}
  	if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
  	    type) {
d001e4a3f   David Sterba   btrfs: tree-check...
802
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
803
  			  "unrecognized chunk type: 0x%llx",
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
804
805
806
  			  ~(BTRFS_BLOCK_GROUP_TYPE_MASK |
  			    BTRFS_BLOCK_GROUP_PROFILE_MASK) &
  			  btrfs_chunk_type(leaf, chunk));
bf871c3b4   Qu Wenruo   btrfs: tree-check...
807
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
808
  	}
c1499166d   David Sterba   btrfs: use has_si...
809
  	if (!has_single_bit_set(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) &&
80e46cf22   Qu Wenruo   btrfs: tree-check...
810
  	    (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0) {
d001e4a3f   David Sterba   btrfs: tree-check...
811
  		chunk_err(leaf, chunk, logical,
80e46cf22   Qu Wenruo   btrfs: tree-check...
812
813
814
815
  		"invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set",
  			  type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
  		return -EUCLEAN;
  	}
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
816
  	if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) {
d001e4a3f   David Sterba   btrfs: tree-check...
817
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
818
819
  	"missing chunk type flag, have 0x%llx one bit must be set in 0x%llx",
  			  type, BTRFS_BLOCK_GROUP_TYPE_MASK);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
820
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
821
822
823
824
  	}
  
  	if ((type & BTRFS_BLOCK_GROUP_SYSTEM) &&
  	    (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) {
d001e4a3f   David Sterba   btrfs: tree-check...
825
  		chunk_err(leaf, chunk, logical,
f11402437   Qu Wenruo   btrfs: tree-check...
826
827
  			  "system chunk with data or metadata type: 0x%llx",
  			  type);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
828
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
829
830
831
832
833
834
835
836
837
  	}
  
  	features = btrfs_super_incompat_flags(fs_info->super_copy);
  	if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
  		mixed = true;
  
  	if (!mixed) {
  		if ((type & BTRFS_BLOCK_GROUP_METADATA) &&
  		    (type & BTRFS_BLOCK_GROUP_DATA)) {
d001e4a3f   David Sterba   btrfs: tree-check...
838
  			chunk_err(leaf, chunk, logical,
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
839
  			"mixed chunk type in non-mixed mode: 0x%llx", type);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
840
  			return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
841
842
843
844
845
846
847
848
849
  		}
  	}
  
  	if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
  	    (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) ||
  	    (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
  	    (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
  	    (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) ||
  	    ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && num_stripes != 1)) {
d001e4a3f   David Sterba   btrfs: tree-check...
850
  		chunk_err(leaf, chunk, logical,
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
851
852
853
  			"invalid num_stripes:sub_stripes %u:%u for profile %llu",
  			num_stripes, sub_stripes,
  			type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
bf871c3b4   Qu Wenruo   btrfs: tree-check...
854
  		return -EUCLEAN;
82fc28fbe   Qu Wenruo   btrfs: Move btrfs...
855
856
857
  	}
  
  	return 0;
fce466eab   Qu Wenruo   btrfs: tree-check...
858
  }
f6d2a5c26   Qu Wenruo   btrfs: tree-check...
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
  /*
   * Enhanced version of chunk item checker.
   *
   * The common btrfs_check_chunk_valid() doesn't check item size since it needs
   * to work on super block sys_chunk_array which doesn't have full item ptr.
   */
  static int check_leaf_chunk_item(struct extent_buffer *leaf,
  				 struct btrfs_chunk *chunk,
  				 struct btrfs_key *key, int slot)
  {
  	int num_stripes;
  
  	if (btrfs_item_size_nr(leaf, slot) < sizeof(struct btrfs_chunk)) {
  		chunk_err(leaf, chunk, key->offset,
  			"invalid chunk item size: have %u expect [%zu, %u)",
  			btrfs_item_size_nr(leaf, slot),
  			sizeof(struct btrfs_chunk),
  			BTRFS_LEAF_DATA_SIZE(leaf->fs_info));
  		return -EUCLEAN;
  	}
  
  	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
  	/* Let btrfs_check_chunk_valid() handle this error type */
  	if (num_stripes == 0)
  		goto out;
  
  	if (btrfs_chunk_item_size(num_stripes) !=
  	    btrfs_item_size_nr(leaf, slot)) {
  		chunk_err(leaf, chunk, key->offset,
  			"invalid chunk item size: have %u expect %lu",
  			btrfs_item_size_nr(leaf, slot),
  			btrfs_chunk_item_size(num_stripes));
  		return -EUCLEAN;
  	}
  out:
  	return btrfs_check_chunk_valid(leaf, chunk, key->offset);
  }
5617ed80c   David Sterba   btrfs: tree-check...
896
  __printf(3, 4)
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
897
  __cold
5617ed80c   David Sterba   btrfs: tree-check...
898
  static void dev_item_err(const struct extent_buffer *eb, int slot,
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
899
900
901
902
903
904
905
906
907
908
909
  			 const char *fmt, ...)
  {
  	struct btrfs_key key;
  	struct va_format vaf;
  	va_list args;
  
  	btrfs_item_key_to_cpu(eb, &key, slot);
  	va_start(args, fmt);
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
5617ed80c   David Sterba   btrfs: tree-check...
910
  	btrfs_crit(eb->fs_info,
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
911
912
913
914
915
916
  	"corrupt %s: root=%llu block=%llu slot=%d devid=%llu %pV",
  		btrfs_header_level(eb) == 0 ? "leaf" : "node",
  		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
  		key.objectid, &vaf);
  	va_end(args);
  }
412a23127   David Sterba   btrfs: tree-check...
917
  static int check_dev_item(struct extent_buffer *leaf,
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
918
919
920
  			  struct btrfs_key *key, int slot)
  {
  	struct btrfs_dev_item *ditem;
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
921
922
  
  	if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) {
5617ed80c   David Sterba   btrfs: tree-check...
923
  		dev_item_err(leaf, slot,
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
924
925
926
927
  			     "invalid objectid: has=%llu expect=%llu",
  			     key->objectid, BTRFS_DEV_ITEMS_OBJECTID);
  		return -EUCLEAN;
  	}
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
928
929
  	ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item);
  	if (btrfs_device_id(leaf, ditem) != key->offset) {
5617ed80c   David Sterba   btrfs: tree-check...
930
  		dev_item_err(leaf, slot,
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
931
932
933
934
935
936
937
938
939
940
941
942
  			     "devid mismatch: key has=%llu item has=%llu",
  			     key->offset, btrfs_device_id(leaf, ditem));
  		return -EUCLEAN;
  	}
  
  	/*
  	 * For device total_bytes, we don't have reliable way to check it, as
  	 * it can be 0 for device removal. Device size check can only be done
  	 * by dev extents check.
  	 */
  	if (btrfs_device_bytes_used(leaf, ditem) >
  	    btrfs_device_total_bytes(leaf, ditem)) {
5617ed80c   David Sterba   btrfs: tree-check...
943
  		dev_item_err(leaf, slot,
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
944
945
946
947
948
949
950
951
952
953
954
  			     "invalid bytes used: have %llu expect [0, %llu]",
  			     btrfs_device_bytes_used(leaf, ditem),
  			     btrfs_device_total_bytes(leaf, ditem));
  		return -EUCLEAN;
  	}
  	/*
  	 * Remaining members like io_align/type/gen/dev_group aren't really
  	 * utilized.  Skip them to make later usage of them easier.
  	 */
  	return 0;
  }
39e57f495   David Sterba   btrfs: tree-check...
955
  static int check_inode_item(struct extent_buffer *leaf,
496245cac   Qu Wenruo   btrfs: tree-check...
956
957
  			    struct btrfs_key *key, int slot)
  {
39e57f495   David Sterba   btrfs: tree-check...
958
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
496245cac   Qu Wenruo   btrfs: tree-check...
959
960
961
962
  	struct btrfs_inode_item *iitem;
  	u64 super_gen = btrfs_super_generation(fs_info->super_copy);
  	u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777);
  	u32 mode;
c23c77b09   Qu Wenruo   btrfs: tree-check...
963
964
965
966
967
  	int ret;
  
  	ret = check_inode_key(leaf, key, slot);
  	if (ret < 0)
  		return ret;
496245cac   Qu Wenruo   btrfs: tree-check...
968

496245cac   Qu Wenruo   btrfs: tree-check...
969
970
971
972
  	iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item);
  
  	/* Here we use super block generation + 1 to handle log tree */
  	if (btrfs_inode_generation(leaf, iitem) > super_gen + 1) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
973
  		inode_item_err(leaf, slot,
496245cac   Qu Wenruo   btrfs: tree-check...
974
975
976
977
978
979
980
  			"invalid inode generation: has %llu expect (0, %llu]",
  			       btrfs_inode_generation(leaf, iitem),
  			       super_gen + 1);
  		return -EUCLEAN;
  	}
  	/* Note for ROOT_TREE_DIR_ITEM, mkfs could set its transid 0 */
  	if (btrfs_inode_transid(leaf, iitem) > super_gen + 1) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
981
  		inode_item_err(leaf, slot,
f96d6960a   Qu Wenruo   btrfs: tree-check...
982
  			"invalid inode transid: has %llu expect [0, %llu]",
496245cac   Qu Wenruo   btrfs: tree-check...
983
984
985
986
987
988
989
990
991
992
993
  			       btrfs_inode_transid(leaf, iitem), super_gen + 1);
  		return -EUCLEAN;
  	}
  
  	/*
  	 * For size and nbytes it's better not to be too strict, as for dir
  	 * item its size/nbytes can easily get wrong, but doesn't affect
  	 * anything in the fs. So here we skip the check.
  	 */
  	mode = btrfs_inode_mode(leaf, iitem);
  	if (mode & ~valid_mask) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
994
  		inode_item_err(leaf, slot,
496245cac   Qu Wenruo   btrfs: tree-check...
995
996
997
998
999
1000
  			       "unknown mode bit detected: 0x%x",
  			       mode & ~valid_mask);
  		return -EUCLEAN;
  	}
  
  	/*
c1499166d   David Sterba   btrfs: use has_si...
1001
1002
1003
  	 * S_IFMT is not bit mapped so we can't completely rely on
  	 * is_power_of_2/has_single_bit_set, but it can save us from checking
  	 * FIFO/CHR/DIR/REG.  Only needs to check BLK, LNK and SOCKS
496245cac   Qu Wenruo   btrfs: tree-check...
1004
  	 */
c1499166d   David Sterba   btrfs: use has_si...
1005
  	if (!has_single_bit_set(mode & S_IFMT)) {
496245cac   Qu Wenruo   btrfs: tree-check...
1006
  		if (!S_ISLNK(mode) && !S_ISBLK(mode) && !S_ISSOCK(mode)) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
1007
  			inode_item_err(leaf, slot,
496245cac   Qu Wenruo   btrfs: tree-check...
1008
1009
1010
1011
1012
1013
  			"invalid mode: has 0%o expect valid S_IF* bit(s)",
  				       mode & S_IFMT);
  			return -EUCLEAN;
  		}
  	}
  	if (S_ISDIR(mode) && btrfs_inode_nlink(leaf, iitem) > 1) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
1014
  		inode_item_err(leaf, slot,
496245cac   Qu Wenruo   btrfs: tree-check...
1015
1016
1017
1018
1019
  		       "invalid nlink: has %u expect no more than 1 for dir",
  			btrfs_inode_nlink(leaf, iitem));
  		return -EUCLEAN;
  	}
  	if (btrfs_inode_flags(leaf, iitem) & ~BTRFS_INODE_FLAG_MASK) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
1020
  		inode_item_err(leaf, slot,
496245cac   Qu Wenruo   btrfs: tree-check...
1021
1022
1023
1024
1025
1026
1027
  			       "unknown flags detected: 0x%llx",
  			       btrfs_inode_flags(leaf, iitem) &
  			       ~BTRFS_INODE_FLAG_MASK);
  		return -EUCLEAN;
  	}
  	return 0;
  }
259ee7754   Qu Wenruo   btrfs: tree-check...
1028
1029
1030
1031
  static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key,
  			   int slot)
  {
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
1465af12e   Qu Wenruo   btrfs: tree-check...
1032
  	struct btrfs_root_item ri = { 0 };
259ee7754   Qu Wenruo   btrfs: tree-check...
1033
1034
  	const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY |
  				     BTRFS_ROOT_SUBVOL_DEAD;
57a0e6749   Qu Wenruo   btrfs: tree-check...
1035
  	int ret;
259ee7754   Qu Wenruo   btrfs: tree-check...
1036

57a0e6749   Qu Wenruo   btrfs: tree-check...
1037
1038
1039
  	ret = check_root_key(leaf, key, slot);
  	if (ret < 0)
  		return ret;
259ee7754   Qu Wenruo   btrfs: tree-check...
1040

1465af12e   Qu Wenruo   btrfs: tree-check...
1041
1042
  	if (btrfs_item_size_nr(leaf, slot) != sizeof(ri) &&
  	    btrfs_item_size_nr(leaf, slot) != btrfs_legacy_root_item_size()) {
259ee7754   Qu Wenruo   btrfs: tree-check...
1043
  		generic_err(leaf, slot,
1465af12e   Qu Wenruo   btrfs: tree-check...
1044
1045
1046
  			    "invalid root item size, have %u expect %zu or %u",
  			    btrfs_item_size_nr(leaf, slot), sizeof(ri),
  			    btrfs_legacy_root_item_size());
1a49a97df   Daniel Xu   btrfs: tree-check...
1047
  		return -EUCLEAN;
259ee7754   Qu Wenruo   btrfs: tree-check...
1048
  	}
1465af12e   Qu Wenruo   btrfs: tree-check...
1049
1050
1051
1052
1053
  	/*
  	 * For legacy root item, the members starting at generation_v2 will be
  	 * all filled with 0.
  	 * And since we allow geneartion_v2 as 0, it will still pass the check.
  	 */
259ee7754   Qu Wenruo   btrfs: tree-check...
1054
  	read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot),
1465af12e   Qu Wenruo   btrfs: tree-check...
1055
  			   btrfs_item_size_nr(leaf, slot));
259ee7754   Qu Wenruo   btrfs: tree-check...
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
  
  	/* Generation related */
  	if (btrfs_root_generation(&ri) >
  	    btrfs_super_generation(fs_info->super_copy) + 1) {
  		generic_err(leaf, slot,
  			"invalid root generation, have %llu expect (0, %llu]",
  			    btrfs_root_generation(&ri),
  			    btrfs_super_generation(fs_info->super_copy) + 1);
  		return -EUCLEAN;
  	}
  	if (btrfs_root_generation_v2(&ri) >
  	    btrfs_super_generation(fs_info->super_copy) + 1) {
  		generic_err(leaf, slot,
  		"invalid root v2 generation, have %llu expect (0, %llu]",
  			    btrfs_root_generation_v2(&ri),
  			    btrfs_super_generation(fs_info->super_copy) + 1);
  		return -EUCLEAN;
  	}
  	if (btrfs_root_last_snapshot(&ri) >
  	    btrfs_super_generation(fs_info->super_copy) + 1) {
  		generic_err(leaf, slot,
  		"invalid root last_snapshot, have %llu expect (0, %llu]",
  			    btrfs_root_last_snapshot(&ri),
  			    btrfs_super_generation(fs_info->super_copy) + 1);
  		return -EUCLEAN;
  	}
  
  	/* Alignment and level check */
  	if (!IS_ALIGNED(btrfs_root_bytenr(&ri), fs_info->sectorsize)) {
  		generic_err(leaf, slot,
  		"invalid root bytenr, have %llu expect to be aligned to %u",
  			    btrfs_root_bytenr(&ri), fs_info->sectorsize);
  		return -EUCLEAN;
  	}
  	if (btrfs_root_level(&ri) >= BTRFS_MAX_LEVEL) {
  		generic_err(leaf, slot,
  			    "invalid root level, have %u expect [0, %u]",
  			    btrfs_root_level(&ri), BTRFS_MAX_LEVEL - 1);
  		return -EUCLEAN;
  	}
  	if (ri.drop_level >= BTRFS_MAX_LEVEL) {
  		generic_err(leaf, slot,
  			    "invalid root level, have %u expect [0, %u]",
  			    ri.drop_level, BTRFS_MAX_LEVEL - 1);
  		return -EUCLEAN;
  	}
  
  	/* Flags check */
  	if (btrfs_root_flags(&ri) & ~valid_root_flags) {
  		generic_err(leaf, slot,
  			    "invalid root flags, have 0x%llx expect mask 0x%llx",
  			    btrfs_root_flags(&ri), valid_root_flags);
  		return -EUCLEAN;
  	}
  	return 0;
  }
f82d1c7ca   Qu Wenruo   btrfs: tree-check...
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
  __printf(3,4)
  __cold
  static void extent_err(const struct extent_buffer *eb, int slot,
  		       const char *fmt, ...)
  {
  	struct btrfs_key key;
  	struct va_format vaf;
  	va_list args;
  	u64 bytenr;
  	u64 len;
  
  	btrfs_item_key_to_cpu(eb, &key, slot);
  	bytenr = key.objectid;
e2406a6f1   Qu Wenruo   btrfs: tree-check...
1125
1126
1127
  	if (key.type == BTRFS_METADATA_ITEM_KEY ||
  	    key.type == BTRFS_TREE_BLOCK_REF_KEY ||
  	    key.type == BTRFS_SHARED_BLOCK_REF_KEY)
f82d1c7ca   Qu Wenruo   btrfs: tree-check...
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
  		len = eb->fs_info->nodesize;
  	else
  		len = key.offset;
  	va_start(args, fmt);
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	btrfs_crit(eb->fs_info,
  	"corrupt %s: block=%llu slot=%d extent bytenr=%llu len=%llu %pV",
  		btrfs_header_level(eb) == 0 ? "leaf" : "node",
  		eb->start, slot, bytenr, len, &vaf);
  	va_end(args);
  }
  
  static int check_extent_item(struct extent_buffer *leaf,
  			     struct btrfs_key *key, int slot)
  {
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
  	struct btrfs_extent_item *ei;
  	bool is_tree_block = false;
  	unsigned long ptr;	/* Current pointer inside inline refs */
  	unsigned long end;	/* Extent item end */
  	const u32 item_size = btrfs_item_size_nr(leaf, slot);
  	u64 flags;
  	u64 generation;
  	u64 total_refs;		/* Total refs in btrfs_extent_item */
  	u64 inline_refs = 0;	/* found total inline refs */
  
  	if (key->type == BTRFS_METADATA_ITEM_KEY &&
  	    !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) {
  		generic_err(leaf, slot,
  "invalid key type, METADATA_ITEM type invalid when SKINNY_METADATA feature disabled");
  		return -EUCLEAN;
  	}
  	/* key->objectid is the bytenr for both key types */
  	if (!IS_ALIGNED(key->objectid, fs_info->sectorsize)) {
  		generic_err(leaf, slot,
  		"invalid key objectid, have %llu expect to be aligned to %u",
  			   key->objectid, fs_info->sectorsize);
  		return -EUCLEAN;
  	}
  
  	/* key->offset is tree level for METADATA_ITEM_KEY */
  	if (key->type == BTRFS_METADATA_ITEM_KEY &&
  	    key->offset >= BTRFS_MAX_LEVEL) {
  		extent_err(leaf, slot,
  			   "invalid tree level, have %llu expect [0, %u]",
  			   key->offset, BTRFS_MAX_LEVEL - 1);
  		return -EUCLEAN;
  	}
  
  	/*
  	 * EXTENT/METADATA_ITEM consists of:
  	 * 1) One btrfs_extent_item
  	 *    Records the total refs, type and generation of the extent.
  	 *
  	 * 2) One btrfs_tree_block_info (for EXTENT_ITEM and tree backref only)
  	 *    Records the first key and level of the tree block.
  	 *
  	 * 2) Zero or more btrfs_extent_inline_ref(s)
  	 *    Each inline ref has one btrfs_extent_inline_ref shows:
  	 *    2.1) The ref type, one of the 4
  	 *         TREE_BLOCK_REF	Tree block only
  	 *         SHARED_BLOCK_REF	Tree block only
  	 *         EXTENT_DATA_REF	Data only
  	 *         SHARED_DATA_REF	Data only
  	 *    2.2) Ref type specific data
  	 *         Either using btrfs_extent_inline_ref::offset, or specific
  	 *         data structure.
  	 */
  	if (item_size < sizeof(*ei)) {
  		extent_err(leaf, slot,
  			   "invalid item size, have %u expect [%zu, %u)",
  			   item_size, sizeof(*ei),
  			   BTRFS_LEAF_DATA_SIZE(fs_info));
  		return -EUCLEAN;
  	}
  	end = item_size + btrfs_item_ptr_offset(leaf, slot);
  
  	/* Checks against extent_item */
  	ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
  	flags = btrfs_extent_flags(leaf, ei);
  	total_refs = btrfs_extent_refs(leaf, ei);
  	generation = btrfs_extent_generation(leaf, ei);
  	if (generation > btrfs_super_generation(fs_info->super_copy) + 1) {
  		extent_err(leaf, slot,
  			   "invalid generation, have %llu expect (0, %llu]",
  			   generation,
  			   btrfs_super_generation(fs_info->super_copy) + 1);
  		return -EUCLEAN;
  	}
c1499166d   David Sterba   btrfs: use has_si...
1220
1221
  	if (!has_single_bit_set(flags & (BTRFS_EXTENT_FLAG_DATA |
  					 BTRFS_EXTENT_FLAG_TREE_BLOCK))) {
f82d1c7ca   Qu Wenruo   btrfs: tree-check...
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
  		extent_err(leaf, slot,
  		"invalid extent flag, have 0x%llx expect 1 bit set in 0x%llx",
  			flags, BTRFS_EXTENT_FLAG_DATA |
  			BTRFS_EXTENT_FLAG_TREE_BLOCK);
  		return -EUCLEAN;
  	}
  	is_tree_block = !!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK);
  	if (is_tree_block) {
  		if (key->type == BTRFS_EXTENT_ITEM_KEY &&
  		    key->offset != fs_info->nodesize) {
  			extent_err(leaf, slot,
  				   "invalid extent length, have %llu expect %u",
  				   key->offset, fs_info->nodesize);
  			return -EUCLEAN;
  		}
  	} else {
  		if (key->type != BTRFS_EXTENT_ITEM_KEY) {
  			extent_err(leaf, slot,
  			"invalid key type, have %u expect %u for data backref",
  				   key->type, BTRFS_EXTENT_ITEM_KEY);
  			return -EUCLEAN;
  		}
  		if (!IS_ALIGNED(key->offset, fs_info->sectorsize)) {
  			extent_err(leaf, slot,
  			"invalid extent length, have %llu expect aligned to %u",
  				   key->offset, fs_info->sectorsize);
  			return -EUCLEAN;
  		}
  	}
  	ptr = (unsigned long)(struct btrfs_extent_item *)(ei + 1);
  
  	/* Check the special case of btrfs_tree_block_info */
  	if (is_tree_block && key->type != BTRFS_METADATA_ITEM_KEY) {
  		struct btrfs_tree_block_info *info;
  
  		info = (struct btrfs_tree_block_info *)ptr;
  		if (btrfs_tree_block_level(leaf, info) >= BTRFS_MAX_LEVEL) {
  			extent_err(leaf, slot,
  			"invalid tree block info level, have %u expect [0, %u]",
  				   btrfs_tree_block_level(leaf, info),
  				   BTRFS_MAX_LEVEL - 1);
  			return -EUCLEAN;
  		}
  		ptr = (unsigned long)(struct btrfs_tree_block_info *)(info + 1);
  	}
  
  	/* Check inline refs */
  	while (ptr < end) {
  		struct btrfs_extent_inline_ref *iref;
  		struct btrfs_extent_data_ref *dref;
  		struct btrfs_shared_data_ref *sref;
  		u64 dref_offset;
  		u64 inline_offset;
  		u8 inline_type;
  
  		if (ptr + sizeof(*iref) > end) {
  			extent_err(leaf, slot,
  "inline ref item overflows extent item, ptr %lu iref size %zu end %lu",
  				   ptr, sizeof(*iref), end);
  			return -EUCLEAN;
  		}
  		iref = (struct btrfs_extent_inline_ref *)ptr;
  		inline_type = btrfs_extent_inline_ref_type(leaf, iref);
  		inline_offset = btrfs_extent_inline_ref_offset(leaf, iref);
  		if (ptr + btrfs_extent_inline_ref_size(inline_type) > end) {
  			extent_err(leaf, slot,
  "inline ref item overflows extent item, ptr %lu iref size %u end %lu",
  				   ptr, inline_type, end);
  			return -EUCLEAN;
  		}
  
  		switch (inline_type) {
  		/* inline_offset is subvolid of the owner, no need to check */
  		case BTRFS_TREE_BLOCK_REF_KEY:
  			inline_refs++;
  			break;
  		/* Contains parent bytenr */
  		case BTRFS_SHARED_BLOCK_REF_KEY:
  			if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) {
  				extent_err(leaf, slot,
  		"invalid tree parent bytenr, have %llu expect aligned to %u",
  					   inline_offset, fs_info->sectorsize);
  				return -EUCLEAN;
  			}
  			inline_refs++;
  			break;
  		/*
  		 * Contains owner subvolid, owner key objectid, adjusted offset.
  		 * The only obvious corruption can happen in that offset.
  		 */
  		case BTRFS_EXTENT_DATA_REF_KEY:
  			dref = (struct btrfs_extent_data_ref *)(&iref->offset);
  			dref_offset = btrfs_extent_data_ref_offset(leaf, dref);
  			if (!IS_ALIGNED(dref_offset, fs_info->sectorsize)) {
  				extent_err(leaf, slot,
  		"invalid data ref offset, have %llu expect aligned to %u",
  					   dref_offset, fs_info->sectorsize);
  				return -EUCLEAN;
  			}
  			inline_refs += btrfs_extent_data_ref_count(leaf, dref);
  			break;
  		/* Contains parent bytenr and ref count */
  		case BTRFS_SHARED_DATA_REF_KEY:
  			sref = (struct btrfs_shared_data_ref *)(iref + 1);
  			if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) {
  				extent_err(leaf, slot,
  		"invalid data parent bytenr, have %llu expect aligned to %u",
  					   inline_offset, fs_info->sectorsize);
  				return -EUCLEAN;
  			}
  			inline_refs += btrfs_shared_data_ref_count(leaf, sref);
  			break;
  		default:
  			extent_err(leaf, slot, "unknown inline ref type: %u",
  				   inline_type);
  			return -EUCLEAN;
  		}
  		ptr += btrfs_extent_inline_ref_size(inline_type);
  	}
  	/* No padding is allowed */
  	if (ptr != end) {
  		extent_err(leaf, slot,
  			   "invalid extent item size, padding bytes found");
  		return -EUCLEAN;
  	}
  
  	/* Finally, check the inline refs against total refs */
  	if (inline_refs > total_refs) {
  		extent_err(leaf, slot,
  			"invalid extent refs, have %llu expect >= inline %llu",
  			   total_refs, inline_refs);
  		return -EUCLEAN;
  	}
  	return 0;
  }
e2406a6f1   Qu Wenruo   btrfs: tree-check...
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
  static int check_simple_keyed_refs(struct extent_buffer *leaf,
  				   struct btrfs_key *key, int slot)
  {
  	u32 expect_item_size = 0;
  
  	if (key->type == BTRFS_SHARED_DATA_REF_KEY)
  		expect_item_size = sizeof(struct btrfs_shared_data_ref);
  
  	if (btrfs_item_size_nr(leaf, slot) != expect_item_size) {
  		generic_err(leaf, slot,
  		"invalid item size, have %u expect %u for key type %u",
  			    btrfs_item_size_nr(leaf, slot),
  			    expect_item_size, key->type);
  		return -EUCLEAN;
  	}
  	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;
  	}
  	if (key->type != BTRFS_TREE_BLOCK_REF_KEY &&
  	    !IS_ALIGNED(key->offset, leaf->fs_info->sectorsize)) {
  		extent_err(leaf, slot,
  		"invalid tree parent bytenr, have %llu expect aligned to %u",
  			   key->offset, leaf->fs_info->sectorsize);
  		return -EUCLEAN;
  	}
  	return 0;
  }
0785a9aac   Qu Wenruo   btrfs: tree-check...
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
  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);
6d06b0ad9   David Sterba   btrfs: tree-check...
1399
  		return -EUCLEAN;
0785a9aac   Qu Wenruo   btrfs: tree-check...
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
  	}
  	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);
6d06b0ad9   David Sterba   btrfs: tree-check...
1428
  			return -EUCLEAN;
0785a9aac   Qu Wenruo   btrfs: tree-check...
1429
1430
1431
1432
  		}
  	}
  	return 0;
  }
c3053ebb0   Qu Wenruo   btrfs: tree-check...
1433
1434
  #define inode_ref_err(eb, slot, fmt, args...)			\
  	inode_item_err(eb, slot, fmt, ##args)
71bf92a9b   Qu Wenruo   btrfs: tree-check...
1435
1436
1437
1438
1439
1440
1441
  static int check_inode_ref(struct extent_buffer *leaf,
  			   struct btrfs_key *key, struct btrfs_key *prev_key,
  			   int slot)
  {
  	struct btrfs_inode_ref *iref;
  	unsigned long ptr;
  	unsigned long end;
80d7fd1e0   Qu Wenruo   btrfs: tree-check...
1442
1443
  	if (!check_prev_ino(leaf, key, slot, prev_key))
  		return -EUCLEAN;
71bf92a9b   Qu Wenruo   btrfs: tree-check...
1444
1445
  	/* namelen can't be 0, so item_size == sizeof() is also invalid */
  	if (btrfs_item_size_nr(leaf, slot) <= sizeof(*iref)) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
1446
  		inode_ref_err(leaf, slot,
71bf92a9b   Qu Wenruo   btrfs: tree-check...
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
  			"invalid item size, have %u expect (%zu, %u)",
  			btrfs_item_size_nr(leaf, slot),
  			sizeof(*iref), BTRFS_LEAF_DATA_SIZE(leaf->fs_info));
  		return -EUCLEAN;
  	}
  
  	ptr = btrfs_item_ptr_offset(leaf, slot);
  	end = ptr + btrfs_item_size_nr(leaf, slot);
  	while (ptr < end) {
  		u16 namelen;
  
  		if (ptr + sizeof(iref) > end) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
1459
  			inode_ref_err(leaf, slot,
71bf92a9b   Qu Wenruo   btrfs: tree-check...
1460
1461
1462
1463
1464
1465
1466
1467
  			"inode ref overflow, ptr %lu end %lu inode_ref_size %zu",
  				ptr, end, sizeof(iref));
  			return -EUCLEAN;
  		}
  
  		iref = (struct btrfs_inode_ref *)ptr;
  		namelen = btrfs_inode_ref_name_len(leaf, iref);
  		if (ptr + sizeof(*iref) + namelen > end) {
c3053ebb0   Qu Wenruo   btrfs: tree-check...
1468
  			inode_ref_err(leaf, slot,
71bf92a9b   Qu Wenruo   btrfs: tree-check...
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
  				"inode ref overflow, ptr %lu end %lu namelen %u",
  				ptr, end, namelen);
  			return -EUCLEAN;
  		}
  
  		/*
  		 * NOTE: In theory we should record all found index numbers
  		 * to find any duplicated indexes, but that will be too time
  		 * consuming for inodes with too many hard links.
  		 */
  		ptr += sizeof(*iref) + namelen;
  	}
  	return 0;
  }
ad7b0368f   Qu Wenruo   btrfs: tree-check...
1483
  /*
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1484
1485
   * Common point to switch the item-specific validation.
   */
0076bc89a   David Sterba   btrfs: tree-check...
1486
  static int check_leaf_item(struct extent_buffer *leaf,
4e9845eff   Filipe Manana   Btrfs: tree-check...
1487
1488
  			   struct btrfs_key *key, int slot,
  			   struct btrfs_key *prev_key)
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1489
1490
  {
  	int ret = 0;
075cb3c78   Qu Wenruo   btrfs: tree-check...
1491
  	struct btrfs_chunk *chunk;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1492
1493
1494
  
  	switch (key->type) {
  	case BTRFS_EXTENT_DATA_KEY:
4e9845eff   Filipe Manana   Btrfs: tree-check...
1495
  		ret = check_extent_data_item(leaf, key, slot, prev_key);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1496
1497
  		break;
  	case BTRFS_EXTENT_CSUM_KEY:
ad1d8c439   Filipe Manana   Btrfs: make tree ...
1498
  		ret = check_csum_item(leaf, key, slot, prev_key);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1499
  		break;
ad7b0368f   Qu Wenruo   btrfs: tree-check...
1500
1501
1502
  	case BTRFS_DIR_ITEM_KEY:
  	case BTRFS_DIR_INDEX_KEY:
  	case BTRFS_XATTR_ITEM_KEY:
c18679ebd   Qu Wenruo   btrfs: tree-check...
1503
  		ret = check_dir_item(leaf, key, prev_key, slot);
ad7b0368f   Qu Wenruo   btrfs: tree-check...
1504
  		break;
71bf92a9b   Qu Wenruo   btrfs: tree-check...
1505
1506
1507
  	case BTRFS_INODE_REF_KEY:
  		ret = check_inode_ref(leaf, key, prev_key, slot);
  		break;
fce466eab   Qu Wenruo   btrfs: tree-check...
1508
  	case BTRFS_BLOCK_GROUP_ITEM_KEY:
af60ce2b9   David Sterba   btrfs: tree-check...
1509
  		ret = check_block_group_item(leaf, key, slot);
fce466eab   Qu Wenruo   btrfs: tree-check...
1510
  		break;
075cb3c78   Qu Wenruo   btrfs: tree-check...
1511
1512
  	case BTRFS_CHUNK_ITEM_KEY:
  		chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
f6d2a5c26   Qu Wenruo   btrfs: tree-check...
1513
  		ret = check_leaf_chunk_item(leaf, chunk, key, slot);
075cb3c78   Qu Wenruo   btrfs: tree-check...
1514
  		break;
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
1515
  	case BTRFS_DEV_ITEM_KEY:
412a23127   David Sterba   btrfs: tree-check...
1516
  		ret = check_dev_item(leaf, key, slot);
ab4ba2e13   Qu Wenruo   btrfs: tree-check...
1517
  		break;
496245cac   Qu Wenruo   btrfs: tree-check...
1518
  	case BTRFS_INODE_ITEM_KEY:
39e57f495   David Sterba   btrfs: tree-check...
1519
  		ret = check_inode_item(leaf, key, slot);
496245cac   Qu Wenruo   btrfs: tree-check...
1520
  		break;
259ee7754   Qu Wenruo   btrfs: tree-check...
1521
1522
1523
  	case BTRFS_ROOT_ITEM_KEY:
  		ret = check_root_item(leaf, key, slot);
  		break;
f82d1c7ca   Qu Wenruo   btrfs: tree-check...
1524
1525
1526
1527
  	case BTRFS_EXTENT_ITEM_KEY:
  	case BTRFS_METADATA_ITEM_KEY:
  		ret = check_extent_item(leaf, key, slot);
  		break;
e2406a6f1   Qu Wenruo   btrfs: tree-check...
1528
1529
1530
1531
1532
  	case BTRFS_TREE_BLOCK_REF_KEY:
  	case BTRFS_SHARED_DATA_REF_KEY:
  	case BTRFS_SHARED_BLOCK_REF_KEY:
  		ret = check_simple_keyed_refs(leaf, key, slot);
  		break;
0785a9aac   Qu Wenruo   btrfs: tree-check...
1533
1534
1535
  	case BTRFS_EXTENT_DATA_REF_KEY:
  		ret = check_extent_data_ref(leaf, key, slot);
  		break;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1536
1537
1538
  	}
  	return ret;
  }
e2ccd361e   David Sterba   btrfs: tree-check...
1539
  static int check_leaf(struct extent_buffer *leaf, bool check_item_data)
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1540
  {
e2ccd361e   David Sterba   btrfs: tree-check...
1541
  	struct btrfs_fs_info *fs_info = leaf->fs_info;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1542
1543
1544
1545
1546
  	/* No valid key type is 0, so all key should be larger than this key */
  	struct btrfs_key prev_key = {0, 0, 0};
  	struct btrfs_key key;
  	u32 nritems = btrfs_header_nritems(leaf);
  	int slot;
f556faa46   Qu Wenruo   btrfs: tree-check...
1547
  	if (btrfs_header_level(leaf) != 0) {
86a6be3ab   David Sterba   btrfs: tree-check...
1548
  		generic_err(leaf, 0,
f556faa46   Qu Wenruo   btrfs: tree-check...
1549
1550
1551
1552
  			"invalid level for leaf, have %d expect 0",
  			btrfs_header_level(leaf));
  		return -EUCLEAN;
  	}
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1553
1554
1555
1556
1557
1558
1559
1560
1561
  	/*
  	 * Extent buffers from a relocation tree have a owner field that
  	 * corresponds to the subvolume tree they are based on. So just from an
  	 * extent buffer alone we can not find out what is the id of the
  	 * corresponding subvolume tree, so we can not figure out if the extent
  	 * buffer corresponds to the root of the relocation tree or not. So
  	 * skip this check for relocation trees.
  	 */
  	if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) {
ba480dd4d   Qu Wenruo   btrfs: tree-check...
1562
  		u64 owner = btrfs_header_owner(leaf);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1563

ba480dd4d   Qu Wenruo   btrfs: tree-check...
1564
1565
1566
1567
1568
1569
1570
  		/* These trees must never be empty */
  		if (owner == BTRFS_ROOT_TREE_OBJECTID ||
  		    owner == BTRFS_CHUNK_TREE_OBJECTID ||
  		    owner == BTRFS_EXTENT_TREE_OBJECTID ||
  		    owner == BTRFS_DEV_TREE_OBJECTID ||
  		    owner == BTRFS_FS_TREE_OBJECTID ||
  		    owner == BTRFS_DATA_RELOC_TREE_OBJECTID) {
86a6be3ab   David Sterba   btrfs: tree-check...
1571
  			generic_err(leaf, 0,
ba480dd4d   Qu Wenruo   btrfs: tree-check...
1572
1573
1574
1575
  			"invalid root, root %llu must never be empty",
  				    owner);
  			return -EUCLEAN;
  		}
62fdaa52a   Qu Wenruo   btrfs: Detect unb...
1576
1577
1578
1579
1580
1581
  		/* Unknown tree */
  		if (owner == 0) {
  			generic_err(leaf, 0,
  				"invalid owner, root 0 is not defined");
  			return -EUCLEAN;
  		}
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
  		return 0;
  	}
  
  	if (nritems == 0)
  		return 0;
  
  	/*
  	 * Check the following things to make sure this is a good leaf, and
  	 * leaf users won't need to bother with similar sanity checks:
  	 *
  	 * 1) key ordering
  	 * 2) item offset and size
  	 *    No overlap, no hole, all inside the leaf.
  	 * 3) item content
  	 *    If possible, do comprehensive sanity check.
  	 *    NOTE: All checks must only rely on the item data itself.
  	 */
  	for (slot = 0; slot < nritems; slot++) {
  		u32 item_end_expected;
  		int ret;
  
  		btrfs_item_key_to_cpu(leaf, &key, slot);
  
  		/* Make sure the keys are in the right order */
  		if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) {
86a6be3ab   David Sterba   btrfs: tree-check...
1607
  			generic_err(leaf, slot,
478d01b3f   Qu Wenruo   btrfs: tree-check...
1608
1609
1610
1611
  	"bad key order, prev (%llu %u %llu) current (%llu %u %llu)",
  				prev_key.objectid, prev_key.type,
  				prev_key.offset, key.objectid, key.type,
  				key.offset);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
  			return -EUCLEAN;
  		}
  
  		/*
  		 * Make sure the offset and ends are right, remember that the
  		 * item data starts at the end of the leaf and grows towards the
  		 * front.
  		 */
  		if (slot == 0)
  			item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info);
  		else
  			item_end_expected = btrfs_item_offset_nr(leaf,
  								 slot - 1);
  		if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
86a6be3ab   David Sterba   btrfs: tree-check...
1626
  			generic_err(leaf, slot,
478d01b3f   Qu Wenruo   btrfs: tree-check...
1627
1628
1629
  				"unexpected item end, have %u expect %u",
  				btrfs_item_end_nr(leaf, slot),
  				item_end_expected);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
  			return -EUCLEAN;
  		}
  
  		/*
  		 * Check to make sure that we don't point outside of the leaf,
  		 * just in case all the items are consistent to each other, but
  		 * all point outside of the leaf.
  		 */
  		if (btrfs_item_end_nr(leaf, slot) >
  		    BTRFS_LEAF_DATA_SIZE(fs_info)) {
86a6be3ab   David Sterba   btrfs: tree-check...
1640
  			generic_err(leaf, slot,
478d01b3f   Qu Wenruo   btrfs: tree-check...
1641
1642
1643
  			"slot end outside of leaf, have %u expect range [0, %u]",
  				btrfs_item_end_nr(leaf, slot),
  				BTRFS_LEAF_DATA_SIZE(fs_info));
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1644
1645
1646
1647
1648
1649
  			return -EUCLEAN;
  		}
  
  		/* Also check if the item pointer overlaps with btrfs item. */
  		if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) >
  		    btrfs_item_ptr_offset(leaf, slot)) {
86a6be3ab   David Sterba   btrfs: tree-check...
1650
  			generic_err(leaf, slot,
478d01b3f   Qu Wenruo   btrfs: tree-check...
1651
1652
1653
1654
  		"slot overlaps with its data, item end %lu data start %lu",
  				btrfs_item_nr_offset(slot) +
  				sizeof(struct btrfs_item),
  				btrfs_item_ptr_offset(leaf, slot));
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1655
1656
  			return -EUCLEAN;
  		}
69fc6cbba   Qu Wenruo   btrfs: tree-check...
1657
1658
1659
1660
1661
  		if (check_item_data) {
  			/*
  			 * Check if the item size and content meet other
  			 * criteria
  			 */
4e9845eff   Filipe Manana   Btrfs: tree-check...
1662
  			ret = check_leaf_item(leaf, &key, slot, &prev_key);
69fc6cbba   Qu Wenruo   btrfs: tree-check...
1663
1664
1665
  			if (ret < 0)
  				return ret;
  		}
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1666
1667
1668
1669
1670
1671
1672
1673
  
  		prev_key.objectid = key.objectid;
  		prev_key.type = key.type;
  		prev_key.offset = key.offset;
  	}
  
  	return 0;
  }
1c4360ee0   David Sterba   btrfs: get fs_inf...
1674
  int btrfs_check_leaf_full(struct extent_buffer *leaf)
69fc6cbba   Qu Wenruo   btrfs: tree-check...
1675
  {
e2ccd361e   David Sterba   btrfs: tree-check...
1676
  	return check_leaf(leaf, true);
69fc6cbba   Qu Wenruo   btrfs: tree-check...
1677
  }
02529d7a1   Qu Wenruo   btrfs: tree-check...
1678
  ALLOW_ERROR_INJECTION(btrfs_check_leaf_full, ERRNO);
69fc6cbba   Qu Wenruo   btrfs: tree-check...
1679

cfdaad5e5   David Sterba   btrfs: get fs_inf...
1680
  int btrfs_check_leaf_relaxed(struct extent_buffer *leaf)
69fc6cbba   Qu Wenruo   btrfs: tree-check...
1681
  {
e2ccd361e   David Sterba   btrfs: tree-check...
1682
  	return check_leaf(leaf, false);
69fc6cbba   Qu Wenruo   btrfs: tree-check...
1683
  }
813fd1dca   David Sterba   btrfs: get fs_inf...
1684
  int btrfs_check_node(struct extent_buffer *node)
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1685
  {
813fd1dca   David Sterba   btrfs: get fs_inf...
1686
  	struct btrfs_fs_info *fs_info = node->fs_info;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1687
1688
1689
  	unsigned long nr = btrfs_header_nritems(node);
  	struct btrfs_key key, next_key;
  	int slot;
f556faa46   Qu Wenruo   btrfs: tree-check...
1690
  	int level = btrfs_header_level(node);
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1691
1692
  	u64 bytenr;
  	int ret = 0;
f556faa46   Qu Wenruo   btrfs: tree-check...
1693
  	if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
86a6be3ab   David Sterba   btrfs: tree-check...
1694
  		generic_err(node, 0,
f556faa46   Qu Wenruo   btrfs: tree-check...
1695
1696
1697
1698
  			"invalid level for node, have %d expect [1, %d]",
  			level, BTRFS_MAX_LEVEL - 1);
  		return -EUCLEAN;
  	}
2f659546c   Qu Wenruo   btrfs: tree-check...
1699
1700
  	if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) {
  		btrfs_crit(fs_info,
bba4f2989   Qu Wenruo   btrfs: tree-check...
1701
  "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]",
2f659546c   Qu Wenruo   btrfs: tree-check...
1702
  			   btrfs_header_owner(node), node->start,
bba4f2989   Qu Wenruo   btrfs: tree-check...
1703
  			   nr == 0 ? "small" : "large", nr,
2f659546c   Qu Wenruo   btrfs: tree-check...
1704
  			   BTRFS_NODEPTRS_PER_BLOCK(fs_info));
bba4f2989   Qu Wenruo   btrfs: tree-check...
1705
  		return -EUCLEAN;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1706
1707
1708
1709
1710
1711
1712
1713
  	}
  
  	for (slot = 0; slot < nr - 1; slot++) {
  		bytenr = btrfs_node_blockptr(node, slot);
  		btrfs_node_key_to_cpu(node, &key, slot);
  		btrfs_node_key_to_cpu(node, &next_key, slot + 1);
  
  		if (!bytenr) {
86a6be3ab   David Sterba   btrfs: tree-check...
1714
  			generic_err(node, slot,
bba4f2989   Qu Wenruo   btrfs: tree-check...
1715
1716
1717
1718
  				"invalid NULL node pointer");
  			ret = -EUCLEAN;
  			goto out;
  		}
2f659546c   Qu Wenruo   btrfs: tree-check...
1719
  		if (!IS_ALIGNED(bytenr, fs_info->sectorsize)) {
86a6be3ab   David Sterba   btrfs: tree-check...
1720
  			generic_err(node, slot,
bba4f2989   Qu Wenruo   btrfs: tree-check...
1721
  			"unaligned pointer, have %llu should be aligned to %u",
2f659546c   Qu Wenruo   btrfs: tree-check...
1722
  				bytenr, fs_info->sectorsize);
bba4f2989   Qu Wenruo   btrfs: tree-check...
1723
  			ret = -EUCLEAN;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1724
1725
1726
1727
  			goto out;
  		}
  
  		if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
86a6be3ab   David Sterba   btrfs: tree-check...
1728
  			generic_err(node, slot,
bba4f2989   Qu Wenruo   btrfs: tree-check...
1729
1730
1731
1732
1733
  	"bad key order, current (%llu %u %llu) next (%llu %u %llu)",
  				key.objectid, key.type, key.offset,
  				next_key.objectid, next_key.type,
  				next_key.offset);
  			ret = -EUCLEAN;
557ea5dd0   Qu Wenruo   btrfs: Move leaf ...
1734
1735
1736
1737
1738
1739
  			goto out;
  		}
  	}
  out:
  	return ret;
  }
02529d7a1   Qu Wenruo   btrfs: tree-check...
1740
  ALLOW_ERROR_INJECTION(btrfs_check_node, ERRNO);