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 14306065 : xchk_setup_directory(
33 : struct xfs_scrub *sc)
34 : {
35 14306065 : int error;
36 :
37 28612130 : if (xchk_could_repair(sc)) {
38 184730 : error = xrep_setup_directory(sc);
39 184635 : if (error)
40 : return error;
41 : }
42 :
43 14305970 : 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 137805824 : xchk_dir_check_ftype(
88 : struct xfs_scrub *sc,
89 : xfs_fileoff_t offset,
90 : struct xfs_inode *ip,
91 : int ftype)
92 : {
93 137805824 : struct xfs_mount *mp = sc->mp;
94 :
95 137805824 : 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 137805824 : 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 109192726 : xchk_dir_lock_child(
111 : struct xfs_scrub *sc,
112 : struct xfs_inode *ip)
113 : {
114 109192726 : if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
115 : return 0;
116 :
117 109151562 : if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
118 323 : xfs_iunlock(ip, XFS_IOLOCK_SHARED);
119 323 : return 0;
120 : }
121 :
122 218302588 : if (!xfs_inode_has_attr_fork(ip) || !xfs_need_iread_extents(&ip->i_af))
123 109151325 : return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;
124 :
125 35 : xfs_iunlock(ip, XFS_ILOCK_SHARED);
126 :
127 35 : 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 109150770 : xchk_dir_parent_pointer(
138 : struct xchk_dir *sd,
139 : const struct xfs_name *name,
140 : struct xfs_inode *ip)
141 : {
142 109150770 : struct xfs_scrub *sc = sd->sc;
143 109150770 : int error;
144 :
145 109150770 : sd->pptr.p_ino = sc->ip->i_ino;
146 109150770 : sd->pptr.p_gen = VFS_I(sc->ip)->i_generation;
147 109150770 : sd->pptr.p_namelen = name->len;
148 218301540 : memcpy(sd->pptr.p_name, name->name, name->len);
149 109150770 : xfs_parent_irec_hashname(sc->mp, &sd->pptr);
150 :
151 109152596 : error = xfs_parent_lookup(sc->tp, ip, &sd->pptr, &sd->pptr_scratch);
152 109147529 : if (error == -ENOATTR)
153 0 : xchk_fblock_xref_set_corrupt(sc, XFS_DATA_FORK, 0);
154 :
155 109147529 : return 0;
156 : }
157 :
158 : /* Look for a parent pointer matching this dirent, if the child isn't busy. */
159 : STATIC int
160 137790041 : 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 137790041 : struct xfs_scrub *sc = sd->sc;
167 137790041 : unsigned int lockmode;
168 137790041 : int error;
169 :
170 : /* dot and dotdot entries do not have parent pointers */
171 261286033 : if (xfs_dir2_samename(name, &xfs_name_dot) ||
172 123496147 : xfs_dir2_samename(name, &xfs_name_dotdot))
173 28604264 : return 0;
174 :
175 : /* Try to lock the inode. */
176 109195057 : lockmode = xchk_dir_lock_child(sc, ip);
177 109195203 : if (!lockmode) {
178 43834 : struct xchk_dirent save_de = {
179 43834 : .namelen = name->len,
180 43834 : .ino = ip->i_ino,
181 : };
182 :
183 : /* Couldn't lock the inode, so save the dirent for later. */
184 43834 : trace_xchk_dir_defer(sc->ip, name->name, name->len, ip->i_ino);
185 :
186 87668 : error = xfblob_store(sd->dir_names, &save_de.name_cookie,
187 43834 : name->name, name->len);
188 43834 : if (xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
189 : &error))
190 43834 : 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 109151369 : error = xchk_dir_parent_pointer(sd, name, ip);
201 109147027 : xfs_iunlock(ip, lockmode);
202 109152733 : 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 137800827 : 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 137800827 : struct xfs_mount *mp = dp->i_mount;
221 137800827 : struct xfs_inode *ip;
222 137800827 : struct xchk_dir *sd = priv;
223 137800827 : xfs_ino_t lookup_ino;
224 137800827 : xfs_dablk_t offset;
225 137800827 : int error = 0;
226 :
227 137800827 : offset = xfs_dir2_db_to_da(mp->m_dir_geo,
228 : xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos));
229 :
230 137800827 : if (xchk_should_terminate(sc, &error))
231 0 : return error;
232 :
233 : /* Does this inode number make sense? */
234 137802397 : 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 137807111 : if (!xfs_dir2_namecheck(name->name, name->len)) {
241 2 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
242 2 : return -ECANCELED;
243 : }
244 :
245 137807716 : if (xfs_dir2_samename(name, &xfs_name_dot)) {
246 : /* If this is "." then check that the inum matches the dir. */
247 14303371 : if (ino != dp->i_ino)
248 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
249 123508527 : } 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 14303880 : 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 137812716 : error = xchk_dir_lookup(sc, dp, name, &lookup_ino);
260 : /* ENOENT means the hash lookup failed and the dir is corrupt */
261 137801723 : if (error == -ENOENT)
262 0 : error = -EFSCORRUPTED;
263 137801723 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error))
264 0 : goto out;
265 137806088 : 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 137806088 : error = xchk_iget(sc, ino, &ip);
280 137805687 : 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 137805687 : if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, offset, &error))
286 0 : goto out;
287 :
288 137804862 : xchk_dir_check_ftype(sc, offset, ip, name->type);
289 :
290 137804061 : if (xfs_has_parent(mp)) {
291 137791449 : error = xchk_dir_check_pptr_fast(sd, dapos, name, ip);
292 137788613 : if (error)
293 : goto out_rele;
294 : }
295 :
296 137801225 : out_rele:
297 137801225 : xchk_irele(sc, ip);
298 137801627 : out:
299 137801627 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
300 : return -ECANCELED;
301 137801627 : return error;
302 : }
303 :
304 : /* Scrub a directory btree record. */
305 : STATIC int
306 60148292 : xchk_dir_rec(
307 : struct xchk_da_btree *ds,
308 : int level)
309 : {
310 60148292 : struct xfs_name dname = { };
311 60148292 : struct xfs_da_state_blk *blk = &ds->state->path.blk[level];
312 60148292 : struct xfs_mount *mp = ds->state->mp;
313 60148292 : struct xfs_inode *dp = ds->dargs.dp;
314 60148292 : struct xfs_da_geometry *geo = mp->m_dir_geo;
315 60148292 : struct xfs_dir2_data_entry *dent;
316 60148292 : struct xfs_buf *bp;
317 60148292 : struct xfs_dir2_leaf_entry *ent;
318 60148292 : unsigned int end;
319 60148292 : unsigned int iter_off;
320 60148292 : xfs_ino_t ino;
321 60148292 : xfs_dablk_t rec_bno;
322 60148292 : xfs_dir2_db_t db;
323 60148292 : xfs_dir2_data_aoff_t off;
324 60148292 : xfs_dir2_dataptr_t ptr;
325 60148292 : xfs_dahash_t calc_hash;
326 60148292 : xfs_dahash_t hash;
327 60148292 : struct xfs_dir3_icleaf_hdr hdr;
328 60148292 : unsigned int tag;
329 60148292 : int error;
330 :
331 60148292 : ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC ||
332 : blk->magic == XFS_DIR2_LEAFN_MAGIC);
333 :
334 60148292 : xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr);
335 60148433 : ent = hdr.ents + blk->index;
336 :
337 : /* Check the hash of the entry. */
338 60148433 : error = xchk_da_btree_hash(ds, level, &ent->hashval);
339 60147894 : if (error)
340 0 : goto out;
341 :
342 : /* Valid hash pointer? */
343 60147894 : ptr = be32_to_cpu(ent->address);
344 60147894 : if (ptr == 0)
345 : return 0;
346 :
347 : /* Find the directory entry's location. */
348 50266035 : db = xfs_dir2_dataptr_to_db(geo, ptr);
349 50266035 : off = xfs_dir2_dataptr_to_off(geo, ptr);
350 50266035 : rec_bno = xfs_dir2_db_to_da(geo, db);
351 :
352 50266035 : if (rec_bno >= geo->leafblk) {
353 0 : xchk_da_set_corrupt(ds, level);
354 0 : goto out;
355 : }
356 50266035 : error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner,
357 : rec_bno, XFS_DABUF_MAP_HOLE_OK, &bp);
358 50265676 : if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno,
359 : &error))
360 0 : goto out;
361 50266029 : if (!bp) {
362 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
363 0 : goto out;
364 : }
365 50266029 : xchk_buffer_recheck(ds->sc, bp);
366 :
367 50262907 : if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
368 0 : goto out_relse;
369 :
370 50262907 : dent = bp->b_addr + off;
371 :
372 : /* Make sure we got a real directory entry. */
373 50262907 : iter_off = geo->data_entry_offset;
374 50262907 : end = xfs_dir3_data_end_offset(geo, bp->b_addr);
375 50261444 : if (!end) {
376 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
377 0 : goto out_relse;
378 : }
379 5007458583 : for (;;) {
380 5007458583 : struct xfs_dir2_data_entry *dep = bp->b_addr + iter_off;
381 5007458583 : struct xfs_dir2_data_unused *dup = bp->b_addr + iter_off;
382 :
383 5007458583 : 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 5007458583 : if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
389 275525547 : iter_off += be16_to_cpu(dup->length);
390 275525547 : continue;
391 : }
392 4731933036 : if (dep == dent)
393 : break;
394 9371387064 : iter_off += xfs_dir2_data_entsize(mp, dep->namelen);
395 : }
396 :
397 : /* Retrieve the entry, sanity check it, and compare hashes. */
398 50261444 : ino = be64_to_cpu(dent->inumber);
399 50261444 : hash = be32_to_cpu(ent->hashval);
400 50261444 : tag = be16_to_cpup(xfs_dir2_data_entry_tag_p(mp, dent));
401 50262241 : if (!xfs_verify_dir_ino(mp, ino) || tag != off)
402 322 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
403 50262899 : 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 50262899 : dname.name = dent->name;
410 50262899 : dname.len = dent->namelen;
411 50262899 : calc_hash = xfs_dir2_hashname(mp, &dname);
412 50264698 : if (calc_hash != hash)
413 0 : xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
414 :
415 50264698 : out_relse:
416 50264698 : xfs_trans_brelse(ds->dargs.trans, bp);
417 50266134 : out:
418 50266134 : 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 5181813 : 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 5181813 : struct xfs_dir2_data_free *dfp;
434 5181813 : unsigned int dup_length;
435 :
436 5181813 : dup_length = be16_to_cpu(dup->length);
437 :
438 : /* Unused entry is shorter than any of the bestfrees */
439 5181813 : if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
440 : return;
441 :
442 4208941 : for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--)
443 4208941 : 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 576550 : xchk_directory_data_bestfree(
453 : struct xfs_scrub *sc,
454 : xfs_dablk_t lblk,
455 : bool is_block)
456 : {
457 576550 : struct xfs_dir2_data_unused *dup;
458 576550 : struct xfs_dir2_data_free *dfp;
459 576550 : struct xfs_buf *bp;
460 576550 : struct xfs_dir2_data_free *bf;
461 576550 : struct xfs_mount *mp = sc->mp;
462 576550 : u16 tag;
463 576550 : unsigned int nr_bestfrees = 0;
464 576550 : unsigned int nr_frees = 0;
465 576550 : unsigned int smallest_bestfree;
466 576550 : int newlen;
467 576550 : unsigned int offset;
468 576550 : unsigned int end;
469 576550 : int error;
470 :
471 576550 : if (is_block) {
472 : /* dir block format */
473 270752 : if (lblk != XFS_B_TO_FSBT(mp, XFS_DIR2_DATA_OFFSET))
474 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
475 270752 : error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp);
476 : } else {
477 : /* dir data format */
478 305798 : error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk,
479 : 0, &bp);
480 : }
481 576551 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
482 0 : goto out;
483 576551 : xchk_buffer_recheck(sc, bp);
484 :
485 : /* XXX: Check xfs_dir3_data_hdr.pad is zero once we start setting it. */
486 :
487 576550 : 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 576550 : bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr);
492 576550 : smallest_bestfree = UINT_MAX;
493 2882751 : for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
494 1729651 : offset = be16_to_cpu(dfp->offset);
495 1729651 : if (offset == 0)
496 490757 : continue;
497 1238894 : 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 1238894 : dup = bp->b_addr + offset;
502 1238894 : tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
503 :
504 : /* bestfree doesn't match the entry it points at? */
505 2477788 : if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) ||
506 1238894 : be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) ||
507 1238894 : 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 1238894 : 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 1238894 : smallest_bestfree = be16_to_cpu(dfp->length);
519 1238894 : nr_bestfrees++;
520 : }
521 :
522 : /* Make sure the bestfrees are actually the best free spaces. */
523 576550 : offset = mp->m_dir_geo->data_entry_offset;
524 576550 : 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 61428600 : while (offset < end) {
528 60852049 : dup = bp->b_addr + offset;
529 :
530 : /* Skip real entries */
531 60852049 : if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) {
532 55670236 : struct xfs_dir2_data_entry *dep = bp->b_addr + offset;
533 :
534 55670236 : newlen = xfs_dir2_data_entsize(mp, dep->namelen);
535 55670236 : if (newlen <= 0) {
536 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
537 : lblk);
538 : goto out_buf;
539 : }
540 55670236 : offset += newlen;
541 55670236 : continue;
542 : }
543 :
544 : /* Spot check this free entry */
545 5181813 : tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
546 5181813 : 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 5181813 : xchk_directory_check_free_entry(sc, lblk, bf, dup);
556 5181814 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
557 0 : goto out_buf;
558 :
559 : /* Move on. */
560 5181814 : newlen = be16_to_cpu(dup->length);
561 5181814 : if (newlen <= 0) {
562 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
563 0 : goto out_buf;
564 : }
565 5181814 : offset += newlen;
566 5181814 : if (offset <= end)
567 5181814 : nr_frees++;
568 : }
569 :
570 : /* We're required to fill all the space. */
571 576551 : 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 576551 : if (nr_frees < nr_bestfrees)
576 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
577 576551 : out_buf:
578 576551 : xfs_trans_brelse(sc->tp, bp);
579 576551 : out:
580 576551 : 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 305798 : 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 305798 : struct xfs_dir2_data_free *dfp;
597 :
598 305798 : dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr);
599 :
600 305798 : if (len != be16_to_cpu(dfp->length))
601 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
602 :
603 305798 : if (len > 0 && be16_to_cpu(dfp->offset) == 0)
604 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
605 305798 : }
606 :
607 : /* Check free space info in a directory leaf1 block. */
608 : STATIC int
609 6244 : 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 6244 : struct xfs_dir3_icleaf_hdr leafhdr;
616 6244 : struct xfs_dir2_leaf_tail *ltp;
617 6244 : struct xfs_dir2_leaf *leaf;
618 6244 : struct xfs_buf *dbp;
619 6244 : struct xfs_buf *bp;
620 6244 : struct xfs_da_geometry *geo = sc->mp->m_dir_geo;
621 6244 : __be16 *bestp;
622 6244 : __u16 best;
623 6244 : __u32 hash;
624 6244 : __u32 lasthash = 0;
625 6244 : __u32 bestcount;
626 6244 : unsigned int stale = 0;
627 6244 : int i;
628 6244 : int error;
629 :
630 : /* Read the free space block. */
631 6244 : error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
632 6244 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
633 0 : return error;
634 6244 : xchk_buffer_recheck(sc, bp);
635 :
636 6244 : leaf = bp->b_addr;
637 6244 : xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf);
638 6244 : ltp = xfs_dir2_leaf_tail_p(geo, leaf);
639 6244 : bestcount = be32_to_cpu(ltp->bestcount);
640 6244 : bestp = xfs_dir2_leaf_bests_p(ltp);
641 :
642 6244 : if (xfs_has_crc(sc->mp)) {
643 6244 : struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr;
644 :
645 6244 : 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 6244 : 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 6244 : 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 6244 : 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 1731726 : for (i = 0; i < leafhdr.count; i++) {
676 1725482 : hash = be32_to_cpu(leafhdr.ents[i].hashval);
677 1725482 : if (i > 0 && lasthash > hash)
678 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
679 1725482 : lasthash = hash;
680 1725482 : if (leafhdr.ents[i].address ==
681 : cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
682 350134 : stale++;
683 : }
684 6244 : if (leafhdr.stale != stale)
685 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
686 6244 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
687 0 : goto out;
688 :
689 : /* Check all the bestfree entries. */
690 18191 : for (i = 0; i < bestcount; i++, bestp++) {
691 11947 : best = be16_to_cpu(*bestp);
692 11947 : 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 11947 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
696 : &error))
697 : break;
698 :
699 11947 : if (!dbp) {
700 62 : if (best != NULLDATAOFF) {
701 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
702 : lblk);
703 0 : break;
704 : }
705 62 : continue;
706 : }
707 :
708 11885 : if (best == NULLDATAOFF)
709 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
710 : else
711 11885 : xchk_directory_check_freesp(sc, lblk, dbp, best);
712 11885 : xfs_trans_brelse(sc->tp, dbp);
713 11885 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
714 : break;
715 : }
716 6244 : out:
717 6244 : xfs_trans_brelse(sc->tp, bp);
718 6244 : return error;
719 : }
720 :
721 : /* Check free space info in a directory freespace block. */
722 : STATIC int
723 16627 : xchk_directory_free_bestfree(
724 : struct xfs_scrub *sc,
725 : struct xfs_da_args *args,
726 : xfs_dablk_t lblk)
727 : {
728 16627 : struct xfs_dir3_icfree_hdr freehdr;
729 16627 : struct xfs_buf *dbp;
730 16627 : struct xfs_buf *bp;
731 16627 : __u16 best;
732 16627 : unsigned int stale = 0;
733 16627 : int i;
734 16627 : int error;
735 :
736 : /* Read the free space block */
737 16627 : error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
738 16627 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
739 0 : return error;
740 16627 : xchk_buffer_recheck(sc, bp);
741 :
742 16627 : if (xfs_has_crc(sc->mp)) {
743 16627 : struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
744 :
745 16627 : 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 16627 : xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr);
751 331765 : for (i = 0; i < freehdr.nvalid; i++) {
752 298511 : best = be16_to_cpu(freehdr.bests[i]);
753 298511 : if (best == NULLDATAOFF) {
754 4598 : stale++;
755 4598 : continue;
756 : }
757 587826 : error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
758 293913 : (freehdr.firstdb + i) * args->geo->fsbcount,
759 : 0, &dbp);
760 293913 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
761 : &error))
762 0 : goto out;
763 293913 : xchk_directory_check_freesp(sc, lblk, dbp, best);
764 293913 : xfs_trans_brelse(sc->tp, dbp);
765 : }
766 :
767 16627 : if (freehdr.nused + stale != freehdr.nvalid)
768 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
769 16627 : out:
770 16627 : xfs_trans_brelse(sc->tp, bp);
771 16627 : return error;
772 : }
773 :
774 : /* Check free space information in directories. */
775 : STATIC int
776 14303770 : xchk_directory_blocks(
777 : struct xfs_scrub *sc)
778 : {
779 14303770 : struct xfs_bmbt_irec got;
780 14303770 : struct xfs_da_args args = {
781 14303770 : .dp = sc->ip,
782 : .whichfork = XFS_DATA_FORK,
783 14303770 : .geo = sc->mp->m_dir_geo,
784 14303770 : .trans = sc->tp,
785 14303770 : .owner = sc->ip->i_ino,
786 : };
787 14303770 : struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
788 14303770 : struct xfs_mount *mp = sc->mp;
789 14303770 : xfs_fileoff_t leaf_lblk;
790 14303770 : xfs_fileoff_t free_lblk;
791 14303770 : xfs_fileoff_t lblk;
792 14303770 : struct xfs_iext_cursor icur;
793 14303770 : xfs_dablk_t dabno;
794 14303770 : xfs_dir2_db_t last_data_db = 0;
795 14303770 : bool found;
796 14303770 : bool is_block = false;
797 14303770 : int error;
798 :
799 : /* Ignore local format directories. */
800 14303770 : if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
801 : ifp->if_format != XFS_DINODE_FMT_BTREE)
802 : return 0;
803 :
804 293621 : lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
805 293621 : leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
806 293621 : free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
807 :
808 : /* Is this a block dir? */
809 293621 : error = xfs_dir2_isblock(&args, &is_block);
810 293620 : 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 293621 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
815 815205 : while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
816 : /* No more data blocks... */
817 544452 : 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 521584 : for (lblk = roundup((xfs_dablk_t)got.br_startoff,
832 : args.geo->fsbcount);
833 1098135 : lblk < got.br_startoff + got.br_blockcount;
834 576551 : lblk += args.geo->fsbcount) {
835 576550 : last_data_db = xfs_dir2_da_to_db(args.geo, lblk);
836 576550 : error = xchk_directory_data_bestfree(sc, lblk,
837 : is_block);
838 576551 : if (error)
839 0 : goto out;
840 : }
841 521585 : dabno = got.br_startoff + got.br_blockcount;
842 521585 : lblk = roundup(dabno, args.geo->fsbcount);
843 521585 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
844 : }
845 :
846 293621 : 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 293621 : if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) &&
851 22868 : got.br_startoff == leaf_lblk &&
852 45736 : got.br_blockcount == args.geo->fsbcount &&
853 22868 : !xfs_iext_next_extent(ifp, &icur, &got)) {
854 6244 : if (is_block) {
855 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
856 0 : goto out;
857 : }
858 6244 : error = xchk_directory_leaf1_bestfree(sc, &args, last_data_db,
859 : leaf_lblk);
860 6244 : if (error)
861 0 : goto out;
862 : }
863 :
864 293621 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
865 0 : goto out;
866 :
867 : /* Scan for free blocks */
868 293621 : lblk = free_lblk;
869 293621 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
870 310246 : 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 16627 : lblk = got.br_startoff;
876 16627 : if (lblk & ~0xFFFFFFFFULL) {
877 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
878 0 : goto out;
879 : }
880 16627 : 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 16627 : for (lblk = roundup((xfs_dablk_t)got.br_startoff,
897 : args.geo->fsbcount);
898 33254 : lblk < got.br_startoff + got.br_blockcount;
899 16627 : lblk += args.geo->fsbcount) {
900 16627 : error = xchk_directory_free_bestfree(sc, &args,
901 : lblk);
902 16627 : if (error)
903 0 : goto out;
904 : }
905 16627 : dabno = got.br_startoff + got.br_blockcount;
906 16627 : lblk = roundup(dabno, args.geo->fsbcount);
907 16627 : found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
908 : }
909 293619 : out:
910 293619 : 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 14302318 : xchk_dir_finish_slow_dirents(
1034 : struct xchk_dir *sd)
1035 : {
1036 14302318 : xfarray_idx_t array_cur;
1037 14302318 : int error;
1038 :
1039 14302318 : 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 14303799 : xchk_directory(
1066 : struct xfs_scrub *sc)
1067 : {
1068 14303799 : struct xchk_dir *sd;
1069 14303799 : int error;
1070 :
1071 14303799 : if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
1072 : return -ENOENT;
1073 :
1074 : /* Plausible size? */
1075 14303799 : 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 14303799 : error = xchk_da_btree(sc, XFS_DATA_FORK, xchk_dir_rec, NULL);
1082 14303898 : if (error)
1083 : return error;
1084 :
1085 14303897 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
1086 : return 0;
1087 :
1088 : /* Check the freespace. */
1089 14303871 : error = xchk_directory_blocks(sc);
1090 14303983 : if (error)
1091 : return error;
1092 :
1093 14303983 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
1094 : return 0;
1095 :
1096 14304015 : sd = kvzalloc(sizeof(struct xchk_dir), XCHK_GFP_FLAGS);
1097 14303795 : if (!sd)
1098 : return -ENOMEM;
1099 14303795 : sd->sc = sc;
1100 :
1101 14303795 : if (xfs_has_parent(sc->mp)) {
1102 14302477 : char *descr;
1103 :
1104 : /*
1105 : * Set up some staging memory for dirents that we can't check
1106 : * due to locking contention.
1107 : */
1108 14302477 : descr = xchk_xfile_ino_descr(sc, "slow directory entries");
1109 14302385 : error = xfarray_create(descr, 0, sizeof(struct xchk_dirent),
1110 : &sd->dir_entries);
1111 14302243 : kfree(descr);
1112 14302533 : if (error)
1113 0 : goto out_sd;
1114 :
1115 14302533 : descr = xchk_xfile_ino_descr(sc, "slow directory entry names");
1116 14302086 : error = xfblob_create(descr, &sd->dir_names);
1117 14302630 : kfree(descr);
1118 14302658 : if (error)
1119 0 : goto out_entries;
1120 : }
1121 :
1122 : /* Look up every name in this directory by hash. */
1123 14303976 : error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, sd);
1124 14303901 : if (error == -ECANCELED)
1125 : error = 0;
1126 14303892 : if (error)
1127 0 : goto out_names;
1128 :
1129 14303901 : if (xfs_has_parent(sc->mp)) {
1130 14302583 : error = xchk_dir_finish_slow_dirents(sd);
1131 14302432 : if (error)
1132 0 : goto out_names;
1133 : }
1134 :
1135 14303750 : out_names:
1136 14303750 : if (sd->dir_names)
1137 14302432 : xfblob_destroy(sd->dir_names);
1138 1318 : out_entries:
1139 14303996 : if (sd->dir_entries)
1140 14302678 : xfarray_destroy(sd->dir_entries);
1141 1318 : out_sd:
1142 14304003 : kvfree(sd);
1143 14304003 : 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 168975201 : 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 168975201 : if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS)
1162 696361 : return dp->i_df.if_nextents == 0;
1163 :
1164 : return false;
1165 : }
|