ufs: use lazy list instead of active list for syncer

Quota code is temporarily regressed to do a full vnode scan.

Reviewed by:	jeff
Tested by:	pho (in a larger patch, previous version)
Differential Revision:	https://reviews.freebsd.org/D22996
This commit is contained in:
Mateusz Guzik 2020-01-13 02:35:15 +00:00
parent 57083d2576
commit 80663cadb8
4 changed files with 78 additions and 12 deletions

View File

@ -1446,6 +1446,23 @@ sync_doupdate(struct inode *ip)
IN_UPDATE)) != 0);
}
static int
ffs_sync_lazy_filter(struct vnode *vp, void *arg __unused)
{
struct inode *ip;
/*
* Flags are safe to access because ->v_data invalidation
* is held off by listmtx.
*/
if (vp->v_type == VNON)
return (false);
ip = VTOI(vp);
if (!sync_doupdate(ip) && (vp->v_iflag & VI_OWEINACT) == 0)
return (false);
return (true);
}
/*
* For a lazy sync, we only care about access times, quotas and the
* superblock. Other filesystem changes are already converted to
@ -1465,7 +1482,7 @@ ffs_sync_lazy(mp)
td = curthread;
if ((mp->mnt_flag & MNT_NOATIME) != 0)
goto qupdate;
MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) {
MNT_VNODE_FOREACH_LAZY(vp, mp, mvp, ffs_sync_lazy_filter, NULL) {
if (vp->v_type == VNON) {
VI_UNLOCK(vp);
continue;

View File

@ -113,6 +113,9 @@ static vop_fsync_t ffs_fsync;
static vop_getpages_t ffs_getpages;
static vop_getpages_async_t ffs_getpages_async;
static vop_lock1_t ffs_lock;
#ifdef INVARIANTS
static vop_unlock_t ffs_unlock_debug;
#endif
static vop_read_t ffs_read;
static vop_write_t ffs_write;
static int ffs_extread(struct vnode *vp, struct uio *uio, int ioflag);
@ -135,6 +138,9 @@ struct vop_vector ffs_vnodeops1 = {
.vop_getpages = ffs_getpages,
.vop_getpages_async = ffs_getpages_async,
.vop_lock1 = ffs_lock,
#ifdef INVARIANTS
.vop_unlock = ffs_unlock_debug,
#endif
.vop_read = ffs_read,
.vop_reallocblks = ffs_reallocblks,
.vop_write = ffs_write,
@ -147,6 +153,9 @@ struct vop_vector ffs_fifoops1 = {
.vop_fsync = ffs_fsync,
.vop_fdatasync = ffs_fdatasync,
.vop_lock1 = ffs_lock,
#ifdef INVARIANTS
.vop_unlock = ffs_unlock_debug,
#endif
.vop_vptofh = ffs_vptofh,
};
VFS_VOP_VECTOR_REGISTER(ffs_fifoops1);
@ -159,6 +168,9 @@ struct vop_vector ffs_vnodeops2 = {
.vop_getpages = ffs_getpages,
.vop_getpages_async = ffs_getpages_async,
.vop_lock1 = ffs_lock,
#ifdef INVARIANTS
.vop_unlock = ffs_unlock_debug,
#endif
.vop_read = ffs_read,
.vop_reallocblks = ffs_reallocblks,
.vop_write = ffs_write,
@ -177,6 +189,9 @@ struct vop_vector ffs_fifoops2 = {
.vop_fsync = ffs_fsync,
.vop_fdatasync = ffs_fdatasync,
.vop_lock1 = ffs_lock,
#ifdef INVARIANTS
.vop_unlock = ffs_unlock_debug,
#endif
.vop_reallocblks = ffs_reallocblks,
.vop_strategy = ffsext_strategy,
.vop_closeextattr = ffs_closeextattr,
@ -463,6 +478,26 @@ ffs_lock(ap)
#endif
}
#ifdef INVARIANTS
static int
ffs_unlock_debug(struct vop_unlock_args *ap)
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
if (ip->i_flag & UFS_INODE_FLAG_LAZY_MASK) {
if ((vp->v_mflag & VMP_LAZYLIST) == 0) {
VI_LOCK(vp);
VNASSERT((vp->v_mflag & VMP_LAZYLIST), vp,
("%s: modified vnode (%x) not on lazy list",
__func__, ip->i_flag));
VI_UNLOCK(vp);
}
}
return (VOP_UNLOCK_APV(&ufs_vnodeops, ap));
}
#endif
static int
ffs_read_hole(struct uio *uio, long xfersize, long *size)
{
@ -665,12 +700,8 @@ ffs_read(ap)
vfs_bio_brelse(bp, ioflag);
if ((error == 0 || uio->uio_resid != orig_resid) &&
(vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0 &&
(ip->i_flag & IN_ACCESS) == 0) {
VI_LOCK(vp);
UFS_INODE_SET_FLAG(ip, IN_ACCESS);
VI_UNLOCK(vp);
}
(vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0)
UFS_INODE_SET_FLAG_SHARED(ip, IN_ACCESS);
return (error);
}

View File

@ -138,11 +138,32 @@ struct inode {
"\14b12\13is_ufs2\12truncated\11ea_lockwait\10ea_locked" \
"\7lazyaccess\6lazymod\5needsync\4modified\3update\2change\1access"
#define UFS_INODE_FLAG_LAZY_MASK \
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE | IN_LAZYMOD | IN_LAZYACCESS)
#define UFS_INODE_SET_FLAG(ip, flags) do { \
struct inode *_ip = (ip); \
struct vnode *_vp = ITOV(_ip); \
int _flags = (flags); \
\
_ip->i_flag |= _flags; \
if (_flags & UFS_INODE_FLAG_LAZY_MASK) \
vlazy(_vp); \
} while (0)
#define UFS_INODE_SET_FLAG_SHARED(ip, flags) do { \
struct inode *_ip = (ip); \
struct vnode *_vp = ITOV(_ip); \
int _flags = (flags); \
\
ASSERT_VI_UNLOCKED(_vp, __func__); \
if ((_ip->i_flag & (_flags)) != _flags) { \
VI_LOCK(_vp); \
_ip->i_flag |= _flags; \
if (_flags & UFS_INODE_FLAG_LAZY_MASK) \
vlazy(_vp); \
VI_UNLOCK(_vp); \
} \
} while (0)
#define i_dirhash i_un.dirhash

View File

@ -686,12 +686,9 @@ ufs_markatime(ap)
struct vnode *a_vp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct inode *ip = VTOI(ap->a_vp);
VI_LOCK(vp);
UFS_INODE_SET_FLAG(ip, IN_ACCESS);
VI_UNLOCK(vp);
UFS_INODE_SET_FLAG_SHARED(ip, IN_ACCESS);
/*
* XXXKIB No UFS_UPDATE(ap->a_vp, 0) there.
*/