XXX softdep:

If the number of deletes in progress is getting too high, newdirrem()
requests the syncer to flush faster, and in some cases will block to
prevent deletes accumulating faster than the disk can service them.

The syncer will try to lock vnodes that the remover holds locked, leading
to the syncer and remover proceeding in lockstep and making very little
overall forward progress.

Put a hook into ufs_rmdir() and ufs_remove() so that the softdep code
can pace itself without holding vnode locks if the number of deletes is
running out of control.
This commit is contained in:
ad 2008-05-31 21:37:08 +00:00
parent 736a4d9b78
commit 3592ae4882
4 changed files with 48 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_softdep.c,v 1.112 2008/05/16 09:22:00 hannken Exp $ */
/* $NetBSD: ffs_softdep.c,v 1.113 2008/05/31 21:37:08 ad Exp $ */
/*
* Copyright 1998 Marshall Kirk McKusick. All Rights Reserved.
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.c,v 1.112 2008/05/16 09:22:00 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.c,v 1.113 2008/05/31 21:37:08 ad Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@ -2948,6 +2948,21 @@ newdirrem(bp, dp, ip, isrmdir, prevdirremp)
return (dirrem);
}
void
softdep_pace_dirrem(void)
{
int limit;
limit = max_softdeps >> 1;
if (num_dirrem <= limit)
return;
mutex_enter(&bufcache_lock);
if (num_dirrem > limit)
(void)cv_timedwait(&proc_wait_cv, &bufcache_lock, tickdelay);
mutex_exit(&bufcache_lock);
}
/*
* Directory entry change dependencies.
*

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_softdep.stub.c,v 1.22 2008/01/02 11:49:09 ad Exp $ */
/* $NetBSD: ffs_softdep.stub.c,v 1.23 2008/05/31 21:37:08 ad Exp $ */
/*
* Copyright 1997 Marshall Kirk McKusick. All Rights Reserved.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.stub.c,v 1.22 2008/01/02 11:49:09 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.stub.c,v 1.23 2008/05/31 21:37:08 ad Exp $");
#include <sys/param.h>
#include <sys/vnode.h>
@ -221,3 +221,10 @@ softdep_unmount(struct mount *mp)
return;
}
void
softdep_pace_dirrem(void)
{
panic("softdep_pace_dirrem called");
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_extern.h,v 1.59 2008/05/16 09:22:01 hannken Exp $ */
/* $NetBSD: ufs_extern.h,v 1.60 2008/05/31 21:37:08 ad Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -184,6 +184,7 @@ void softdep_setup_directory_change(struct buf *, struct inode *,
struct inode *, ino_t, int);
void softdep_change_linkcnt(struct inode *);
void softdep_releasefile(struct inode *);
void softdep_pace_dirrem(void);
__END_DECLS

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_vnops.c,v 1.164 2008/01/30 09:50:27 ad Exp $ */
/* $NetBSD: ufs_vnops.c,v 1.165 2008/05/31 21:37:08 ad Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993, 1995
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.164 2008/01/30 09:50:27 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.165 2008/05/31 21:37:08 ad Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@ -642,6 +642,7 @@ ufs_remove(void *v)
struct vnode *vp, *dvp;
struct inode *ip;
int error;
bool pace;
vp = ap->a_vp;
dvp = ap->a_dvp;
@ -658,8 +659,16 @@ ufs_remove(void *v)
vrele(vp);
else
vput(vp);
pace = DOINGSOFTDEP(dvp);
vput(dvp);
fstrans_done(dvp->v_mount);
if (pace) {
/*
* Give the syncer some breathing room so that it
* can flush removes. XXX
*/
softdep_pace_dirrem();
}
return (error);
}
@ -1447,6 +1456,7 @@ ufs_rmdir(void *v)
struct componentname *cnp;
struct inode *ip, *dp;
int error;
bool pace;
vp = ap->a_vp;
dvp = ap->a_dvp;
@ -1537,8 +1547,16 @@ ufs_rmdir(void *v)
out:
VN_KNOTE(vp, NOTE_DELETE);
fstrans_done(dvp->v_mount);
pace = DOINGSOFTDEP(dvp);
vput(dvp);
vput(vp);
if (pace) {
/*
* Give the syncer some breathing room so that it
* can flush removes. XXX
*/
softdep_pace_dirrem();
}
return (error);
}