diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:25:04 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-09-17 18:55:28 -0700 |
commit | 8894004f29e6d5bf300401714486bff40f71ad89 (patch) | |
tree | d260b51ad498e902212867936f8a084960f6d89a | |
parent | 2c94b6e9e6cb98a5a8b59fe66636b39d74d7f42a (diff) |
xfs: experiment with dontcache when scanning inodesvectorized-scrub_2021-09-17
Add some experimental flags to drop inodes from the cache after a scan.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r-- | fs/xfs/libxfs/xfs_fs.h | 17 | ||||
-rw-r--r-- | fs/xfs/scrub/common.c | 25 | ||||
-rw-r--r-- | fs/xfs/scrub/common.h | 3 | ||||
-rw-r--r-- | fs/xfs/scrub/dir.c | 2 | ||||
-rw-r--r-- | fs/xfs/scrub/dir_repair.c | 4 | ||||
-rw-r--r-- | fs/xfs/scrub/inode_repair.c | 3 | ||||
-rw-r--r-- | fs/xfs/scrub/parent.c | 6 | ||||
-rw-r--r-- | fs/xfs/scrub/parent_repair.c | 4 | ||||
-rw-r--r-- | fs/xfs/scrub/quotacheck.c | 4 | ||||
-rw-r--r-- | fs/xfs/scrub/rmap_repair.c | 4 | ||||
-rw-r--r-- | fs/xfs/scrub/rtrmap_repair.c | 4 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.c | 11 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.c | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.h | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_iwalk.h | 6 |
16 files changed, 74 insertions, 33 deletions
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index d16276aa0bd7..fe258a48b4b1 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -499,9 +499,13 @@ struct xfs_bulk_ireq { */ #define XFS_BULK_IREQ_METADIR (1 << 2) +/* Don't mark inodes DONTCACHE */ +#define XFS_BULK_IREQ_RETAIN_INODES (1 << 3) + #define XFS_BULK_IREQ_FLAGS_ALL (XFS_BULK_IREQ_AGNO | \ XFS_BULK_IREQ_SPECIAL | \ - XFS_BULK_IREQ_METADIR) + XFS_BULK_IREQ_METADIR | \ + XFS_BULK_IREQ_RETAIN_INODES) /* Operate on the root directory inode. */ #define XFS_BULK_IREQ_SPECIAL_ROOT (1) @@ -782,8 +786,12 @@ struct xfs_scrub_metadata { /* i: Allow scrub to freeze the filesystem to perform global scans. */ #define XFS_SCRUB_IFLAG_FREEZE_OK (1 << 8) +/* i: Don't mark inodes DONTCACHE at the end. */ +#define XFS_SCRUB_IFLAG_RETAIN_INODES (1 << 9) + #define XFS_SCRUB_FLAGS_IN (XFS_SCRUB_IFLAG_REPAIR | \ - XFS_SCRUB_IFLAG_FREEZE_OK) + XFS_SCRUB_IFLAG_FREEZE_OK | \ + XFS_SCRUB_IFLAG_RETAIN_INODES) #define XFS_SCRUB_FLAGS_OUT (XFS_SCRUB_OFLAG_CORRUPT | \ XFS_SCRUB_OFLAG_PREEN | \ XFS_SCRUB_OFLAG_XFAIL | \ @@ -812,7 +820,10 @@ struct xfs_scrub_vec_head { struct xfs_scrub_vec svh_vecs[0]; }; -#define XFS_SCRUB_VEC_FLAGS_ALL (0) +/* i: Don't mark inodes DONTCACHE at the end. */ +#define XFS_SCRUB_VEC_IFLAG_RETAIN_INODES (1 << 0) + +#define XFS_SCRUB_VEC_FLAGS_ALL (XFS_SCRUB_VEC_IFLAG_RETAIN_INODES) static inline size_t sizeof_xfs_scrub_vec(unsigned int nr) { diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index 96864ec1d21f..443fe6b88dd2 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -836,8 +836,7 @@ xchk_get_inode( /* Look up the inode, see if the generation number matches. */ if (xfs_internal_inum(mp, sc->sm->sm_ino)) return -ENOENT; - error = xfs_iget(mp, NULL, sc->sm->sm_ino, - XFS_IGET_UNTRUSTED | XFS_IGET_DONTCACHE, 0, &ip); + error = xfs_iget(mp, NULL, sc->sm->sm_ino, XFS_IGET_UNTRUSTED, 0, &ip); switch (error) { case -ENOENT: /* Inode doesn't exist, just bail out. */ @@ -859,7 +858,7 @@ xchk_get_inode( * that it no longer exists. */ error = xfs_imap(sc->mp, sc->tp, sc->sm->sm_ino, &imap, - XFS_IGET_UNTRUSTED | XFS_IGET_DONTCACHE); + XFS_IGET_UNTRUSTED); if (error) return -ENOENT; error = -EFSCORRUPTED; @@ -884,7 +883,7 @@ xchk_get_inode( */ if (VFS_I(ip)->i_generation != sc->sm->sm_gen || (xfs_is_metadata_inode(ip) && !S_ISDIR(VFS_I(ip)->i_mode))) { - xfs_irele(ip); + xchk_irele(sc, ip); return -ENOENT; } @@ -892,6 +891,24 @@ xchk_get_inode( return 0; } +void +__xchk_irele( + struct xfs_inode *ip, + bool set_dontcache) +{ + if (set_dontcache && atomic_read(&VFS_I(ip)->i_count) == 1) + d_mark_dontcache(VFS_I(ip)); + xfs_irele(ip); +} + +void +xchk_irele( + struct xfs_scrub *sc, + struct xfs_inode *ip) +{ + __xchk_irele(ip, !(sc->sm->sm_flags & XFS_SCRUB_IFLAG_RETAIN_INODES)); +} + /* Set us up to scrub a file's contents. */ int xchk_setup_inode_contents( diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index 6fa1fb21150d..d8e3ee1d24c4 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -168,6 +168,9 @@ int xchk_install_inode(struct xfs_scrub *sc, struct xfs_inode *ip); void xchk_buffer_recheck(struct xfs_scrub *sc, struct xfs_buf *bp); void xchk_whine(const struct xfs_mount *mp, const char *fmt, ...); +void __xchk_irele(struct xfs_inode *ip, bool set_dontcache); +void xchk_irele(struct xfs_scrub *sc, struct xfs_inode *ip); + /* * Don't bother cross-referencing if we already found corruption or cross * referencing discrepancies. diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c index acca10a72fc1..73217aa58951 100644 --- a/fs/xfs/scrub/dir.c +++ b/fs/xfs/scrub/dir.c @@ -143,7 +143,7 @@ xchk_dir_check_ftype( if (xfs_is_metadata_inode(ip) ^ xfs_is_metadata_inode(sdc->sc->ip)) xchk_fblock_set_corrupt(sdc->sc, XFS_DATA_FORK, 0); - xfs_irele(ip); + xchk_irele(sdc->sc, ip); out: return error; } diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c index 91d812dbdb1d..444a2545875b 100644 --- a/fs/xfs/scrub/dir_repair.c +++ b/fs/xfs/scrub/dir_repair.c @@ -182,12 +182,12 @@ xrep_dir_salvage_entry( /* Don't mix metadata and regular directory trees. */ if (xfs_is_metadata_inode(ip) ^ xfs_is_metadata_inode(rd->sc->ip)) { - xfs_irele(ip); + xchk_irele(rd->sc, ip); return 0; } key.ftype = xfs_mode_to_ftype(VFS_I(ip)->i_mode); - xfs_irele(ip); + xchk_irele(rd->sc, ip); /* Remember this for later. */ error = xblob_put(rd->dir_names, &key.name_cookie, name, key.namelen); diff --git a/fs/xfs/scrub/inode_repair.c b/fs/xfs/scrub/inode_repair.c index 12f163e24c41..144481f94ce8 100644 --- a/fs/xfs/scrub/inode_repair.c +++ b/fs/xfs/scrub/inode_repair.c @@ -1183,8 +1183,7 @@ xrep_dinode_core( sc->tp = NULL; /* ...and reload it? */ - error = xfs_iget(sc->mp, sc->tp, ino, - XFS_IGET_UNTRUSTED | XFS_IGET_DONTCACHE, 0, &sc->ip); + error = xfs_iget(sc->mp, sc->tp, ino, XFS_IGET_UNTRUSTED, 0, &sc->ip); if (error) return error; sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c index 519acb248d97..e4444f580244 100644 --- a/fs/xfs/scrub/parent.c +++ b/fs/xfs/scrub/parent.c @@ -285,11 +285,11 @@ xchk_parent_validate( /* Drat, parent changed. Try again! */ if (dnum != dp->i_ino) { - xfs_irele(dp); + xchk_irele(sc, dp); *try_again = true; return 0; } - xfs_irele(dp); + xchk_irele(sc, dp); /* * '..' didn't change, so check that there was only one entry @@ -302,7 +302,7 @@ xchk_parent_validate( out_unlock: xfs_iunlock(dp, XFS_IOLOCK_SHARED); out_rele: - xfs_irele(dp); + xchk_irele(sc, dp); out: return error; } diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c index 4570e7c94c32..b740c043faf5 100644 --- a/fs/xfs/scrub/parent_repair.c +++ b/fs/xfs/scrub/parent_repair.c @@ -188,7 +188,7 @@ findparent_walk_directory( out_unlock: xfs_iunlock(dp, XFS_IOLOCK_SHARED); out_rele: - xfs_irele(dp); + xchk_irele(fpi->sc, dp); return error; } @@ -275,7 +275,7 @@ findparent_from_dcache( ret = XFS_I(pip)->i_ino; } - xfs_irele(XFS_I(pip)); + xchk_irele(sc, XFS_I(pip)); out_dput: dput(dentry); diff --git a/fs/xfs/scrub/quotacheck.c b/fs/xfs/scrub/quotacheck.c index 89f4f833c3ad..07f50e48b986 100644 --- a/fs/xfs/scrub/quotacheck.c +++ b/fs/xfs/scrub/quotacheck.c @@ -437,7 +437,7 @@ xqcheck_collect_counts( struct xfs_scrub *sc = xqc->sc; struct xchk_iscan *iscan = &xqc->iscan; struct xfs_inode *ip; - int flags = XFS_IGET_UNTRUSTED | XFS_IGET_DONTCACHE; + int flags = XFS_IGET_UNTRUSTED; unsigned int retries = 20; int error; @@ -451,7 +451,7 @@ xqcheck_collect_counts( switch (error) { case 0: error = xqcheck_inode(xqc, ip); - xfs_irele(ip); + xchk_irele(sc, ip); if (error) return error; retries = 20; diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c index dbe20807e60d..2797d31a7642 100644 --- a/fs/xfs/scrub/rmap_repair.c +++ b/fs/xfs/scrub/rmap_repair.c @@ -616,7 +616,7 @@ xrep_rmap_scan_inode( int error; /* Grab inode and lock it so we can scan it. */ - error = xfs_iget(mp, rr->sc->tp, ino, XFS_IGET_DONTCACHE, 0, &ip); + error = xfs_iget(mp, rr->sc->tp, ino, 0, 0, &ip); if (error == -ENOENT) xfs_emerg(mp, "%s: iget of ino 0x%llx returned ENOENT?!", __func__, ino); @@ -639,7 +639,7 @@ xrep_rmap_scan_inode( out_unlock: xfs_iunlock(ip, lock_mode); - xfs_irele(ip); + xchk_irele(rr->sc, ip); return error; } diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c index aaa5964a7cda..1ba8d979d82c 100644 --- a/fs/xfs/scrub/rtrmap_repair.c +++ b/fs/xfs/scrub/rtrmap_repair.c @@ -351,7 +351,7 @@ xrep_rtrmap_scan_inode( return 0; /* Grab inode and lock it so we can scan it. */ - error = xfs_iget(mp, rr->sc->tp, ino, XFS_IGET_DONTCACHE, 0, &ip); + error = xfs_iget(mp, rr->sc->tp, ino, 0, 0, &ip); if (error == -ENOENT) xfs_emerg(mp, "%s: iget of ino 0x%llx returned ENOENT?!", __func__, ino); @@ -381,7 +381,7 @@ xrep_rtrmap_scan_inode( out_unlock: xfs_iunlock(ip, XFS_ILOCK_SHARED); out_rele: - xfs_irele(ip); + xchk_irele(rr->sc, ip); return error; } diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 668f94aab100..27a0b3502200 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -170,7 +170,7 @@ xchk_teardown( if (sc->ip) { if (sc->ilock_flags) xfs_iunlock(sc->ip, sc->ilock_flags); - xfs_irele(sc->ip); + xchk_irele(sc, sc->ip); sc->ip = NULL; } if (sc->flags & XREP_ATOMIC_EXCHANGE) { @@ -743,7 +743,8 @@ xfs_scrubv_metadata( * consider setting dontcache at the end. */ if (v->sv_type < XFS_SCRUB_TYPE_NR && - meta_scrub_ops[v->sv_type].type == ST_INODE) + meta_scrub_ops[v->sv_type].type == ST_INODE && + !(vhead->svh_flags & XFS_SCRUB_VEC_IFLAG_RETAIN_INODES)) set_dontcache = true; trace_xchk_scrubv_item(mp, vhead, v); @@ -760,7 +761,7 @@ xfs_scrubv_metadata( if (ip && (VFS_I(ip)->i_generation != vhead->svh_gen || (xfs_is_metadata_inode(ip) && !S_ISDIR(VFS_I(ip)->i_mode)))) { - xfs_irele(ip); + __xchk_irele(ip, set_dontcache); ip = NULL; } } @@ -815,8 +816,6 @@ xfs_scrubv_metadata( * If we're holding the only reference to this inode and the scan was * clean, mark it dontcache so that we don't pollute the cache. */ - if (set_dontcache && atomic_read(&VFS_I(ip)->i_count) == 1) - d_mark_dontcache(VFS_I(ip)); - xfs_irele(ip); + __xchk_irele(ip, set_dontcache); return error; } diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 97ccc69a3bf4..fb94301dbc85 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -897,6 +897,9 @@ xfs_bulk_ireq_setup( if (hdr->flags & XFS_BULK_IREQ_METADIR) breq->flags |= XFS_IWALK_METADIR; + if (hdr->flags & XFS_BULK_IREQ_RETAIN_INODES) + breq->flags |= XFS_IWALK_RETAIN_INODES; + return 0; } diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index f92057ad686b..528bf3e59995 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -74,11 +74,13 @@ xfs_bulkstat_one_int( struct xfs_inode *ip; /* incore inode pointer */ struct inode *inode; struct xfs_bulkstat *buf = bc->buf; + int flags = XFS_IGET_UNTRUSTED; int error = -EINVAL; - error = xfs_iget(mp, tp, ino, - (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED), - XFS_ILOCK_SHARED, &ip); + if (!(bc->breq->flags & XFS_IBULK_RETAIN_INODES)) + flags |= XFS_IGET_DONTCACHE; + + error = xfs_iget(mp, tp, ino, flags, XFS_ILOCK_SHARED, &ip); if (error == -ENOENT || error == -EINVAL) goto out_advance; if (error) diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index f5a13f69883a..7fc2e40d30bd 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h @@ -22,6 +22,9 @@ struct xfs_ibulk { /* Signal that we can return metadata directories. */ #define XFS_IBULK_METADIR (XFS_IWALK_METADIR) +/* Don't drop inodes. */ +#define XFS_IBULK_RETAIN_INODES (XFS_IWALK_RETAIN_INODES) + /* * Advance the user buffer pointer by one record of the given size. If the * buffer is now full, return the appropriate error code. diff --git a/fs/xfs/xfs_iwalk.h b/fs/xfs/xfs_iwalk.h index d7a082e45cbf..bdec747ff834 100644 --- a/fs/xfs/xfs_iwalk.h +++ b/fs/xfs/xfs_iwalk.h @@ -31,8 +31,12 @@ int xfs_iwalk_threaded(struct xfs_mount *mp, xfs_ino_t startino, /* Signal that we can return metadata directories. */ #define XFS_IWALK_METADIR (0x2) +/* Don't drop inodes. */ +#define XFS_IWALK_RETAIN_INODES (0x4) + #define XFS_IWALK_FLAGS_ALL (XFS_IWALK_SAME_AG | \ - XFS_IWALK_METADIR) + XFS_IWALK_METADIR | \ + XFS_IWALK_RETAIN_INODES) /* Walk all inode btree records in the filesystem starting from @startino. */ typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp, |