1050 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2021-2024 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_iwalk.h"17#include "xfs_ialloc.h"18#include "xfs_dir2.h"19#include "xfs_dir2_priv.h"20#include "xfs_ag.h"21#include "xfs_parent.h"22#include "scrub/scrub.h"23#include "scrub/common.h"24#include "scrub/repair.h"25#include "scrub/xfile.h"26#include "scrub/xfarray.h"27#include "scrub/iscan.h"28#include "scrub/orphanage.h"29#include "scrub/nlinks.h"30#include "scrub/trace.h"31#include "scrub/readdir.h"32#include "scrub/tempfile.h"33#include "scrub/listxattr.h"34 35/*36 * Live Inode Link Count Checking37 * ==============================38 *39 * Inode link counts are "summary" metadata, in the sense that they are40 * computed as the number of directory entries referencing each file on the41 * filesystem. Therefore, we compute the correct link counts by creating a42 * shadow link count structure and walking every inode.43 */44 45/* Set us up to scrub inode link counts. */46int47xchk_setup_nlinks(48 struct xfs_scrub *sc)49{50 struct xchk_nlink_ctrs *xnc;51 int error;52 53 xchk_fsgates_enable(sc, XCHK_FSGATES_DIRENTS);54 55 if (xchk_could_repair(sc)) {56 error = xrep_setup_nlinks(sc);57 if (error)58 return error;59 }60 61 xnc = kvzalloc(sizeof(struct xchk_nlink_ctrs), XCHK_GFP_FLAGS);62 if (!xnc)63 return -ENOMEM;64 xnc->xname.name = xnc->namebuf;65 xnc->sc = sc;66 sc->buf = xnc;67 68 return xchk_setup_fs(sc);69}70 71/*72 * Part 1: Collecting file link counts. For each file, we create a shadow link73 * counting structure, then walk the entire directory tree, incrementing parent74 * and child link counts for each directory entry seen.75 *76 * To avoid false corruption reports in part 2, any failure in this part must77 * set the INCOMPLETE flag even when a negative errno is returned. This care78 * must be taken with certain errno values (i.e. EFSBADCRC, EFSCORRUPTED,79 * ECANCELED) that are absorbed into a scrub state flag update by80 * xchk_*_process_error. Scrub and repair share the same incore data81 * structures, so the INCOMPLETE flag is critical to prevent a repair based on82 * insufficient information.83 *84 * Because we are scanning a live filesystem, it's possible that another thread85 * will try to update the link counts for an inode that we've already scanned.86 * This will cause our counts to be incorrect. Therefore, we hook all87 * directory entry updates because that is when link count updates occur. By88 * shadowing transaction updates in this manner, live nlink check can ensure by89 * locking the inode and the shadow structure that its own copies are not out90 * of date. Because the hook code runs in a different process context from the91 * scrub code and the scrub state flags are not accessed atomically, failures92 * in the hook code must abort the iscan and the scrubber must notice the93 * aborted scan and set the incomplete flag.94 *95 * Note that we use jump labels and srcu notifier hooks to minimize the96 * overhead when live nlinks is /not/ running. Locking order for nlink97 * observations is inode ILOCK -> iscan_lock/xchk_nlink_ctrs lock.98 */99 100/*101 * Add a delta to an nlink counter, clamping the value to U32_MAX. Because102 * XFS_MAXLINK < U32_MAX, the checking code will produce the correct results103 * even if we lose some precision.104 */105static inline void106careful_add(107 xfs_nlink_t *nlinkp,108 int delta)109{110 uint64_t new_value = (uint64_t)(*nlinkp) + delta;111 112 BUILD_BUG_ON(XFS_MAXLINK > U32_MAX);113 *nlinkp = min_t(uint64_t, new_value, U32_MAX);114}115 116/* Update incore link count information. Caller must hold the nlinks lock. */117STATIC int118xchk_nlinks_update_incore(119 struct xchk_nlink_ctrs *xnc,120 xfs_ino_t ino,121 int parents_delta,122 int backrefs_delta,123 int children_delta)124{125 struct xchk_nlink nl;126 int error;127 128 if (!xnc->nlinks)129 return 0;130 131 error = xfarray_load_sparse(xnc->nlinks, ino, &nl);132 if (error)133 return error;134 135 trace_xchk_nlinks_update_incore(xnc->sc->mp, ino, &nl, parents_delta,136 backrefs_delta, children_delta);137 138 careful_add(&nl.parents, parents_delta);139 careful_add(&nl.backrefs, backrefs_delta);140 careful_add(&nl.children, children_delta);141 142 nl.flags |= XCHK_NLINK_WRITTEN;143 error = xfarray_store(xnc->nlinks, ino, &nl);144 if (error == -EFBIG) {145 /*146 * EFBIG means we tried to store data at too high a byte offset147 * in the sparse array. IOWs, we cannot complete the check and148 * must notify userspace that the check was incomplete.149 */150 error = -ECANCELED;151 }152 return error;153}154 155/*156 * Apply a link count change from the regular filesystem into our shadow link157 * count structure based on a directory update in progress.158 */159STATIC int160xchk_nlinks_live_update(161 struct notifier_block *nb,162 unsigned long action,163 void *data)164{165 struct xfs_dir_update_params *p = data;166 struct xchk_nlink_ctrs *xnc;167 int error;168 169 xnc = container_of(nb, struct xchk_nlink_ctrs, dhook.dirent_hook.nb);170 171 /*172 * Ignore temporary directories being used to stage dir repairs, since173 * we don't bump the link counts of the children.174 */175 if (xrep_is_tempfile(p->dp))176 return NOTIFY_DONE;177 178 trace_xchk_nlinks_live_update(xnc->sc->mp, p->dp, action, p->ip->i_ino,179 p->delta, p->name->name, p->name->len);180 181 /*182 * If we've already scanned @dp, update the number of parents that link183 * to @ip. If @ip is a subdirectory, update the number of child links184 * going out of @dp.185 */186 if (xchk_iscan_want_live_update(&xnc->collect_iscan, p->dp->i_ino)) {187 mutex_lock(&xnc->lock);188 error = xchk_nlinks_update_incore(xnc, p->ip->i_ino, p->delta,189 0, 0);190 if (!error && S_ISDIR(VFS_IC(p->ip)->i_mode))191 error = xchk_nlinks_update_incore(xnc, p->dp->i_ino, 0,192 0, p->delta);193 mutex_unlock(&xnc->lock);194 if (error)195 goto out_abort;196 }197 198 /*199 * If @ip is a subdirectory and we've already scanned it, update the200 * number of backrefs pointing to @dp.201 */202 if (S_ISDIR(VFS_IC(p->ip)->i_mode) &&203 xchk_iscan_want_live_update(&xnc->collect_iscan, p->ip->i_ino)) {204 mutex_lock(&xnc->lock);205 error = xchk_nlinks_update_incore(xnc, p->dp->i_ino, 0,206 p->delta, 0);207 mutex_unlock(&xnc->lock);208 if (error)209 goto out_abort;210 }211 212 return NOTIFY_DONE;213 214out_abort:215 xchk_iscan_abort(&xnc->collect_iscan);216 return NOTIFY_DONE;217}218 219/* Bump the observed link count for the inode referenced by this entry. */220STATIC int221xchk_nlinks_collect_dirent(222 struct xfs_scrub *sc,223 struct xfs_inode *dp,224 xfs_dir2_dataptr_t dapos,225 const struct xfs_name *name,226 xfs_ino_t ino,227 void *priv)228{229 struct xchk_nlink_ctrs *xnc = priv;230 bool dot = false, dotdot = false;231 int error;232 233 /* Does this name make sense? */234 if (name->len == 0 || !xfs_dir2_namecheck(name->name, name->len)) {235 error = -ECANCELED;236 goto out_abort;237 }238 239 if (name->len == 1 && name->name[0] == '.')240 dot = true;241 else if (name->len == 2 && name->name[0] == '.' &&242 name->name[1] == '.')243 dotdot = true;244 245 /* Don't accept a '.' entry that points somewhere else. */246 if (dot && ino != dp->i_ino) {247 error = -ECANCELED;248 goto out_abort;249 }250 251 /* Don't accept an invalid inode number. */252 if (!xfs_verify_dir_ino(sc->mp, ino)) {253 error = -ECANCELED;254 goto out_abort;255 }256 257 /* Update the shadow link counts if we haven't already failed. */258 259 if (xchk_iscan_aborted(&xnc->collect_iscan)) {260 error = -ECANCELED;261 goto out_incomplete;262 }263 264 trace_xchk_nlinks_collect_dirent(sc->mp, dp, ino, name);265 266 mutex_lock(&xnc->lock);267 268 /*269 * If this is a dotdot entry, it is a back link from dp to ino. How270 * we handle this depends on whether or not dp is the root directory.271 *272 * The root directory is its own parent, so we pretend the dotdot entry273 * establishes the "parent" of the root directory. Increment the274 * number of parents of the root directory.275 *276 * Otherwise, increment the number of backrefs pointing back to ino.277 *278 * If the filesystem has parent pointers, we walk the pptrs to279 * determine the backref count.280 */281 if (dotdot) {282 if (dp == sc->mp->m_rootip)283 error = xchk_nlinks_update_incore(xnc, ino, 1, 0, 0);284 else if (!xfs_has_parent(sc->mp))285 error = xchk_nlinks_update_incore(xnc, ino, 0, 1, 0);286 else287 error = 0;288 if (error)289 goto out_unlock;290 }291 292 /*293 * If this dirent is a forward link from dp to ino, increment the294 * number of parents linking into ino.295 */296 if (!dot && !dotdot) {297 error = xchk_nlinks_update_incore(xnc, ino, 1, 0, 0);298 if (error)299 goto out_unlock;300 }301 302 /*303 * If this dirent is a forward link to a subdirectory, increment the304 * number of child links of dp.305 */306 if (!dot && !dotdot && name->type == XFS_DIR3_FT_DIR) {307 error = xchk_nlinks_update_incore(xnc, dp->i_ino, 0, 0, 1);308 if (error)309 goto out_unlock;310 }311 312 mutex_unlock(&xnc->lock);313 return 0;314 315out_unlock:316 mutex_unlock(&xnc->lock);317out_abort:318 xchk_iscan_abort(&xnc->collect_iscan);319out_incomplete:320 xchk_set_incomplete(sc);321 return error;322}323 324/* Bump the backref count for the inode referenced by this parent pointer. */325STATIC int326xchk_nlinks_collect_pptr(327 struct xfs_scrub *sc,328 struct xfs_inode *ip,329 unsigned int attr_flags,330 const unsigned char *name,331 unsigned int namelen,332 const void *value,333 unsigned int valuelen,334 void *priv)335{336 struct xfs_name xname = {337 .name = name,338 .len = namelen,339 };340 struct xchk_nlink_ctrs *xnc = priv;341 const struct xfs_parent_rec *pptr_rec = value;342 xfs_ino_t parent_ino;343 int error;344 345 /* Update the shadow link counts if we haven't already failed. */346 347 if (xchk_iscan_aborted(&xnc->collect_iscan)) {348 error = -ECANCELED;349 goto out_incomplete;350 }351 352 if (!(attr_flags & XFS_ATTR_PARENT))353 return 0;354 355 error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,356 valuelen, &parent_ino, NULL);357 if (error)358 return error;359 360 trace_xchk_nlinks_collect_pptr(sc->mp, ip, &xname, pptr_rec);361 362 mutex_lock(&xnc->lock);363 364 error = xchk_nlinks_update_incore(xnc, parent_ino, 0, 1, 0);365 if (error)366 goto out_unlock;367 368 mutex_unlock(&xnc->lock);369 return 0;370 371out_unlock:372 mutex_unlock(&xnc->lock);373 xchk_iscan_abort(&xnc->collect_iscan);374out_incomplete:375 xchk_set_incomplete(sc);376 return error;377}378 379/* Walk a directory to bump the observed link counts of the children. */380STATIC int381xchk_nlinks_collect_dir(382 struct xchk_nlink_ctrs *xnc,383 struct xfs_inode *dp)384{385 struct xfs_scrub *sc = xnc->sc;386 unsigned int lock_mode;387 int error = 0;388 389 /*390 * Ignore temporary directories being used to stage dir repairs, since391 * we don't bump the link counts of the children.392 */393 if (xrep_is_tempfile(dp))394 return 0;395 396 /* Prevent anyone from changing this directory while we walk it. */397 xfs_ilock(dp, XFS_IOLOCK_SHARED);398 lock_mode = xfs_ilock_data_map_shared(dp);399 400 /*401 * The dotdot entry of an unlinked directory still points to the last402 * parent, but the parent no longer links to this directory. Skip the403 * directory to avoid overcounting.404 */405 if (VFS_I(dp)->i_nlink == 0)406 goto out_unlock;407 408 /*409 * We cannot count file links if the directory looks as though it has410 * been zapped by the inode record repair code.411 */412 if (xchk_dir_looks_zapped(dp)) {413 error = -EBUSY;414 goto out_abort;415 }416 417 error = xchk_dir_walk(sc, dp, xchk_nlinks_collect_dirent, xnc);418 if (error == -ECANCELED) {419 error = 0;420 goto out_unlock;421 }422 if (error)423 goto out_abort;424 425 /* Walk the parent pointers to get real backref counts. */426 if (xfs_has_parent(sc->mp)) {427 /*428 * If the extended attributes look as though they has been429 * zapped by the inode record repair code, we cannot scan for430 * parent pointers.431 */432 if (xchk_pptr_looks_zapped(dp)) {433 error = -EBUSY;434 goto out_unlock;435 }436 437 error = xchk_xattr_walk(sc, dp, xchk_nlinks_collect_pptr, NULL,438 xnc);439 if (error == -ECANCELED) {440 error = 0;441 goto out_unlock;442 }443 if (error)444 goto out_abort;445 }446 447 xchk_iscan_mark_visited(&xnc->collect_iscan, dp);448 goto out_unlock;449 450out_abort:451 xchk_set_incomplete(sc);452 xchk_iscan_abort(&xnc->collect_iscan);453out_unlock:454 xfs_iunlock(dp, lock_mode);455 xfs_iunlock(dp, XFS_IOLOCK_SHARED);456 return error;457}458 459/* If this looks like a valid pointer, count it. */460static inline int461xchk_nlinks_collect_metafile(462 struct xchk_nlink_ctrs *xnc,463 xfs_ino_t ino)464{465 if (!xfs_verify_ino(xnc->sc->mp, ino))466 return 0;467 468 trace_xchk_nlinks_collect_metafile(xnc->sc->mp, ino);469 return xchk_nlinks_update_incore(xnc, ino, 1, 0, 0);470}471 472/* Bump the link counts of metadata files rooted in the superblock. */473STATIC int474xchk_nlinks_collect_metafiles(475 struct xchk_nlink_ctrs *xnc)476{477 struct xfs_mount *mp = xnc->sc->mp;478 int error = -ECANCELED;479 480 481 if (xchk_iscan_aborted(&xnc->collect_iscan))482 goto out_incomplete;483 484 mutex_lock(&xnc->lock);485 error = xchk_nlinks_collect_metafile(xnc, mp->m_sb.sb_rbmino);486 if (error)487 goto out_abort;488 489 error = xchk_nlinks_collect_metafile(xnc, mp->m_sb.sb_rsumino);490 if (error)491 goto out_abort;492 493 error = xchk_nlinks_collect_metafile(xnc, mp->m_sb.sb_uquotino);494 if (error)495 goto out_abort;496 497 error = xchk_nlinks_collect_metafile(xnc, mp->m_sb.sb_gquotino);498 if (error)499 goto out_abort;500 501 error = xchk_nlinks_collect_metafile(xnc, mp->m_sb.sb_pquotino);502 if (error)503 goto out_abort;504 mutex_unlock(&xnc->lock);505 506 return 0;507 508out_abort:509 mutex_unlock(&xnc->lock);510 xchk_iscan_abort(&xnc->collect_iscan);511out_incomplete:512 xchk_set_incomplete(xnc->sc);513 return error;514}515 516/* Advance the collection scan cursor for this non-directory file. */517static inline int518xchk_nlinks_collect_file(519 struct xchk_nlink_ctrs *xnc,520 struct xfs_inode *ip)521{522 xfs_ilock(ip, XFS_IOLOCK_SHARED);523 xchk_iscan_mark_visited(&xnc->collect_iscan, ip);524 xfs_iunlock(ip, XFS_IOLOCK_SHARED);525 return 0;526}527 528/* Walk all directories and count inode links. */529STATIC int530xchk_nlinks_collect(531 struct xchk_nlink_ctrs *xnc)532{533 struct xfs_scrub *sc = xnc->sc;534 struct xfs_inode *ip;535 int error;536 537 /* Count the rt and quota files that are rooted in the superblock. */538 error = xchk_nlinks_collect_metafiles(xnc);539 if (error)540 return error;541 542 /*543 * Set up for a potentially lengthy filesystem scan by reducing our544 * transaction resource usage for the duration. Specifically:545 *546 * Cancel the transaction to release the log grant space while we scan547 * the filesystem.548 *549 * Create a new empty transaction to eliminate the possibility of the550 * inode scan deadlocking on cyclical metadata.551 *552 * We pass the empty transaction to the file scanning function to avoid553 * repeatedly cycling empty transactions. This can be done even though554 * we take the IOLOCK to quiesce the file because empty transactions555 * do not take sb_internal.556 */557 xchk_trans_cancel(sc);558 error = xchk_trans_alloc_empty(sc);559 if (error)560 return error;561 562 while ((error = xchk_iscan_iter(&xnc->collect_iscan, &ip)) == 1) {563 if (S_ISDIR(VFS_I(ip)->i_mode))564 error = xchk_nlinks_collect_dir(xnc, ip);565 else566 error = xchk_nlinks_collect_file(xnc, ip);567 xchk_irele(sc, ip);568 if (error)569 break;570 571 if (xchk_should_terminate(sc, &error))572 break;573 }574 xchk_iscan_iter_finish(&xnc->collect_iscan);575 if (error) {576 xchk_set_incomplete(sc);577 /*578 * If we couldn't grab an inode that was busy with a state579 * change, change the error code so that we exit to userspace580 * as quickly as possible.581 */582 if (error == -EBUSY)583 return -ECANCELED;584 return error;585 }586 587 /*588 * Switch out for a real transaction in preparation for building a new589 * tree.590 */591 xchk_trans_cancel(sc);592 return xchk_setup_fs(sc);593}594 595/*596 * Part 2: Comparing file link counters. Walk each inode and compare the link597 * counts against our shadow information; and then walk each shadow link count598 * structure (that wasn't covered in the first part), comparing it against the599 * file.600 */601 602/* Read the observed link count for comparison with the actual inode. */603STATIC int604xchk_nlinks_comparison_read(605 struct xchk_nlink_ctrs *xnc,606 xfs_ino_t ino,607 struct xchk_nlink *obs)608{609 struct xchk_nlink nl;610 int error;611 612 error = xfarray_load_sparse(xnc->nlinks, ino, &nl);613 if (error)614 return error;615 616 nl.flags |= (XCHK_NLINK_COMPARE_SCANNED | XCHK_NLINK_WRITTEN);617 618 error = xfarray_store(xnc->nlinks, ino, &nl);619 if (error == -EFBIG) {620 /*621 * EFBIG means we tried to store data at too high a byte offset622 * in the sparse array. IOWs, we cannot complete the check and623 * must notify userspace that the check was incomplete. This624 * shouldn't really happen outside of the collection phase.625 */626 xchk_set_incomplete(xnc->sc);627 return -ECANCELED;628 }629 if (error)630 return error;631 632 /* Copy the counters, but do not expose the internal state. */633 obs->parents = nl.parents;634 obs->backrefs = nl.backrefs;635 obs->children = nl.children;636 obs->flags = 0;637 return 0;638}639 640/* Check our link count against an inode. */641STATIC int642xchk_nlinks_compare_inode(643 struct xchk_nlink_ctrs *xnc,644 struct xfs_inode *ip)645{646 struct xchk_nlink obs;647 struct xfs_scrub *sc = xnc->sc;648 uint64_t total_links;649 unsigned int actual_nlink;650 int error;651 652 /*653 * Ignore temporary files being used to stage repairs, since we assume654 * they're correct for non-directories, and the directory repair code655 * doesn't bump the link counts for the children.656 */657 if (xrep_is_tempfile(ip))658 return 0;659 660 xfs_ilock(ip, XFS_ILOCK_SHARED);661 mutex_lock(&xnc->lock);662 663 if (xchk_iscan_aborted(&xnc->collect_iscan)) {664 xchk_set_incomplete(xnc->sc);665 error = -ECANCELED;666 goto out_scanlock;667 }668 669 error = xchk_nlinks_comparison_read(xnc, ip->i_ino, &obs);670 if (error)671 goto out_scanlock;672 673 /*674 * If we don't have ftype to get an accurate count of the subdirectory675 * entries in this directory, take advantage of the fact that on a676 * consistent ftype=0 filesystem, the number of subdirectory677 * backreferences (dotdot entries) pointing towards this directory678 * should be equal to the number of subdirectory entries in the679 * directory.680 */681 if (!xfs_has_ftype(sc->mp) && S_ISDIR(VFS_I(ip)->i_mode))682 obs.children = obs.backrefs;683 684 total_links = xchk_nlink_total(ip, &obs);685 actual_nlink = VFS_I(ip)->i_nlink;686 687 trace_xchk_nlinks_compare_inode(sc->mp, ip, &obs);688 689 /*690 * If we found so many parents that we'd overflow i_nlink, we must flag691 * this as a corruption. The VFS won't let users increase the link692 * count, but it will let them decrease it.693 */694 if (total_links > XFS_NLINK_PINNED) {695 xchk_ino_set_corrupt(sc, ip->i_ino);696 goto out_corrupt;697 } else if (total_links > XFS_MAXLINK) {698 xchk_ino_set_warning(sc, ip->i_ino);699 }700 701 /* Link counts should match. */702 if (total_links != actual_nlink) {703 xchk_ino_set_corrupt(sc, ip->i_ino);704 goto out_corrupt;705 }706 707 if (S_ISDIR(VFS_I(ip)->i_mode) && actual_nlink > 0) {708 /*709 * The collection phase ignores directories with zero link710 * count, so we ignore them here too.711 *712 * The number of subdirectory backreferences (dotdot entries)713 * pointing towards this directory should be equal to the714 * number of subdirectory entries in the directory.715 */716 if (obs.children != obs.backrefs)717 xchk_ino_xref_set_corrupt(sc, ip->i_ino);718 } else {719 /*720 * Non-directories and unlinked directories should not have721 * back references.722 */723 if (obs.backrefs != 0) {724 xchk_ino_set_corrupt(sc, ip->i_ino);725 goto out_corrupt;726 }727 728 /*729 * Non-directories and unlinked directories should not have730 * children.731 */732 if (obs.children != 0) {733 xchk_ino_set_corrupt(sc, ip->i_ino);734 goto out_corrupt;735 }736 }737 738 if (ip == sc->mp->m_rootip) {739 /*740 * For the root of a directory tree, both the '.' and '..'741 * entries should point to the root directory. The dotdot742 * entry is counted as a parent of the root /and/ a backref of743 * the root directory.744 */745 if (obs.parents != 1) {746 xchk_ino_set_corrupt(sc, ip->i_ino);747 goto out_corrupt;748 }749 } else if (actual_nlink > 0) {750 /*751 * Linked files that are not the root directory should have at752 * least one parent.753 */754 if (obs.parents == 0) {755 xchk_ino_set_corrupt(sc, ip->i_ino);756 goto out_corrupt;757 }758 }759 760out_corrupt:761 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)762 error = -ECANCELED;763out_scanlock:764 mutex_unlock(&xnc->lock);765 xfs_iunlock(ip, XFS_ILOCK_SHARED);766 return error;767}768 769/*770 * Check our link count against an inode that wasn't checked previously. This771 * is intended to catch directories with dangling links, though we could be772 * racing with inode allocation in other threads.773 */774STATIC int775xchk_nlinks_compare_inum(776 struct xchk_nlink_ctrs *xnc,777 xfs_ino_t ino)778{779 struct xchk_nlink obs;780 struct xfs_mount *mp = xnc->sc->mp;781 struct xfs_trans *tp = xnc->sc->tp;782 struct xfs_buf *agi_bp;783 struct xfs_inode *ip;784 int error;785 786 /*787 * The first iget failed, so try again with the variant that returns788 * either an incore inode or the AGI buffer. If the function returns789 * EINVAL/ENOENT, it should have passed us the AGI buffer so that we790 * can guarantee that the inode won't be allocated while we check for791 * a zero link count in the observed link count data.792 */793 error = xchk_iget_agi(xnc->sc, ino, &agi_bp, &ip);794 if (!error) {795 /* Actually got an inode, so use the inode compare. */796 error = xchk_nlinks_compare_inode(xnc, ip);797 xchk_irele(xnc->sc, ip);798 return error;799 }800 if (error == -ENOENT || error == -EINVAL) {801 /* No inode was found. Check for zero link count below. */802 error = 0;803 }804 if (error)805 goto out_agi;806 807 /* Ensure that we have protected against inode allocation/freeing. */808 if (agi_bp == NULL) {809 ASSERT(agi_bp != NULL);810 xchk_set_incomplete(xnc->sc);811 return -ECANCELED;812 }813 814 if (xchk_iscan_aborted(&xnc->collect_iscan)) {815 xchk_set_incomplete(xnc->sc);816 error = -ECANCELED;817 goto out_agi;818 }819 820 mutex_lock(&xnc->lock);821 error = xchk_nlinks_comparison_read(xnc, ino, &obs);822 if (error)823 goto out_scanlock;824 825 trace_xchk_nlinks_check_zero(mp, ino, &obs);826 827 /*828 * If we can't grab the inode, the link count had better be zero. We829 * still hold the AGI to prevent inode allocation/freeing.830 */831 if (xchk_nlink_total(NULL, &obs) != 0) {832 xchk_ino_set_corrupt(xnc->sc, ino);833 error = -ECANCELED;834 }835 836out_scanlock:837 mutex_unlock(&xnc->lock);838out_agi:839 if (agi_bp)840 xfs_trans_brelse(tp, agi_bp);841 return error;842}843 844/*845 * Try to visit every inode in the filesystem to compare the link count. Move846 * on if we can't grab an inode, since we'll revisit unchecked nlink records in847 * the second part.848 */849static int850xchk_nlinks_compare_iter(851 struct xchk_nlink_ctrs *xnc,852 struct xfs_inode **ipp)853{854 int error;855 856 do {857 error = xchk_iscan_iter(&xnc->compare_iscan, ipp);858 } while (error == -EBUSY);859 860 return error;861}862 863/* Compare the link counts we observed against the live information. */864STATIC int865xchk_nlinks_compare(866 struct xchk_nlink_ctrs *xnc)867{868 struct xchk_nlink nl;869 struct xfs_scrub *sc = xnc->sc;870 struct xfs_inode *ip;871 xfarray_idx_t cur = XFARRAY_CURSOR_INIT;872 int error;873 874 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)875 return 0;876 877 /*878 * Create a new empty transaction so that we can advance the iscan879 * cursor without deadlocking if the inobt has a cycle and push on the880 * inactivation workqueue.881 */882 xchk_trans_cancel(sc);883 error = xchk_trans_alloc_empty(sc);884 if (error)885 return error;886 887 /*888 * Use the inobt to walk all allocated inodes to compare the link889 * counts. Inodes skipped by _compare_iter will be tried again in the890 * next phase of the scan.891 */892 xchk_iscan_start(sc, 0, 0, &xnc->compare_iscan);893 while ((error = xchk_nlinks_compare_iter(xnc, &ip)) == 1) {894 error = xchk_nlinks_compare_inode(xnc, ip);895 xchk_iscan_mark_visited(&xnc->compare_iscan, ip);896 xchk_irele(sc, ip);897 if (error)898 break;899 900 if (xchk_should_terminate(sc, &error))901 break;902 }903 xchk_iscan_iter_finish(&xnc->compare_iscan);904 xchk_iscan_teardown(&xnc->compare_iscan);905 if (error)906 return error;907 908 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)909 return 0;910 911 /*912 * Walk all the non-null nlink observations that weren't checked in the913 * previous step.914 */915 mutex_lock(&xnc->lock);916 while ((error = xfarray_iter(xnc->nlinks, &cur, &nl)) == 1) {917 xfs_ino_t ino = cur - 1;918 919 if (nl.flags & XCHK_NLINK_COMPARE_SCANNED)920 continue;921 922 mutex_unlock(&xnc->lock);923 924 error = xchk_nlinks_compare_inum(xnc, ino);925 if (error)926 return error;927 928 if (xchk_should_terminate(xnc->sc, &error))929 return error;930 931 mutex_lock(&xnc->lock);932 }933 mutex_unlock(&xnc->lock);934 935 return error;936}937 938/* Tear down everything associated with a nlinks check. */939static void940xchk_nlinks_teardown_scan(941 void *priv)942{943 struct xchk_nlink_ctrs *xnc = priv;944 945 /* Discourage any hook functions that might be running. */946 xchk_iscan_abort(&xnc->collect_iscan);947 948 xfs_dir_hook_del(xnc->sc->mp, &xnc->dhook);949 950 xfarray_destroy(xnc->nlinks);951 xnc->nlinks = NULL;952 953 xchk_iscan_teardown(&xnc->collect_iscan);954 mutex_destroy(&xnc->lock);955 xnc->sc = NULL;956}957 958/*959 * Scan all inodes in the entire filesystem to generate link count data. If960 * the scan is successful, the counts will be left alive for a repair. If any961 * error occurs, we'll tear everything down.962 */963STATIC int964xchk_nlinks_setup_scan(965 struct xfs_scrub *sc,966 struct xchk_nlink_ctrs *xnc)967{968 struct xfs_mount *mp = sc->mp;969 char *descr;970 unsigned long long max_inos;971 xfs_agnumber_t last_agno = mp->m_sb.sb_agcount - 1;972 xfs_agino_t first_agino, last_agino;973 int error;974 975 mutex_init(&xnc->lock);976 977 /* Retry iget every tenth of a second for up to 30 seconds. */978 xchk_iscan_start(sc, 30000, 100, &xnc->collect_iscan);979 980 /*981 * Set up enough space to store an nlink record for the highest982 * possible inode number in this system.983 */984 xfs_agino_range(mp, last_agno, &first_agino, &last_agino);985 max_inos = XFS_AGINO_TO_INO(mp, last_agno, last_agino) + 1;986 descr = xchk_xfile_descr(sc, "file link counts");987 error = xfarray_create(descr, min(XFS_MAXINUMBER + 1, max_inos),988 sizeof(struct xchk_nlink), &xnc->nlinks);989 kfree(descr);990 if (error)991 goto out_teardown;992 993 /*994 * Hook into the directory entry code so that we can capture updates to995 * file link counts. The hook only triggers for inodes that were996 * already scanned, and the scanner thread takes each inode's ILOCK,997 * which means that any in-progress inode updates will finish before we998 * can scan the inode.999 */1000 ASSERT(sc->flags & XCHK_FSGATES_DIRENTS);1001 xfs_dir_hook_setup(&xnc->dhook, xchk_nlinks_live_update);1002 error = xfs_dir_hook_add(mp, &xnc->dhook);1003 if (error)1004 goto out_teardown;1005 1006 /* Use deferred cleanup to pass the inode link count data to repair. */1007 sc->buf_cleanup = xchk_nlinks_teardown_scan;1008 return 0;1009 1010out_teardown:1011 xchk_nlinks_teardown_scan(xnc);1012 return error;1013}1014 1015/* Scrub the link count of all inodes on the filesystem. */1016int1017xchk_nlinks(1018 struct xfs_scrub *sc)1019{1020 struct xchk_nlink_ctrs *xnc = sc->buf;1021 int error = 0;1022 1023 /* Set ourselves up to check link counts on the live filesystem. */1024 error = xchk_nlinks_setup_scan(sc, xnc);1025 if (error)1026 return error;1027 1028 /* Walk all inodes, picking up link count information. */1029 error = xchk_nlinks_collect(xnc);1030 if (!xchk_xref_process_error(sc, 0, 0, &error))1031 return error;1032 1033 /* Fail fast if we're not playing with a full dataset. */1034 if (xchk_iscan_aborted(&xnc->collect_iscan))1035 xchk_set_incomplete(sc);1036 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)1037 return 0;1038 1039 /* Compare link counts. */1040 error = xchk_nlinks_compare(xnc);1041 if (!xchk_xref_process_error(sc, 0, 0, &error))1042 return error;1043 1044 /* Check one last time for an incomplete dataset. */1045 if (xchk_iscan_aborted(&xnc->collect_iscan))1046 xchk_set_incomplete(sc);1047 1048 return 0;1049}1050