int numvnodes;
SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0,
"Number of vnodes allocated");
+int verbose_reclaims;
+SYSCTL_INT(_debug, OID_AUTO, verbose_reclaims, CTLFLAG_RD, &verbose_reclaims, 0,
+ "Output filename of reclaimed vnode(s)");
enum vtype iftovt_tab[16] = {
VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
lwkt_gettoken(&vp->v_token);
switch(waitfor) {
+ case MNT_LAZY | MNT_NOWAIT:
case MNT_LAZY:
/*
* Lazy (filesystem syncer typ) Asynchronous plus limit the
int active;
int n;
vm_object_t object;
+ struct namecache *ncp;
/*
* If the vnode has already been reclaimed we have nothing to do.
return;
vsetflags(vp, VRECLAIMED);
+ if (verbose_reclaims) {
+ if ((ncp = TAILQ_FIRST(&vp->v_namecache)) != NULL)
+ kprintf("Debug: reclaim %p %s\n", vp, ncp->nc_name);
+ }
+
/*
* Scrap the vfs cache
*/
while (cache_inval_vp(vp, 0) != 0) {
- kprintf("Warning: vnode %p clean/cache_resolution race detected\n", vp);
+ kprintf("Warning: vnode %p clean/cache_resolution "
+ "race detected\n", vp);
tsleep(vp, 0, "vclninv", 2);
}
/*
* We only need to do something if this is a lazy evaluation.
*/
- if (ap->a_waitfor != MNT_LAZY)
+ if ((ap->a_waitfor & MNT_LAZY) == 0)
return (0);
/*
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC; /* ZZZ hack */
vfs_msync(mp, MNT_NOWAIT);
- VFS_SYNC(mp, MNT_LAZY);
+ VFS_SYNC(mp, MNT_NOWAIT | MNT_LAZY);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
}
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
- VFS_SYNC(mp, MNT_NOWAIT);
+ VFS_SYNC(mp, MNT_NOWAIT | MNT_LAZY);
mp->mnt_flag |= asyncflag;
}
return(0);
*
* waitfor flags to vfs_sync() and getfsstat()
*/
-#define MNT_WAIT 1 /* synchronously wait for I/O to complete */
-#define MNT_NOWAIT 2 /* start all I/O, but do not wait for it */
-#define MNT_LAZY 4 /* be lazy and do not necessarily push it all */
+#define MNT_WAIT 0x0001 /* synchronously wait for I/O to complete */
+#define MNT_NOWAIT 0x0002 /* start all I/O, but do not wait for it */
+#define MNT_LAZY 0x0004 /* be lazy and do not necessarily push it all */
#define VOP_FSYNC_SYSCALL 0x0001 /* from system call */
/*
* Force stale file system control information to be flushed.
*/
- if (waitfor != MNT_LAZY) {
+ if ((waitfor & MNT_LAZY) == 0) {
vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
if ((error = VOP_FSYNC(ump->um_devvp, waitfor, 0)) != 0)
scaninfo.allerror = error;
if (vp->v_type == VNON ||
((ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
- (RB_EMPTY(&vp->v_rbdirty_tree) || info->waitfor == MNT_LAZY))) {
+ (RB_EMPTY(&vp->v_rbdirty_tree) || (info->waitfor & MNT_LAZY)))) {
return(0);
}
if ((error = VOP_FSYNC(vp, info->waitfor, 0)) != 0)
* Wait for I/O associated with indirect blocks to complete,
* since there is no way to quickly wait for them below.
*/
- if (bp->b_vp == info->vp || info->waitfor == MNT_NOWAIT)
+ if (bp->b_vp == info->vp || (info->waitfor & MNT_NOWAIT))
bawrite(bp);
else
bwrite(bp);
* the vnodes in case any were already flushing during the first pass,
* and activate the flusher twice (the second time brings the UNDO FIFO's
* start position up to the end position after the first call).
+ *
+ * If doing a lazy sync make just one pass on the vnode list, ignoring
+ * any new vnodes added to the list while the sync is in progress.
*/
int
hammer_sync_hmp(hammer_mount_t hmp, int waitfor)
{
struct hammer_sync_info info;
+ int flags;
+
+ flags = VMSC_GETVP;
+ if (waitfor & MNT_LAZY)
+ flags |= VMSC_ONEPASS;
info.error = 0;
info.waitfor = MNT_NOWAIT;
- vmntvnodescan(hmp->mp, VMSC_GETVP|VMSC_NOWAIT,
+ vmntvnodescan(hmp->mp, flags | VMSC_NOWAIT,
hammer_sync_scan1, hammer_sync_scan2, &info);
- if (info.error == 0 && waitfor == MNT_WAIT) {
+
+ if (info.error == 0 && (waitfor & MNT_WAIT)) {
info.waitfor = waitfor;
- vmntvnodescan(hmp->mp, VMSC_GETVP,
+ vmntvnodescan(hmp->mp, flags,
hammer_sync_scan1, hammer_sync_scan2, &info);
}
if (waitfor == MNT_WAIT) {
/*
* Flush filesystem control info.
*/
- if (waitfor != MNT_LAZY) {
+ if ((waitfor & MNT_LAZY) == 0) {
vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY);
if ((error = VOP_FSYNC(pmp->pm_devvp, waitfor, 0)) != 0)
scaninfo.allerror = error;
if (vp->v_type == VNON || vp->v_type == VBAD ||
((dep->de_flag &
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0 &&
- (RB_EMPTY(&vp->v_rbdirty_tree) || info->waitfor == MNT_LAZY))) {
+ (RB_EMPTY(&vp->v_rbdirty_tree) || (info->waitfor & MNT_LAZY)))) {
return(0);
}
if ((error = VOP_FSYNC(vp, info->waitfor, 0)) != 0)
if (vn_islocked(vp) || RB_EMPTY(&vp->v_rbdirty_tree))
return(-1);
- if (info->waitfor == MNT_LAZY)
+ if (info->waitfor & MNT_LAZY)
return(-1);
return(0);
}
if (vp->v_mount != mp)
goto loop;
if (vn_islocked(vp) || RB_EMPTY(&vp->v_rbdirty_tree) ||
- waitfor == MNT_LAZY)
+ (waitfor & MNT_LAZY))
continue;
if (vget(vp, LK_EXCLUSIVE))
goto loop;
if (vp->v_mount != mp)
goto loop;
if (vn_islocked(vp) || RB_EMPTY(&vp->v_rbdirty_tree) ||
- waitfor == MNT_LAZY)
+ (waitfor & MNT_LAZY))
continue;
if (vget(vp, LK_EXCLUSIVE))
goto loop;
* The brief unlock is to allow any pent up dependency
* processing to be done. Then proceed with the second pass.
*/
- if (waitfor == MNT_NOWAIT) {
+ if (waitfor & MNT_NOWAIT) {
waitfor = MNT_WAIT;
FREE_LOCK(&lk);
ACQUIRE_LOCK(&lk);
if (getdirtybuf(&nbp, info->waitfor) == 0)
break;
FREE_LOCK(&lk);
- if (info->waitfor == MNT_NOWAIT) {
+ if (info->waitfor & MNT_NOWAIT) {
bawrite(nbp);
} else if ((error = bwrite(nbp)) != 0) {
bawrite(bp);
if (getdirtybuf(&nbp, info->waitfor) == 0)
break;
FREE_LOCK(&lk);
- if (info->waitfor == MNT_NOWAIT) {
+ if (info->waitfor & MNT_NOWAIT) {
bawrite(nbp);
} else if ((error = bwrite(nbp)) != 0) {
bawrite(bp);
if (getdirtybuf(&nbp, info->waitfor) == 0)
break;
FREE_LOCK(&lk);
- if (info->waitfor == MNT_NOWAIT) {
+ if (info->waitfor & MNT_NOWAIT) {
bawrite(nbp);
} else if ((error = bwrite(nbp)) != 0) {
bawrite(bp);
if (getdirtybuf(&nbp, info->waitfor) == 0)
break;
FREE_LOCK(&lk);
- if (info->waitfor == MNT_NOWAIT) {
+ if (info->waitfor & MNT_NOWAIT) {
bawrite(nbp);
} else if ((error = bwrite(nbp)) != 0) {
bawrite(bp);
continue;
bp = adp->ad_buf;
if (getdirtybuf(&bp, waitfor) == 0) {
- if (waitfor == MNT_NOWAIT)
+ if (waitfor & MNT_NOWAIT)
continue;
break;
}
FREE_LOCK(&lk);
- if (waitfor == MNT_NOWAIT) {
+ if (waitfor & MNT_NOWAIT) {
bawrite(bp);
} else if ((error = bwrite(bp)) != 0) {
ACQUIRE_LOCK(&lk);
continue;
bp = adp->ad_buf;
if (getdirtybuf(&bp, waitfor) == 0) {
- if (waitfor == MNT_NOWAIT)
+ if (waitfor & MNT_NOWAIT)
continue;
break;
}
FREE_LOCK(&lk);
- if (waitfor == MNT_NOWAIT) {
+ if (waitfor & MNT_NOWAIT) {
bawrite(bp);
} else if ((error = bwrite(bp)) != 0) {
ACQUIRE_LOCK(&lk);
/*
* Force stale filesystem control information to be flushed.
*/
- if (waitfor != MNT_LAZY) {
+ if ((waitfor & MNT_LAZY) == 0) {
if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
waitfor = MNT_NOWAIT;
vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);