Lines Matching +full:tp +full:- +full:link
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2021-2024 Oracle. All Rights Reserved.
35 * Live Inode Link Count Repair
38 * Use the live inode link count information that we collected to replace the
39 * nlink values of the incore inodes. A scrub->repair cycle should have left
44 /* Set up to repair inode link counts. */
53 * Inodes that aren't the root directory or the orphanage, have a nonzero link
63 struct xfs_mount *mp = ip->i_mount; in xrep_nlinks_is_orphaned()
65 if (obs->parents != 0) in xrep_nlinks_is_orphaned()
67 if (ip == mp->m_rootip || ip == sc->orphanage) in xrep_nlinks_is_orphaned()
80 pag = xfs_perag_get(sc->mp, XFS_INO_TO_AGNO(sc->mp, sc->ip->i_ino)); in xrep_nlinks_iunlink_remove()
81 error = xfs_iunlink_remove(sc->tp, pag, sc->ip); in xrep_nlinks_iunlink_remove()
87 * Correct the link count of the given inode. Because we have to grab locks
88 * and resources in a certain order, it's possible that this will be a no-op.
95 struct xfs_scrub *sc = xnc->sc; in xrep_nlinks_repair_inode()
96 struct xfs_mount *mp = sc->mp; in xrep_nlinks_repair_inode()
97 struct xfs_inode *ip = sc->ip; in xrep_nlinks_repair_inode()
106 * they're correct for non-directories, and the directory repair code in xrep_nlinks_repair_inode()
107 * doesn't bump the link counts for the children. in xrep_nlinks_repair_inode()
114 * prepare for a link count repair that could involve @ip being adopted in xrep_nlinks_repair_inode()
122 error = xrep_adoption_trans_alloc(sc, &xnc->adoption); in xrep_nlinks_repair_inode()
134 * need for a simple link count update, since that's much more common. in xrep_nlinks_repair_inode()
139 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_link, 0, 0, 0, in xrep_nlinks_repair_inode()
140 &sc->tp); in xrep_nlinks_repair_inode()
147 xfs_trans_ijoin(sc->tp, ip, 0); in xrep_nlinks_repair_inode()
150 mutex_lock(&xnc->lock); in xrep_nlinks_repair_inode()
152 if (xchk_iscan_aborted(&xnc->collect_iscan)) { in xrep_nlinks_repair_inode()
153 error = -ECANCELED; in xrep_nlinks_repair_inode()
157 error = xfarray_load_sparse(xnc->nlinks, ip->i_ino, &obs); in xrep_nlinks_repair_inode()
163 * We still hold @ip's ILOCK, so its link count cannot change. in xrep_nlinks_repair_inode()
165 mutex_unlock(&xnc->lock); in xrep_nlinks_repair_inode()
168 actual_nlink = VFS_I(ip)->i_nlink; in xrep_nlinks_repair_inode()
171 * Non-directories cannot have directories pointing up to them. in xrep_nlinks_repair_inode()
177 * store. This is a never-ending and stupid battle; both tools missed in xrep_nlinks_repair_inode()
180 if (!S_ISDIR(VFS_I(ip)->i_mode) && obs.children != 0) { in xrep_nlinks_repair_inode()
188 * up the incore link counts if we are. in xrep_nlinks_repair_inode()
193 error = xrep_adoption_compute_name(&xnc->adoption, &xnc->xname); in xrep_nlinks_repair_inode()
202 error = xrep_adoption_move(&xnc->adoption); in xrep_nlinks_repair_inode()
207 * Re-read the link counts since the reparenting will have in xrep_nlinks_repair_inode()
210 mutex_lock(&xnc->lock); in xrep_nlinks_repair_inode()
211 error = xfarray_load_sparse(xnc->nlinks, ip->i_ino, &obs); in xrep_nlinks_repair_inode()
212 mutex_unlock(&xnc->lock); in xrep_nlinks_repair_inode()
217 actual_nlink = VFS_I(ip)->i_nlink; in xrep_nlinks_repair_inode()
237 error = xfs_iunlink(sc->tp, ip); in xrep_nlinks_repair_inode()
243 /* Commit the new link count if it changed. */ in xrep_nlinks_repair_inode()
257 xfs_trans_log_inode(sc->tp, ip, XFS_ILOG_CORE); in xrep_nlinks_repair_inode()
263 mutex_unlock(&xnc->lock); in xrep_nlinks_repair_inode()
288 error = xchk_iscan_iter(&xnc->compare_iscan, ipp); in xrep_nlinks_iter()
289 } while (error == -EBUSY); in xrep_nlinks_iter()
294 /* Commit the new inode link counters. */
299 struct xchk_nlink_ctrs *xnc = sc->buf; in xrep_nlinks()
304 * subdirectory links. Child subdirectories with a back link (dotdot in xrep_nlinks()
305 * entry) but no forward link are moved to the orphanage, so we cannot in xrep_nlinks()
306 * repair the link count of the parent directory based on the back link in xrep_nlinks()
310 if (!xfs_has_ftype(sc->mp)) in xrep_nlinks()
311 return -EOPNOTSUPP; in xrep_nlinks()
315 * link counts. Retry iget every tenth of a second for up to 30 in xrep_nlinks()
316 * seconds -- even if repair misses a few inodes, we still try to fix in xrep_nlinks()
319 xchk_iscan_start(sc, 30000, 100, &xnc->compare_iscan); in xrep_nlinks()
320 ASSERT(sc->ip == NULL); in xrep_nlinks()
322 while ((error = xrep_nlinks_iter(xnc, &sc->ip)) == 1) { in xrep_nlinks()
330 xchk_iscan_mark_visited(&xnc->compare_iscan, sc->ip); in xrep_nlinks()
331 xchk_irele(sc, sc->ip); in xrep_nlinks()
332 sc->ip = NULL; in xrep_nlinks()
349 xchk_iscan_iter_finish(&xnc->compare_iscan); in xrep_nlinks()
350 xchk_iscan_teardown(&xnc->compare_iscan); in xrep_nlinks()