Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
4 : * Author: Darrick J. Wong <djwong@kernel.org>
5 : */
6 : #include "xfs.h"
7 : #include "xfs_fs.h"
8 : #include "xfs_shared.h"
9 : #include "xfs_format.h"
10 : #include "xfs_trans_resv.h"
11 : #include "xfs_mount.h"
12 : #include "xfs_log_format.h"
13 : #include "xfs_trans.h"
14 : #include "xfs_inode.h"
15 : #include "xfs_icache.h"
16 : #include "xfs_dir2.h"
17 : #include "xfs_dir2_priv.h"
18 : #include "xfs_attr.h"
19 : #include "xfs_parent.h"
20 : #include "scrub/scrub.h"
21 : #include "scrub/common.h"
22 : #include "scrub/dabtree.h"
23 : #include "scrub/readdir.h"
24 : #include "scrub/repair.h"
25 : #include "scrub/trace.h"
26 : #include "scrub/xfile.h"
27 : #include "scrub/xfarray.h"
28 : #include "scrub/xfblob.h"
29 :
30 : /* Set us up to scrub directories. */
31 : int
32 23116152 : xchk_setup_directory(
33 : struct xfs_scrub *sc)
34 : {
35 23116152 : int error;
36 :
37 46232304 : if (xchk_could_repair(sc)) {
38 584906 : error = xrep_setup_directory(sc);
39 584818 : if (error)
40 : return error;
41 : }
42 :
43 23115619 : return xchk_setup_inode_contents(sc, 0);
44 : }
45 :
46 : /* Directories */
47 :
48 : /* Deferred directory entry that we saved for later. */
49 : struct xchk_dirent {
50 : /* Cookie for retrieval of the dirent name. */
51 : xfblob_cookie name_cookie;
52 :
53 : /* Child inode number. */
54 : xfs_ino_t ino;
55 :
56 : /* Length of the pptr name. */
57 : uint8_t namelen;
58 : };
59 :
60 : struct xchk_dir {
61 : struct xfs_scrub *sc;
62 :
63 : /* Scratch buffer for scanning pptr xattrs */
64 : struct xfs_parent_name_irec pptr;
65 :
66 : /* xattr key and da args for parent pointer validation. */
67 : struct xfs_parent_scratch pptr_scratch;
68 :
69 : /* Fixed-size array of xchk_dirent structures. */
70 : struct xfarray *dir_entries;
71 :
72 : /* Blobs containing dirent names. */
73 : struct xfblob *dir_names;
74 :
75 : /* If we've cycled the ILOCK, we must revalidate deferred dirents. */
76 : bool need_revalidate;
77 :
78 : /* Name buffer for dirent revalidation. */
79 : uint8_t namebuf[MAXNAMELEN];
80 :
81 : };
82 :
83 : /* Scrub a directory entry. */
84 :
85 : /* Check that an inode's mode matches a given XFS_DIR3_FT_* type. */
86 : STATIC void
87 232369782 : xchk_dir_check_ftype(
88 : struct xfs_scrub *sc,
89 : xfs_fileoff_t offset,
90 : struct xfs_inode *ip,
91 : int ftype)
92 : {
93 232369782 : struct xfs_mount *mp = sc->mp;
94 :
95 232369782 : if (!xfs_has_ftype(mp)) {
96 0 : if (ftype != XFS_DIR3_FT_UNKNOWN && ftype != XFS_DIR3_FT_DIR)
97 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
98 0 : return;
99 : }
100 :
101 232369782 : if (xfs_mode_to_ftype(VFS_I(ip)->i_mode) != ftype)
102 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
103 : }
104 :
105 : /*
106 : * Try to lock a child file for checking parent pointers. Returns the inode
107 : * flags for the locks we now hold, or zero if we failed.
108 : */
109 : STATIC unsigned int
110 180352392 : xchk_dir_lock_child(
111 : struct xfs_scrub *sc,
112 : struct xfs_inode *ip)
113 : {
114 180352392 : if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
115 : return 0;
116 :
117 179743261 : if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
118 929 : xfs_iunlock(ip, XFS_IOLOCK_SHARED);
119 929 : return 0;
120 : }
121 :
122 359868788 : if (!xfs_inode_has_attr_fork(ip) || !xfs_need_iread_extents(&ip->i_af))
123 179926863 : return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;
124 :
125 117 : xfs_iunlock(ip, XFS_ILOCK_SHARED);
126 :
127 117 : if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
128 0 : xfs_iunlock(ip, XFS_IOLOCK_SHARED);
129 0 : return 0;
130 : }
131 :
132 : return XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
133 : }
134 :
135 : /* Check the backwards link (parent pointer) associated with this dirent. */
136 : STATIC int
137 179841133 : xchk_dir_parent_pointer(
138 : struct xchk_dir *sd,
139 : const struct xfs_name *name,
140 : struct xfs_inode *ip)
141 : {
142 179841133 : struct xfs_scrub *sc = sd->sc;
143 179841133 : int error;
144 :
145 179841133 : sd->pptr.p_ino = sc->ip->i_ino;
146 179841133 : sd->pptr.p_gen = VFS_I(sc->ip)->i_generation;
147 179841133 : sd->pptr.p_namelen = name->len;
148 359682266 : memcpy(sd->pptr.p_name, name->name, name->len);
149 179841133 : xfs_parent_irec_hashname(sc->mp, &sd->pptr);
150 :
151 179754155 : error = xfs_parent_lookup(sc->tp, ip, &sd->pptr, &sd->pptr_scratch);
152 179830333 : if (error == -ENOATTR)
153 0 : xchk_fblock_xref_set_corrupt(sc, XFS_DATA_FORK, 0);
154 :
155 179830333 : return 0;
156 : }
157 :
158 : /* Look for a parent pointer matching this dirent, if the child isn't busy. */
159 : STATIC int
160 225272440 : xchk_dir_check_pptr_fast(
161 : struct xchk_dir *sd,
162 : xfs_dir2_dataptr_t dapos,
163 : const struct xfs_name *name,
164 : struct xfs_inode *ip)
165 : {
166 225272440 : struct xfs_scrub *sc = sd->sc;
167 225272440 : unsigned int lockmode;
168 225272440 : int error;
169 :
170 : /* dot and dotdot entries do not have parent pointers */
171 428094132 : if (xfs_dir2_samename(name, &xfs_name_dot) ||
172 202836314 : xfs_dir2_samename(name, &xfs_name_dotdot))
173 44900595 : return 0;
174 :
175 : /* Try to lock the inode. */
176 180354797 : lockmode = xchk_dir_lock_child(sc, ip);
177 180390600 : if (!lockmode) {
178 525897 : struct xchk_dirent save_de = {
179 525897 : .namelen = name->len,
180 525897 : .ino = ip->i_ino,
181 : };
182 :
183 : /* Couldn't lock the inode, so save the dirent for later. */
184 525897 : trace_xchk_dir_defer(sc->ip, name->name, name->len, ip->i_ino);
185 :
186 1051788 : error = xfblob_store(sd->dir_names, &save_de.name_cookie,
187 525892 : name->name, name->len);
188 525896 : if (xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
189 : &error))
190 525897 : return error;
191 :
192 0 : error = xfarray_append(sd->dir_entries, &save_de);
193 0 : if (xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
194 : &error))
195 0 : return error;
196 :
197 : return 0;
198 : }
199 :
200 179864703 : error = xchk_dir_parent_pointer(sd, name, ip);
201 179866551 : xfs_iunlock(ip, lockmode);
202 179593724 : return error;
203 : }
204 :
205 : /*
206 : * Scrub a single directory entry.
207 : *
208 : * Check the inode number to make sure it's sane, then we check that we can
209 : * look up this filename. Finally, we check the ftype.
210 : */
211 : STATIC int
212 232255779 : xchk_dir_actor(
213 : struct xfs_scrub *sc,
214 : struct xfs_inode *dp,
215 : xfs_dir2_dataptr_t dapos,
216 : const struct xfs_name *name,
217 : xfs_ino_t ino,
218 : void *priv)
219 : {
220 232255779 : struct xfs_mount *mp = dp->i_mount;
221 232255779 : struct xfs_inode *ip;
222 232255779 : struct xchk_dir *sd = priv;
223 232255779 : xfs_ino_t lookup_ino;
224 232255779 : xfs_dablk_t offset;
225 232255779 : int error = 0;
226 :
227 232255779 : offset = xfs_dir2_db_to_da(mp->m_dir_geo,
228 : xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos));
229 :
230 232175345 : if (xchk_should_terminate(sc, &error))
231 4 : return error;
232 :
233 : /* Does this inode number make sense? */
234 232275173 : if (!xfs_verify_dir_ino(mp, ino)) {
235 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
236 0 : return -ECANCELED;
237 : }
238 :
239 : /* Does this name make sense? */
240 232128570 : if (!xfs_dir2_namecheck(name->name, name->len)) {
241 11 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
242 11 : return -ECANCELED;
243 : }
244 :
245 232063094 : if (xfs_dir2_samename(name, &xfs_name_dot)) {
246 : /* If this is "." then check that the inum matches the dir. */
247 23105556 : if (ino != dp->i_ino)
248 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
249 208977487 : } else if (xfs_dir2_samename(name, &xfs_name_dotdot)) {
250 : /*
251 : * If this is ".." in the root inode, check that the inum
252 : * matches this dir.
253 : */
254 23097946 : if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino)
255 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
256 : }
257 :
258 : /* Verify that we can look up this name by hash. */
259 232013792 : error = xchk_dir_lookup(sc, dp, name, &lookup_ino);
260 : /* ENOENT means the hash lookup failed and the dir is corrupt */
261 232321080 : if (error == -ENOENT)
262 0 : error = -EFSCORRUPTED;
263 232321080 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error))
264 0 : goto out;
265 232200930 : if (lookup_ino != ino) {
266 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
267 0 : return -ECANCELED;
268 : }
269 :
270 : /*
271 : * Grab the inode pointed to by the dirent. We release the inode
272 : * before we cancel the scrub transaction.
273 : *
274 : * If _iget returns -EINVAL or -ENOENT then the child inode number is
275 : * garbage and the directory is corrupt. If the _iget returns
276 : * -EFSCORRUPTED or -EFSBADCRC then the child is corrupt which is a
277 : * cross referencing error. Any other error is an operational error.
278 : */
279 232200930 : error = xchk_iget(sc, ino, &ip);
280 232462940 : if (error == -EINVAL || error == -ENOENT) {
281 0 : error = -EFSCORRUPTED;
282 0 : xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error);
283 0 : goto out;
284 : }
285 232462940 : if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, offset, &error))
286 0 : goto out;
287 :
288 232384073 : xchk_dir_check_ftype(sc, offset, ip, name->type);
289 :
290 232242315 : if (xfs_has_parent(mp)) {
291 225232669 : error = xchk_dir_check_pptr_fast(sd, dapos, name, ip);
292 225043021 : if (error)
293 : goto out_rele;
294 : }
295 :
296 232052667 : out_rele:
297 232052667 : xchk_irele(sc, ip);
298 232398264 : out:
299 232398264 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
300 : return -ECANCELED;
301 232398264 : return error;
302 : }
303 :
304 : /* Scrub a directory btree record. */
305 : STATIC int
306 98793744 : xchk_dir_rec(
307 : struct xchk_da_btree *ds,
308 : int level)
309 : {
310 98793744 : struct xfs_name dname = { };
311 98793744 : struct xfs_da_state_blk *blk = &ds->state->path.blk[level];
312 98788056 : struct xfs_mount *mp = ds->state->mp;
313 98788056 : struct xfs_inode *dp = ds->dargs.dp;
314 98788056 : struct xfs_da_geometry *geo = mp->m_dir_geo;
315 98788056 : struct xfs_dir2_data_entry *dent;
316 98788056 : struct xfs_buf *bp;
317 98788056 : struct xfs_dir2_leaf_entry *ent;
318 98788056 : unsigned int end;
319 98788056 : unsigned int iter_off;
320 98788056 : xfs_ino_t ino;
321 98788056 : xfs_dablk_t rec_bno;
322 98788056 : xfs_dir2_db_t db;
323 98788056 : xfs_dir2_data_aoff_t off;
324 98788056 : xfs_dir2_dataptr_t ptr;
325 98788056 : xfs_dahash_t calc_hash;
326 98788056 : xfs_dahash_t hash;
327 98788056 : struct xfs_dir3_icleaf_hdr hdr;
328 98788056 : unsigned int tag;
329 98788056 : int error;
330 :
331 98788056 : ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC ||
332 : blk->magic == XFS_DIR2_LEAFN_MAGIC);
333 :
334 98788056 : xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr);
335 98757418 : ent = hdr.ents + blk->index;
336 :
337 : /* Check the hash of the entry. */
338 98757418 : error = xchk_da_btree_hash(ds, level, &ent->hashval);
339 98757877 : if (error)
340 0 : goto out;
341 :
342 : /* Valid hash pointer? */
343 98757877 : ptr = be32_to_cpu(ent->address);
344 98757877 : if (ptr == 0)
345 : return 0;
346 :
347 : /* Find the directory entry's location. */
348 87566808 : db = xfs_dir2_dataptr_to_db(geo, ptr);
349 87541038 : off = xfs_dir2_dataptr_to_off(geo, ptr);
350 87541038 : rec_bno = xfs_dir2_db_to_da(geo, db);
351 :
352 87537542 : if (rec_bno >= geo->leafblk) {
353 0 : xchk_da_set_corrupt(ds, level);
354 0 : goto out;
355 : }
356 87537542 : error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner,
357 : rec_bno, XFS_DABUF_MAP_HOLE_OK, &bp);
358 87428005 : if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno,
359 : &error))
360 0 : goto out;
361 87412074 : if (!bp) {
362 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
363 0 : goto out;
364 : }
365 87412074 : xchk_buffer_recheck(ds->sc, bp);
366 :
367 87565996 : if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
368 0 : goto out_relse;
369 :
370 87565996 : dent = bp->b_addr + off;
371 :
372 : /* Make sure we got a real directory entry. */
373 87565996 : iter_off = geo->data_entry_offset;
374 87565996 : end = xfs_dir3_data_end_offset(geo, bp->b_addr);
375 87614976 : if (!end) {
376 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
377 0 : goto out_relse;
378 : }
379 9061805555 : for (;;) {
380 9061805555 : struct xfs_dir2_data_entry *dep = bp->b_addr + iter_off;
381 9061805555 : struct xfs_dir2_data_unused *dup = bp->b_addr + iter_off;
382 :
383 9061805555 : if (iter_off >= end) {
384 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
385 0 : goto out_relse;
386 : }
387 :
388 9061805555 : if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
389 314187883 : iter_off += be16_to_cpu(dup->length);
390 314187883 : continue;
391 : }
392 8747617672 : if (dep == dent)
393 : break;
394 17318100855 : iter_off += xfs_dir2_data_entsize(mp, dep->namelen);
395 : }
396 :
397 : /* Retrieve the entry, sanity check it, and compare hashes. */
398 87614976 : ino = be64_to_cpu(dent->inumber);
399 87614976 : hash = be32_to_cpu(ent->hashval);
400 87614976 : tag = be16_to_cpup(xfs_dir2_data_entry_tag_p(mp, dent));
401 87597283 : if (!xfs_verify_dir_ino(mp, ino) || tag != off)
402 8 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
403 87582947 : if (dent->namelen == 0) {
404 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
405 0 : goto out_relse;
406 : }
407 :
408 : /* Does the directory hash match? */
409 87582947 : dname.name = dent->name;
410 87582947 : dname.len = dent->namelen;
411 87582947 : calc_hash = xfs_dir2_hashname(mp, &dname);
412 87582974 : if (calc_hash != hash)
413 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
414 :
415 87582974 : out_relse:
416 87582974 : xfs_trans_brelse(ds->dargs.trans, bp);
417 87588461 : out:
418 87588461 : return error;
419 : }
420 :
421 : /*
422 : * Is this unused entry either in the bestfree or smaller than all of
423 : * them? We've already checked that the bestfrees are sorted longest to
424 : * shortest, and that there aren't any bogus entries.
425 : */
426 : STATIC void
427 6495181 : xchk_directory_check_free_entry(
428 : struct xfs_scrub *sc,
429 : xfs_dablk_t lblk,
430 : struct xfs_dir2_data_free *bf,
431 : struct xfs_dir2_data_unused *dup)
432 : {
433 6495181 : struct xfs_dir2_data_free *dfp;
434 6495181 : unsigned int dup_length;
435 :
436 6495181 : dup_length = be16_to_cpu(dup->length);
437 :
438 : /* Unused entry is shorter than any of the bestfrees */
439 6495181 : if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
440 : return;
441 :
442 5785310 : for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--)
443 5785310 : if (dup_length == be16_to_cpu(dfp->length))
444 : return;
445 :
446 : /* Unused entry should be in the bestfrees but wasn't found. */
447 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
448 : }
449 :
450 : /* Check free space info in a directory data block. */
451 : STATIC int
452 940617 : xchk_directory_data_bestfree(
453 : struct xfs_scrub *sc,
454 : xfs_dablk_t lblk,
455 : bool is_block)
456 : {
457 940617 : struct xfs_dir2_data_unused *dup;
458 940617 : struct xfs_dir2_data_free *dfp;
459 940617 : struct xfs_buf *bp;
460 940617 : struct xfs_dir2_data_free *bf;
461 940617 : struct xfs_mount *mp = sc->mp;
462 940617 : u16 tag;
463 940617 : unsigned int nr_bestfrees = 0;
464 940617 : unsigned int nr_frees = 0;
465 940617 : unsigned int smallest_bestfree;
466 940617 : int newlen;
467 940617 : unsigned int offset;
468 940617 : unsigned int end;
469 940617 : int error;
470 :
471 940617 : if (is_block) {
472 : /* dir block format */
473 364418 : if (lblk != XFS_B_TO_FSBT(mp, XFS_DIR2_DATA_OFFSET))
474 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
475 364418 : error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp);
476 : } else {
477 : /* dir data format */
478 576199 : error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk,
479 : 0, &bp);
480 : }
481 940664 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
482 0 : goto out;
483 940651 : xchk_buffer_recheck(sc, bp);
484 :
485 : /* XXX: Check xfs_dir3_data_hdr.pad is zero once we start setting it. */
486 :
487 940661 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
488 0 : goto out_buf;
489 :
490 : /* Do the bestfrees correspond to actual free space? */
491 940661 : bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr);
492 940661 : smallest_bestfree = UINT_MAX;
493 4703247 : for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
494 2821940 : offset = be16_to_cpu(dfp->offset);
495 2821940 : if (offset == 0)
496 1135191 : continue;
497 1686749 : if (offset >= mp->m_dir_geo->blksize) {
498 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
499 0 : goto out_buf;
500 : }
501 1686749 : dup = bp->b_addr + offset;
502 1686749 : tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
503 :
504 : /* bestfree doesn't match the entry it points at? */
505 1686749 : if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) ||
506 1686749 : be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) ||
507 : tag != offset) {
508 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
509 0 : goto out_buf;
510 : }
511 :
512 : /* bestfree records should be ordered largest to smallest */
513 1686749 : if (smallest_bestfree < be16_to_cpu(dfp->length)) {
514 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
515 0 : goto out_buf;
516 : }
517 :
518 1686749 : smallest_bestfree = be16_to_cpu(dfp->length);
519 1686749 : nr_bestfrees++;
520 : }
521 :
522 : /* Make sure the bestfrees are actually the best free spaces. */
523 940646 : offset = mp->m_dir_geo->data_entry_offset;
524 940646 : end = xfs_dir3_data_end_offset(mp->m_dir_geo, bp->b_addr);
525 :
526 : /* Iterate the entries, stopping when we hit or go past the end. */
527 102748701 : while (offset < end) {
528 101808020 : dup = bp->b_addr + offset;
529 :
530 : /* Skip real entries */
531 101808020 : if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) {
532 95312981 : struct xfs_dir2_data_entry *dep = bp->b_addr + offset;
533 :
534 95312981 : newlen = xfs_dir2_data_entsize(mp, dep->namelen);
535 95312981 : if (newlen <= 0) {
536 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
537 : lblk);
538 : goto out_buf;
539 : }
540 95312981 : offset += newlen;
541 95312981 : continue;
542 : }
543 :
544 : /* Spot check this free entry */
545 6495039 : tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
546 6495039 : if (tag != offset) {
547 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
548 0 : goto out_buf;
549 : }
550 :
551 : /*
552 : * Either this entry is a bestfree or it's smaller than
553 : * any of the bestfrees.
554 : */
555 6495039 : xchk_directory_check_free_entry(sc, lblk, bf, dup);
556 6495074 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
557 0 : goto out_buf;
558 :
559 : /* Move on. */
560 6495074 : newlen = be16_to_cpu(dup->length);
561 6495074 : if (newlen <= 0) {
562 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
563 0 : goto out_buf;
564 : }
565 6495074 : offset += newlen;
566 6495074 : if (offset <= end)
567 6495069 : nr_frees++;
568 : }
569 :
570 : /* We're required to fill all the space. */
571 940677 : if (offset != end)
572 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
573 :
574 : /* Did we see at least as many free slots as there are bestfrees? */
575 940677 : if (nr_frees < nr_bestfrees)
576 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
577 940677 : out_buf:
578 940677 : xfs_trans_brelse(sc->tp, bp);
579 940671 : out:
580 940671 : return error;
581 : }
582 :
583 : /*
584 : * Does the free space length in the free space index block ($len) match
585 : * the longest length in the directory data block's bestfree array?
586 : * Assume that we've already checked that the data block's bestfree
587 : * array is in order.
588 : */
589 : STATIC void
590 576202 : xchk_directory_check_freesp(
591 : struct xfs_scrub *sc,
592 : xfs_dablk_t lblk,
593 : struct xfs_buf *dbp,
594 : unsigned int len)
595 : {
596 576202 : struct xfs_dir2_data_free *dfp;
597 :
598 576202 : dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr);
599 :
600 576202 : if (len != be16_to_cpu(dfp->length))
601 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
602 :
603 576202 : if (len > 0 && be16_to_cpu(dfp->offset) == 0)
604 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
605 576202 : }
606 :
607 : /* Check free space info in a directory leaf1 block. */
608 : STATIC int
609 20835 : xchk_directory_leaf1_bestfree(
610 : struct xfs_scrub *sc,
611 : struct xfs_da_args *args,
612 : xfs_dir2_db_t last_data_db,
613 : xfs_dablk_t lblk)
614 : {
615 20835 : struct xfs_dir3_icleaf_hdr leafhdr;
616 20835 : struct xfs_dir2_leaf_tail *ltp;
617 20835 : struct xfs_dir2_leaf *leaf;
618 20835 : struct xfs_buf *dbp;
619 20835 : struct xfs_buf *bp;
620 20835 : struct xfs_da_geometry *geo = sc->mp->m_dir_geo;
621 20835 : __be16 *bestp;
622 20835 : __u16 best;
623 20835 : __u32 hash;
624 20835 : __u32 lasthash = 0;
625 20835 : __u32 bestcount;
626 20835 : unsigned int stale = 0;
627 20835 : int i;
628 20835 : int error;
629 :
630 : /* Read the free space block. */
631 20835 : error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
632 20835 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
633 0 : return error;
634 20835 : xchk_buffer_recheck(sc, bp);
635 :
636 20835 : leaf = bp->b_addr;
637 20835 : xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf);
638 20835 : ltp = xfs_dir2_leaf_tail_p(geo, leaf);
639 20835 : bestcount = be32_to_cpu(ltp->bestcount);
640 20835 : bestp = xfs_dir2_leaf_bests_p(ltp);
641 :
642 20835 : if (xfs_has_crc(sc->mp)) {
643 20835 : struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr;
644 :
645 20835 : if (hdr3->pad != cpu_to_be32(0))
646 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
647 : }
648 :
649 : /*
650 : * There must be enough bestfree slots to cover all the directory data
651 : * blocks that we scanned. It is possible for there to be a hole
652 : * between the last data block and i_disk_size. This seems like an
653 : * oversight to the scrub author, but as we have been writing out
654 : * directories like this (and xfs_repair doesn't mind them) for years,
655 : * that's what we have to check.
656 : */
657 20835 : if (bestcount != last_data_db + 1) {
658 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
659 0 : goto out;
660 : }
661 :
662 : /* Is the leaf count even remotely sane? */
663 20835 : if (leafhdr.count > geo->leaf_max_ents) {
664 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
665 0 : goto out;
666 : }
667 :
668 : /* Leaves and bests don't overlap in leaf format. */
669 20835 : if ((char *)&leafhdr.ents[leafhdr.count] > (char *)bestp) {
670 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
671 0 : goto out;
672 : }
673 :
674 : /* Check hash value order, count stale entries. */
675 5071657 : for (i = 0; i < leafhdr.count; i++) {
676 5050822 : hash = be32_to_cpu(leafhdr.ents[i].hashval);
677 5050822 : if (i > 0 && lasthash > hash)
678 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
679 5050822 : lasthash = hash;
680 5050822 : if (leafhdr.ents[i].address ==
681 : cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
682 593628 : stale++;
683 : }
684 20835 : if (leafhdr.stale != stale)
685 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
686 20835 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
687 0 : goto out;
688 :
689 : /* Check all the bestfree entries. */
690 69692 : for (i = 0; i < bestcount; i++, bestp++) {
691 48857 : best = be16_to_cpu(*bestp);
692 48857 : error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
693 : xfs_dir2_db_to_da(args->geo, i),
694 : XFS_DABUF_MAP_HOLE_OK, &dbp);
695 48857 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
696 : &error))
697 : break;
698 :
699 48857 : if (!dbp) {
700 264 : if (best != NULLDATAOFF) {
701 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
702 : lblk);
703 0 : break;
704 : }
705 264 : continue;
706 : }
707 :
708 48593 : if (best == NULLDATAOFF)
709 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
710 : else
711 48593 : xchk_directory_check_freesp(sc, lblk, dbp, best);
712 48593 : xfs_trans_brelse(sc->tp, dbp);
713 48593 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
714 : break;
715 : }
716 20835 : out:
717 20835 : xfs_trans_brelse(sc->tp, bp);
718 20835 : return error;
719 : }
720 :
721 : /* Check free space info in a directory freespace block. */
722 : STATIC int
723 32292 : xchk_directory_free_bestfree(
724 : struct xfs_scrub *sc,
725 : struct xfs_da_args *args,
726 : xfs_dablk_t lblk)
727 : {
728 32292 : struct xfs_dir3_icfree_hdr freehdr;
729 32292 : struct xfs_buf *dbp;
730 32292 : struct xfs_buf *bp;
731 32292 : __u16 best;
732 32292 : unsigned int stale = 0;
733 32292 : int i;
734 32292 : int error;
735 :
736 : /* Read the free space block */
737 32292 : error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
738 32292 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
739 0 : return error;
740 32292 : xchk_buffer_recheck(sc, bp);
741 :
742 32292 : if (xfs_has_crc(sc->mp)) {
743 32292 : struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
744 :
745 32292 : if (hdr3->pad != cpu_to_be32(0))
746 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
747 : }
748 :
749 : /* Check all the entries. */
750 32292 : xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr);
751 606513 : for (i = 0; i < freehdr.nvalid; i++) {
752 541929 : best = be16_to_cpu(freehdr.bests[i]);
753 541929 : if (best == NULLDATAOFF) {
754 14321 : stale++;
755 14321 : continue;
756 : }
757 1055217 : error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
758 527608 : (freehdr.firstdb + i) * args->geo->fsbcount,
759 : 0, &dbp);
760 527609 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
761 : &error))
762 0 : goto out;
763 527609 : xchk_directory_check_freesp(sc, lblk, dbp, best);
764 527609 : xfs_trans_brelse(sc->tp, dbp);
765 : }
766 :
767 32292 : if (freehdr.nused + stale != freehdr.nvalid)
768 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
769 32292 : out:
770 32292 : xfs_trans_brelse(sc->tp, bp);
771 32292 : return error;
772 : }
773 :
774 : /* Check free space information in directories. */
775 : STATIC int
776 23115228 : xchk_directory_blocks(
777 : struct xfs_scrub *sc)
778 : {
779 23115228 : struct xfs_bmbt_irec got;
780 23115228 : struct xfs_da_args args = {
781 23115228 : .dp = sc->ip,
782 : .whichfork = XFS_DATA_FORK,
783 23115228 : .geo = sc->mp->m_dir_geo,
784 23115228 : .trans = sc->tp,
785 23115228 : .owner = sc->ip->i_ino,
786 : };
787 23115228 : struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
788 23115228 : struct xfs_mount *mp = sc->mp;
789 23115228 : xfs_fileoff_t leaf_lblk;
790 23115228 : xfs_fileoff_t free_lblk;
791 23115228 : xfs_fileoff_t lblk;
792 23115228 : struct xfs_iext_cursor icur;
793 23115228 : xfs_dablk_t dabno;
794 23115228 : xfs_dir2_db_t last_data_db = 0;
795 23115228 : bool found;
796 23115228 : bool is_block = false;
797 23115228 : int error;
798 :
799 : /* Ignore local format directories. */
800 23115228 : if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
801 : ifp->if_format != XFS_DINODE_FMT_BTREE)
802 : return 0;
803 :
804 417549 : lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
805 417549 : leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
806 417549 : free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
807 :
808 : /* Is this a block dir? */
809 417549 : error = xfs_dir2_isblock(&args, &is_block);
810 417542 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
811 0 : goto out;
812 :
813 : /* Iterate all the data extents in the directory... */
814 417506 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
815 1217661 : while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
816 : /* No more data blocks... */
817 853214 : if (got.br_startoff >= leaf_lblk)
818 : break;
819 :
820 : /*
821 : * Check each data block's bestfree data.
822 : *
823 : * Iterate all the fsbcount-aligned block offsets in
824 : * this directory. The directory block reading code is
825 : * smart enough to do its own bmap lookups to handle
826 : * discontiguous directory blocks. When we're done
827 : * with the extent record, re-query the bmap at the
828 : * next fsbcount-aligned offset to avoid redundant
829 : * block checks.
830 : */
831 800116 : for (lblk = roundup((xfs_dablk_t)got.br_startoff,
832 : args.geo->fsbcount);
833 1740787 : lblk < got.br_startoff + got.br_blockcount;
834 940671 : lblk += args.geo->fsbcount) {
835 940645 : last_data_db = xfs_dir2_da_to_db(args.geo, lblk);
836 940607 : error = xchk_directory_data_bestfree(sc, lblk,
837 : is_block);
838 940671 : if (error)
839 0 : goto out;
840 : }
841 800142 : dabno = got.br_startoff + got.br_blockcount;
842 800142 : lblk = roundup(dabno, args.geo->fsbcount);
843 800142 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
844 : }
845 :
846 417566 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
847 0 : goto out;
848 :
849 : /* Look for a leaf1 block, which has free info. */
850 417566 : if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) &&
851 53098 : got.br_startoff == leaf_lblk &&
852 106195 : got.br_blockcount == args.geo->fsbcount &&
853 53097 : !xfs_iext_next_extent(ifp, &icur, &got)) {
854 20835 : if (is_block) {
855 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
856 0 : goto out;
857 : }
858 20835 : error = xchk_directory_leaf1_bestfree(sc, &args, last_data_db,
859 : leaf_lblk);
860 20835 : if (error)
861 0 : goto out;
862 : }
863 :
864 417546 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
865 0 : goto out;
866 :
867 : /* Scan for free blocks */
868 417546 : lblk = free_lblk;
869 417546 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
870 449836 : while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
871 : /*
872 : * Dirs can't have blocks mapped above 2^32.
873 : * Single-block dirs shouldn't even be here.
874 : */
875 32292 : lblk = got.br_startoff;
876 32292 : if (lblk & ~0xFFFFFFFFULL) {
877 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
878 0 : goto out;
879 : }
880 32292 : if (is_block) {
881 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
882 0 : goto out;
883 : }
884 :
885 : /*
886 : * Check each dir free block's bestfree data.
887 : *
888 : * Iterate all the fsbcount-aligned block offsets in
889 : * this directory. The directory block reading code is
890 : * smart enough to do its own bmap lookups to handle
891 : * discontiguous directory blocks. When we're done
892 : * with the extent record, re-query the bmap at the
893 : * next fsbcount-aligned offset to avoid redundant
894 : * block checks.
895 : */
896 32292 : for (lblk = roundup((xfs_dablk_t)got.br_startoff,
897 : args.geo->fsbcount);
898 64584 : lblk < got.br_startoff + got.br_blockcount;
899 32292 : lblk += args.geo->fsbcount) {
900 32292 : error = xchk_directory_free_bestfree(sc, &args,
901 : lblk);
902 32292 : if (error)
903 0 : goto out;
904 : }
905 32292 : dabno = got.br_startoff + got.br_blockcount;
906 32292 : lblk = roundup(dabno, args.geo->fsbcount);
907 32292 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
908 : }
909 417561 : out:
910 417561 : return error;
911 : }
912 :
913 : /*
914 : * Revalidate a dirent that we collected in the past but couldn't check because
915 : * of lock contention. Returns 0 if the dirent is still valid, -ENOENT if it
916 : * has gone away on us, or a negative errno.
917 : */
918 : STATIC int
919 0 : xchk_dir_revalidate_dirent(
920 : struct xchk_dir *sd,
921 : const struct xfs_name *xname,
922 : xfs_ino_t ino)
923 : {
924 0 : struct xfs_scrub *sc = sd->sc;
925 0 : xfs_ino_t child_ino;
926 0 : int error;
927 :
928 : /*
929 : * Look up the directory entry. If we get -ENOENT, the directory entry
930 : * went away and there's nothing to revalidate. Return any other
931 : * error.
932 : */
933 0 : error = xchk_dir_lookup(sc, sc->ip, xname, &child_ino);
934 0 : if (error)
935 : return error;
936 :
937 : /* The inode number changed, nothing to revalidate. */
938 0 : if (ino != child_ino)
939 0 : return -ENOENT;
940 :
941 : return 0;
942 : }
943 :
944 : /*
945 : * Check a directory entry's parent pointers the slow way, which means we cycle
946 : * locks a bunch and put up with revalidation until we get it done.
947 : */
948 : STATIC int
949 0 : xchk_dir_slow_dirent(
950 : struct xchk_dir *sd,
951 : struct xchk_dirent *dirent)
952 : {
953 0 : struct xfs_name xname = {
954 0 : .name = sd->namebuf,
955 0 : .len = dirent->namelen,
956 : };
957 0 : struct xfs_scrub *sc = sd->sc;
958 0 : struct xfs_inode *ip;
959 0 : unsigned int lockmode;
960 0 : int error;
961 :
962 : /* Check that the deferred dirent still exists. */
963 0 : if (sd->need_revalidate) {
964 0 : error = xchk_dir_revalidate_dirent(sd, &xname, dirent->ino);
965 0 : if (error == -ENOENT)
966 : return 0;
967 0 : if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
968 : &error))
969 0 : return error;
970 : }
971 :
972 0 : error = xchk_iget(sc, dirent->ino, &ip);
973 0 : if (error == -EINVAL || error == -ENOENT) {
974 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
975 0 : return 0;
976 : }
977 0 : if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
978 0 : return error;
979 :
980 : /*
981 : * If we can grab both IOLOCK and ILOCK of the alleged child, we can
982 : * proceed with the validation.
983 : */
984 0 : lockmode = xchk_dir_lock_child(sc, ip);
985 0 : if (lockmode)
986 0 : goto check_pptr;
987 :
988 : /*
989 : * We couldn't lock the child file. Drop all the locks and try to
990 : * get them again, one at a time.
991 : */
992 0 : xchk_iunlock(sc, sc->ilock_flags);
993 0 : sd->need_revalidate = true;
994 :
995 0 : trace_xchk_dir_slowpath(sc->ip, xname.name, xname.len, ip->i_ino);
996 :
997 0 : while (true) {
998 0 : xchk_ilock(sc, XFS_IOLOCK_EXCL);
999 0 : if (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
1000 0 : xchk_ilock(sc, XFS_ILOCK_EXCL);
1001 0 : if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
1002 : break;
1003 : }
1004 0 : xchk_iunlock(sc, XFS_ILOCK_EXCL);
1005 : }
1006 0 : xchk_iunlock(sc, XFS_IOLOCK_EXCL);
1007 :
1008 0 : if (xchk_should_terminate(sc, &error))
1009 0 : goto out_rele;
1010 :
1011 0 : delay(1);
1012 : }
1013 0 : lockmode = XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
1014 :
1015 : /* Revalidate, since we just cycled the locks. */
1016 0 : error = xchk_dir_revalidate_dirent(sd, &xname, dirent->ino);
1017 0 : if (error == -ENOENT)
1018 0 : goto out_unlock;
1019 0 : if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
1020 0 : goto out_unlock;
1021 :
1022 0 : check_pptr:
1023 0 : error = xchk_dir_parent_pointer(sd, &xname, ip);
1024 0 : out_unlock:
1025 0 : xfs_iunlock(ip, lockmode);
1026 0 : out_rele:
1027 0 : xchk_irele(sc, ip);
1028 0 : return error;
1029 : }
1030 :
1031 : /* Check all the dirents that we deferred the first time around. */
1032 : STATIC int
1033 22482506 : xchk_dir_finish_slow_dirents(
1034 : struct xchk_dir *sd)
1035 : {
1036 22482506 : xfarray_idx_t array_cur;
1037 22482506 : int error;
1038 :
1039 22482506 : foreach_xfarray_idx(sd->dir_entries, array_cur) {
1040 0 : struct xchk_dirent dirent;
1041 :
1042 0 : if (sd->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
1043 0 : return 0;
1044 :
1045 0 : error = xfarray_load(sd->dir_entries, array_cur, &dirent);
1046 0 : if (error)
1047 0 : return error;
1048 :
1049 0 : error = xfblob_load(sd->dir_names, dirent.name_cookie,
1050 0 : sd->namebuf, dirent.namelen);
1051 0 : if (error)
1052 0 : return error;
1053 0 : sd->namebuf[MAXNAMELEN - 1] = 0;
1054 :
1055 0 : error = xchk_dir_slow_dirent(sd, &dirent);
1056 0 : if (error)
1057 0 : return error;
1058 : }
1059 :
1060 : return 0;
1061 : }
1062 :
1063 : /* Scrub a whole directory. */
1064 : int
1065 23135967 : xchk_directory(
1066 : struct xfs_scrub *sc)
1067 : {
1068 23135967 : struct xchk_dir *sd;
1069 23135967 : int error;
1070 :
1071 23135967 : if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
1072 : return -ENOENT;
1073 :
1074 : /* Plausible size? */
1075 23135967 : if (sc->ip->i_disk_size < xfs_dir2_sf_hdr_size(0)) {
1076 0 : xchk_ino_set_corrupt(sc, sc->ip->i_ino);
1077 0 : return 0;
1078 : }
1079 :
1080 : /* Check directory tree structure */
1081 23135967 : error = xchk_da_btree(sc, XFS_DATA_FORK, xchk_dir_rec, NULL);
1082 23073369 : if (error)
1083 : return error;
1084 :
1085 23073368 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
1086 : return 0;
1087 :
1088 : /* Check the freespace. */
1089 23071998 : error = xchk_directory_blocks(sc);
1090 23041424 : if (error)
1091 : return error;
1092 :
1093 23041424 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
1094 : return 0;
1095 :
1096 23042547 : sd = kvzalloc(sizeof(struct xchk_dir), XCHK_GFP_FLAGS);
1097 23143694 : if (!sd)
1098 : return -ENOMEM;
1099 23143694 : sd->sc = sc;
1100 :
1101 23143694 : if (xfs_has_parent(sc->mp)) {
1102 22460052 : char *descr;
1103 :
1104 : /*
1105 : * Set up some staging memory for dirents that we can't check
1106 : * due to locking contention.
1107 : */
1108 22460052 : descr = xchk_xfile_ino_descr(sc, "slow directory entries");
1109 22399420 : error = xfarray_create(descr, 0, sizeof(struct xchk_dirent),
1110 : &sd->dir_entries);
1111 22421296 : kfree(descr);
1112 22443550 : if (error)
1113 0 : goto out_sd;
1114 :
1115 22443550 : descr = xchk_xfile_ino_descr(sc, "slow directory entry names");
1116 22424119 : error = xfblob_create(descr, &sd->dir_names);
1117 22484943 : kfree(descr);
1118 22468629 : if (error)
1119 0 : goto out_entries;
1120 : }
1121 :
1122 : /* Look up every name in this directory by hash. */
1123 23152271 : error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, sd);
1124 23170399 : if (error == -ECANCELED)
1125 : error = 0;
1126 23173790 : if (error)
1127 4 : goto out_names;
1128 :
1129 23170395 : if (xfs_has_parent(sc->mp)) {
1130 22483284 : error = xchk_dir_finish_slow_dirents(sd);
1131 22469496 : if (error)
1132 0 : goto out_names;
1133 : }
1134 :
1135 23156607 : out_names:
1136 23156611 : if (sd->dir_names)
1137 22469730 : xfblob_destroy(sd->dir_names);
1138 686881 : out_entries:
1139 23166590 : if (sd->dir_entries)
1140 22479848 : xfarray_destroy(sd->dir_entries);
1141 686742 : out_sd:
1142 23168097 : kvfree(sd);
1143 23168097 : return error;
1144 : }
1145 :
1146 : /*
1147 : * Decide if this directory has been zapped to satisfy the inode and ifork
1148 : * verifiers. Checking and repairing should be postponed until the directory
1149 : * is fixed.
1150 : */
1151 : bool
1152 180429096 : xchk_dir_looks_zapped(
1153 : struct xfs_inode *dp)
1154 : {
1155 : /*
1156 : * If the dinode repair found a bad data fork, it will reset the fork
1157 : * to extents format with zero records and wait for the bmapbtd
1158 : * scrubber to reconstruct the block mappings. Directories always
1159 : * contain some content, so this is a clear sign of a zapped directory.
1160 : */
1161 180429096 : if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS)
1162 808084 : return dp->i_df.if_nextents == 0;
1163 :
1164 : return false;
1165 : }
|