forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/fs/xfs/scrub/dabtree.c
....@@ -9,20 +9,12 @@
99 #include "xfs_format.h"
1010 #include "xfs_trans_resv.h"
1111 #include "xfs_mount.h"
12
-#include "xfs_defer.h"
13
-#include "xfs_btree.h"
14
-#include "xfs_bit.h"
1512 #include "xfs_log_format.h"
1613 #include "xfs_trans.h"
17
-#include "xfs_sb.h"
1814 #include "xfs_inode.h"
19
-#include "xfs_inode_fork.h"
20
-#include "xfs_da_format.h"
21
-#include "xfs_da_btree.h"
2215 #include "xfs_dir2.h"
2316 #include "xfs_dir2_priv.h"
2417 #include "xfs_attr_leaf.h"
25
-#include "scrub/xfs_scrub.h"
2618 #include "scrub/scrub.h"
2719 #include "scrub/common.h"
2820 #include "scrub/trace.h"
....@@ -85,40 +77,18 @@
8577 __return_address);
8678 }
8779
88
-/* Find an entry at a certain level in a da btree. */
89
-STATIC void *
90
-xchk_da_btree_entry(
91
- struct xchk_da_btree *ds,
92
- int level,
93
- int rec)
80
+static struct xfs_da_node_entry *
81
+xchk_da_btree_node_entry(
82
+ struct xchk_da_btree *ds,
83
+ int level)
9484 {
95
- char *ents;
96
- struct xfs_da_state_blk *blk;
97
- void *baddr;
85
+ struct xfs_da_state_blk *blk = &ds->state->path.blk[level];
86
+ struct xfs_da3_icnode_hdr hdr;
9887
99
- /* Dispatch the entry finding function. */
100
- blk = &ds->state->path.blk[level];
101
- baddr = blk->bp->b_addr;
102
- switch (blk->magic) {
103
- case XFS_ATTR_LEAF_MAGIC:
104
- case XFS_ATTR3_LEAF_MAGIC:
105
- ents = (char *)xfs_attr3_leaf_entryp(baddr);
106
- return ents + (rec * sizeof(struct xfs_attr_leaf_entry));
107
- case XFS_DIR2_LEAFN_MAGIC:
108
- case XFS_DIR3_LEAFN_MAGIC:
109
- ents = (char *)ds->dargs.dp->d_ops->leaf_ents_p(baddr);
110
- return ents + (rec * sizeof(struct xfs_dir2_leaf_entry));
111
- case XFS_DIR2_LEAF1_MAGIC:
112
- case XFS_DIR3_LEAF1_MAGIC:
113
- ents = (char *)ds->dargs.dp->d_ops->leaf_ents_p(baddr);
114
- return ents + (rec * sizeof(struct xfs_dir2_leaf_entry));
115
- case XFS_DA_NODE_MAGIC:
116
- case XFS_DA3_NODE_MAGIC:
117
- ents = (char *)ds->dargs.dp->d_ops->node_tree_p(baddr);
118
- return ents + (rec * sizeof(struct xfs_da_node_entry));
119
- }
88
+ ASSERT(blk->magic == XFS_DA_NODE_MAGIC);
12089
121
- return NULL;
90
+ xfs_da3_node_hdr_from_disk(ds->sc->mp, &hdr, blk->bp->b_addr);
91
+ return hdr.btree + blk->index;
12292 }
12393
12494 /* Scrub a da btree hash (key). */
....@@ -128,7 +98,6 @@
12898 int level,
12999 __be32 *hashp)
130100 {
131
- struct xfs_da_state_blk *blks;
132101 struct xfs_da_node_entry *entry;
133102 xfs_dahash_t hash;
134103 xfs_dahash_t parent_hash;
....@@ -143,8 +112,7 @@
143112 return 0;
144113
145114 /* Is this hash no larger than the parent hash? */
146
- blks = ds->state->path.blk;
147
- entry = xchk_da_btree_entry(ds, level - 1, blks[level - 1].index);
115
+ entry = xchk_da_btree_node_entry(ds, level - 1);
148116 parent_hash = be32_to_cpu(entry->hashval);
149117 if (parent_hash < hash)
150118 xchk_da_set_corrupt(ds, level);
....@@ -251,19 +219,21 @@
251219 int direction,
252220 xfs_dablk_t sibling)
253221 {
222
+ struct xfs_da_state_path *path = &ds->state->path;
223
+ struct xfs_da_state_path *altpath = &ds->state->altpath;
254224 int retval;
225
+ int plevel;
255226 int error;
256227
257
- memcpy(&ds->state->altpath, &ds->state->path,
258
- sizeof(ds->state->altpath));
228
+ memcpy(altpath, path, sizeof(ds->state->altpath));
259229
260230 /*
261231 * If the pointer is null, we shouldn't be able to move the upper
262232 * level pointer anywhere.
263233 */
264234 if (sibling == 0) {
265
- error = xfs_da3_path_shift(ds->state, &ds->state->altpath,
266
- direction, false, &retval);
235
+ error = xfs_da3_path_shift(ds->state, altpath, direction,
236
+ false, &retval);
267237 if (error == 0 && retval == 0)
268238 xchk_da_set_corrupt(ds, level);
269239 error = 0;
....@@ -271,23 +241,33 @@
271241 }
272242
273243 /* Move the alternate cursor one block in the direction given. */
274
- error = xfs_da3_path_shift(ds->state, &ds->state->altpath,
275
- direction, false, &retval);
244
+ error = xfs_da3_path_shift(ds->state, altpath, direction, false,
245
+ &retval);
276246 if (!xchk_da_process_error(ds, level, &error))
277
- return error;
247
+ goto out;
278248 if (retval) {
279249 xchk_da_set_corrupt(ds, level);
280
- return error;
250
+ goto out;
281251 }
282
- if (ds->state->altpath.blk[level].bp)
283
- xchk_buffer_recheck(ds->sc,
284
- ds->state->altpath.blk[level].bp);
252
+ if (altpath->blk[level].bp)
253
+ xchk_buffer_recheck(ds->sc, altpath->blk[level].bp);
285254
286255 /* Compare upper level pointer to sibling pointer. */
287
- if (ds->state->altpath.blk[level].blkno != sibling)
256
+ if (altpath->blk[level].blkno != sibling)
288257 xchk_da_set_corrupt(ds, level);
289
- xfs_trans_brelse(ds->dargs.trans, ds->state->altpath.blk[level].bp);
258
+
290259 out:
260
+ /* Free all buffers in the altpath that aren't referenced from path. */
261
+ for (plevel = 0; plevel < altpath->active; plevel++) {
262
+ if (altpath->blk[plevel].bp == NULL ||
263
+ (plevel < path->active &&
264
+ altpath->blk[plevel].bp == path->blk[plevel].bp))
265
+ continue;
266
+
267
+ xfs_trans_brelse(ds->dargs.trans, altpath->blk[plevel].bp);
268
+ altpath->blk[plevel].bp = NULL;
269
+ }
270
+
291271 return error;
292272 }
293273
....@@ -359,8 +339,8 @@
359339 goto out_nobuf;
360340
361341 /* Read the buffer. */
362
- error = xfs_da_read_buf(dargs->trans, dargs->dp, blk->blkno, -2,
363
- &blk->bp, dargs->whichfork,
342
+ error = xfs_da_read_buf(dargs->trans, dargs->dp, blk->blkno,
343
+ XFS_DABUF_MAP_HOLE_OK, &blk->bp, dargs->whichfork,
364344 &xchk_da_btree_buf_ops);
365345 if (!xchk_da_process_error(ds, level, &error))
366346 goto out_nobuf;
....@@ -437,8 +417,8 @@
437417 XFS_BLFT_DA_NODE_BUF);
438418 blk->magic = XFS_DA_NODE_MAGIC;
439419 node = blk->bp->b_addr;
440
- ip->d_ops->node_hdr_from_disk(&nodehdr, node);
441
- btree = ip->d_ops->node_tree_p(node);
420
+ xfs_da3_node_hdr_from_disk(ip->i_mount, &nodehdr, node);
421
+ btree = nodehdr.btree;
442422 *pmaxrecs = nodehdr.count;
443423 blk->hashval = be32_to_cpu(btree[*pmaxrecs - 1].hashval);
444424 if (level == 0) {
....@@ -459,6 +439,20 @@
459439 default:
460440 xchk_da_set_corrupt(ds, level);
461441 goto out_freebp;
442
+ }
443
+
444
+ /*
445
+ * If we've been handed a block that is below the dabtree root, does
446
+ * its hashval match what the parent block expected to see?
447
+ */
448
+ if (level > 0) {
449
+ struct xfs_da_node_entry *key;
450
+
451
+ key = xchk_da_btree_node_entry(ds, level - 1);
452
+ if (be32_to_cpu(key->hashval) != blk->hashval) {
453
+ xchk_da_set_corrupt(ds, level);
454
+ goto out_freebp;
455
+ }
462456 }
463457
464458 out:
....@@ -483,14 +477,12 @@
483477 struct xfs_mount *mp = sc->mp;
484478 struct xfs_da_state_blk *blks;
485479 struct xfs_da_node_entry *key;
486
- void *rec;
487480 xfs_dablk_t blkno;
488481 int level;
489482 int error;
490483
491484 /* Skip short format data structures; no btree to scan. */
492
- if (XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
493
- XFS_IFORK_FORMAT(sc->ip, whichfork) != XFS_DINODE_FMT_BTREE)
485
+ if (!xfs_ifork_has_extents(XFS_IFORK_PTR(sc->ip, whichfork)))
494486 return 0;
495487
496488 /* Set up initial da state. */
....@@ -498,9 +490,7 @@
498490 ds.dargs.whichfork = whichfork;
499491 ds.dargs.trans = sc->tp;
500492 ds.dargs.op_flags = XFS_DA_OP_OKNOENT;
501
- ds.state = xfs_da_state_alloc();
502
- ds.state->args = &ds.dargs;
503
- ds.state->mp = mp;
493
+ ds.state = xfs_da_state_alloc(&ds.dargs);
504494 ds.sc = sc;
505495 ds.private = private;
506496 if (whichfork == XFS_ATTR_FORK) {
....@@ -542,9 +532,7 @@
542532 }
543533
544534 /* Dispatch record scrubbing. */
545
- rec = xchk_da_btree_entry(&ds, level,
546
- blks[level].index);
547
- error = scrub_fn(&ds, level, rec);
535
+ error = scrub_fn(&ds, level);
548536 if (error)
549537 break;
550538 if (xchk_should_terminate(sc, &error) ||
....@@ -566,7 +554,7 @@
566554 }
567555
568556 /* Hashes in order for scrub? */
569
- key = xchk_da_btree_entry(&ds, level, blks[level].index);
557
+ key = xchk_da_btree_node_entry(&ds, level);
570558 error = xchk_da_btree_hash(&ds, level, &key->hashval);
571559 if (error)
572560 goto out;
....@@ -574,6 +562,11 @@
574562 /* Drill another level deeper. */
575563 blkno = be32_to_cpu(key->before);
576564 level++;
565
+ if (level >= XFS_DA_NODE_MAXDEPTH) {
566
+ /* Too deep! */
567
+ xchk_da_set_corrupt(&ds, level - 1);
568
+ break;
569
+ }
577570 ds.tree_level--;
578571 error = xchk_da_btree_block(&ds, level, blkno);
579572 if (error)