Get rid of the global variable rushjob and replace it with a function in

kern/vfs_subr.c named speedup_syncer() which handles the speedup request.
Change the various clients of rushjob to use the new function.
This commit is contained in:
mckusick 1999-06-15 23:37:29 +00:00
parent 06fe6c5ca3
commit 02e5fe8035
7 changed files with 215 additions and 141 deletions

View File

@ -52,8 +52,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)ffs_softdep.c 9.38 (McKusick) 5/13/99
* $Id: ffs_softdep.c,v 1.28 1999/05/14 01:26:46 mckusick Exp $
* from: @(#)ffs_softdep.c 9.40 (McKusick) 6/15/99
* $Id: ffs_softdep.c,v 1.29 1999/05/22 04:43:04 julian Exp $
*/
/*
@ -201,7 +201,7 @@ static int inodedep_lookup __P((struct fs *, ino_t, int, struct inodedep **));
static int pagedep_lookup __P((struct inode *, ufs_lbn_t, int,
struct pagedep **));
static void pause_timer __P((void *));
static int checklimit __P((long *, int));
static int request_cleanup __P((int, int));
static void add_to_worklist __P((struct worklist *));
/*
@ -449,11 +449,12 @@ static int tickdelay = 2; /* number of ticks to pause during slowdown */
static int proc_waiting; /* tracks whether we have a timeout posted */
static struct proc *filesys_syncer; /* proc of filesystem syncer process */
static int req_clear_inodedeps; /* syncer process flush some inodedeps */
#define FLUSH_INODES 1
static int req_clear_remove; /* syncer process flush some freeblks */
#define FLUSH_REMOVE 2
/*
* runtime statistics
*/
static int stat_rush_requests; /* number of times I/O speeded up */
static int stat_blk_limit_push; /* number of times block limit neared */
static int stat_ino_limit_push; /* number of times inode limit neared */
static int stat_blk_limit_hit; /* number of times block slowdown imposed */
@ -468,7 +469,6 @@ static int stat_dir_entry; /* bufs redirtied as dir entry cannot write */
#if defined(__FreeBSD__)
SYSCTL_INT(_debug, OID_AUTO, max_softdeps, CTLFLAG_RW, &max_softdeps, 0, "");
SYSCTL_INT(_debug, OID_AUTO, tickdelay, CTLFLAG_RW, &tickdelay, 0, "");
SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0, "");
SYSCTL_INT(_debug, OID_AUTO, blk_limit_push, CTLFLAG_RW, &stat_blk_limit_push, 0,"");
SYSCTL_INT(_debug, OID_AUTO, ino_limit_push, CTLFLAG_RW, &stat_ino_limit_push, 0,"");
SYSCTL_INT(_debug, OID_AUTO, blk_limit_hit, CTLFLAG_RW, &stat_blk_limit_hit, 0, "");
@ -480,7 +480,6 @@ SYSCTL_INT(_debug, OID_AUTO, dir_entry, CTLFLAG_RW, &stat_dir_entry, 0, "");
#else /* !__FreeBSD__ */
struct ctldebug debug20 = { "max_softdeps", &max_softdeps };
struct ctldebug debug21 = { "tickdelay", &tickdelay };
struct ctldebug debug22 = { "rush_requests", &stat_rush_requests };
struct ctldebug debug23 = { "blk_limit_push", &stat_blk_limit_push };
struct ctldebug debug24 = { "ino_limit_push", &stat_ino_limit_push };
struct ctldebug debug25 = { "blk_limit_hit", &stat_blk_limit_hit };
@ -535,8 +534,8 @@ softdep_process_worklist(matchmnt)
int matchcnt;
/*
* Record the process identifier of our caller so that we can
* give this process preferential treatment in checklimit below.
* Record the process identifier of our caller so that we can give
* this process preferential treatment in request_cleanup below.
*/
filesys_syncer = p;
matchcnt = 0;
@ -828,7 +827,11 @@ top:
*inodedeppp = NULL;
return (0);
}
if (firsttry && checklimit(&num_inodedep, 1) == 1) {
/*
* If we are over our limit, try to improve the situation.
*/
if (num_inodedep > max_softdeps && firsttry && speedup_syncer() == 0 &&
request_cleanup(FLUSH_INODES, 1)) {
firsttry = 0;
goto top;
}
@ -1577,7 +1580,11 @@ softdep_setup_freeblocks(ip, length)
fs = ip->i_fs;
if (length != 0)
panic("softde_setup_freeblocks: non-zero length");
(void) checklimit(&num_freeblks, 0);
/*
* If we are over our limit, try to improve the situation.
*/
if (num_freeblks > max_softdeps / 2 && speedup_syncer() == 0)
(void) request_cleanup(FLUSH_REMOVE, 0);
num_freeblks += 1;
MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
M_FREEBLKS, M_WAITOK);
@ -1810,10 +1817,14 @@ softdep_freefile(pvp, ino, mode)
struct inodedep *inodedep;
struct freefile *freefile;
/*
* If we are over our limit, try to improve the situation.
*/
if (num_freefile > max_softdeps / 2 && speedup_syncer() == 0)
(void) request_cleanup(FLUSH_REMOVE, 0);
/*
* This sets up the inode de-allocation dependency.
*/
(void) checklimit(&num_freefile, 0);
num_freefile += 1;
MALLOC(freefile, struct freefile *, sizeof(struct freefile),
M_FREEFILE, M_WAITOK);
@ -3774,7 +3785,6 @@ softdep_sync_metadata(ap)
waitfor = MNT_NOWAIT;
top:
if (getdirtybuf(&TAILQ_FIRST(&vp->v_dirtyblkhd), MNT_WAIT) == 0) {
drain_output(vp, 1);
FREE_LOCK(&lk);
return (0);
}
@ -4189,38 +4199,18 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* many dependencies in progress.
*/
static int
checklimit(resource, islocked)
long *resource;
request_cleanup(resource, islocked)
int resource;
int islocked;
{
struct callout_handle handle;
struct proc *p = CURPROC;
int s;
/*
* If we are under our limit, just proceed.
*/
if (*resource < max_softdeps)
return (0);
/*
* We never hold up the filesystem syncer process.
*/
if (p == filesys_syncer)
return (0);
/*
* Our first approach is to speed up the syncer process.
* We never push it to speed up more than half of its
* normal turn time, otherwise it could take over the cpu.
*/
s = splhigh();
if (filesys_syncer->p_wchan == &lbolt)
setrunnable(filesys_syncer);
splx(s);
if (rushjob < syncdelay / 2) {
rushjob += 1;
stat_rush_requests += 1;
return (0);
}
/*
* If we are resource constrained on inode dependencies, try
* flushing some dirty inodes. Otherwise, we are constrained
@ -4228,15 +4218,23 @@ checklimit(resource, islocked)
* with removal dependencies. We would like to do the cleanup
* here, but we probably hold an inode locked at this point and
* that might deadlock against one that we try to clean. So,
* the best that we can do is request the syncer daemon (kick
* started above) to do the cleanup for us.
* the best that we can do is request the syncer daemon to do
* the cleanup for us.
*/
if (resource == &num_inodedep) {
switch (resource) {
case FLUSH_INODES:
stat_ino_limit_push += 1;
req_clear_inodedeps = 1;
} else {
break;
case FLUSH_REMOVE:
stat_blk_limit_push += 1;
req_clear_remove = 1;
break;
default:
panic("request_cleanup: unknown type");
}
/*
* Hopefully the syncer daemon will catch up and awaken us.
@ -4256,10 +4254,16 @@ checklimit(resource, islocked)
untimeout(pause_timer, NULL, handle);
proc_waiting = 0;
} else {
if (resource == &num_inodedep)
switch (resource) {
case FLUSH_INODES:
stat_ino_limit_hit += 1;
else
break;
case FLUSH_REMOVE:
stat_blk_limit_hit += 1;
break;
}
}
if (islocked == 0)
FREE_LOCK(&lk);
@ -4267,7 +4271,7 @@ checklimit(resource, islocked)
}
/*
* Awaken processes pausing in checklimit and clear proc_waiting
* Awaken processes pausing in request_cleanup and clear proc_waiting
* to indicate that there is no longer a timer running.
*/
void

View File

@ -52,8 +52,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)ffs_softdep.c 9.38 (McKusick) 5/13/99
* $Id: ffs_softdep.c,v 1.28 1999/05/14 01:26:46 mckusick Exp $
* from: @(#)ffs_softdep.c 9.40 (McKusick) 6/15/99
* $Id: ffs_softdep.c,v 1.29 1999/05/22 04:43:04 julian Exp $
*/
/*
@ -201,7 +201,7 @@ static int inodedep_lookup __P((struct fs *, ino_t, int, struct inodedep **));
static int pagedep_lookup __P((struct inode *, ufs_lbn_t, int,
struct pagedep **));
static void pause_timer __P((void *));
static int checklimit __P((long *, int));
static int request_cleanup __P((int, int));
static void add_to_worklist __P((struct worklist *));
/*
@ -449,11 +449,12 @@ static int tickdelay = 2; /* number of ticks to pause during slowdown */
static int proc_waiting; /* tracks whether we have a timeout posted */
static struct proc *filesys_syncer; /* proc of filesystem syncer process */
static int req_clear_inodedeps; /* syncer process flush some inodedeps */
#define FLUSH_INODES 1
static int req_clear_remove; /* syncer process flush some freeblks */
#define FLUSH_REMOVE 2
/*
* runtime statistics
*/
static int stat_rush_requests; /* number of times I/O speeded up */
static int stat_blk_limit_push; /* number of times block limit neared */
static int stat_ino_limit_push; /* number of times inode limit neared */
static int stat_blk_limit_hit; /* number of times block slowdown imposed */
@ -468,7 +469,6 @@ static int stat_dir_entry; /* bufs redirtied as dir entry cannot write */
#if defined(__FreeBSD__)
SYSCTL_INT(_debug, OID_AUTO, max_softdeps, CTLFLAG_RW, &max_softdeps, 0, "");
SYSCTL_INT(_debug, OID_AUTO, tickdelay, CTLFLAG_RW, &tickdelay, 0, "");
SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0, "");
SYSCTL_INT(_debug, OID_AUTO, blk_limit_push, CTLFLAG_RW, &stat_blk_limit_push, 0,"");
SYSCTL_INT(_debug, OID_AUTO, ino_limit_push, CTLFLAG_RW, &stat_ino_limit_push, 0,"");
SYSCTL_INT(_debug, OID_AUTO, blk_limit_hit, CTLFLAG_RW, &stat_blk_limit_hit, 0, "");
@ -480,7 +480,6 @@ SYSCTL_INT(_debug, OID_AUTO, dir_entry, CTLFLAG_RW, &stat_dir_entry, 0, "");
#else /* !__FreeBSD__ */
struct ctldebug debug20 = { "max_softdeps", &max_softdeps };
struct ctldebug debug21 = { "tickdelay", &tickdelay };
struct ctldebug debug22 = { "rush_requests", &stat_rush_requests };
struct ctldebug debug23 = { "blk_limit_push", &stat_blk_limit_push };
struct ctldebug debug24 = { "ino_limit_push", &stat_ino_limit_push };
struct ctldebug debug25 = { "blk_limit_hit", &stat_blk_limit_hit };
@ -535,8 +534,8 @@ softdep_process_worklist(matchmnt)
int matchcnt;
/*
* Record the process identifier of our caller so that we can
* give this process preferential treatment in checklimit below.
* Record the process identifier of our caller so that we can give
* this process preferential treatment in request_cleanup below.
*/
filesys_syncer = p;
matchcnt = 0;
@ -828,7 +827,11 @@ top:
*inodedeppp = NULL;
return (0);
}
if (firsttry && checklimit(&num_inodedep, 1) == 1) {
/*
* If we are over our limit, try to improve the situation.
*/
if (num_inodedep > max_softdeps && firsttry && speedup_syncer() == 0 &&
request_cleanup(FLUSH_INODES, 1)) {
firsttry = 0;
goto top;
}
@ -1577,7 +1580,11 @@ softdep_setup_freeblocks(ip, length)
fs = ip->i_fs;
if (length != 0)
panic("softde_setup_freeblocks: non-zero length");
(void) checklimit(&num_freeblks, 0);
/*
* If we are over our limit, try to improve the situation.
*/
if (num_freeblks > max_softdeps / 2 && speedup_syncer() == 0)
(void) request_cleanup(FLUSH_REMOVE, 0);
num_freeblks += 1;
MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
M_FREEBLKS, M_WAITOK);
@ -1810,10 +1817,14 @@ softdep_freefile(pvp, ino, mode)
struct inodedep *inodedep;
struct freefile *freefile;
/*
* If we are over our limit, try to improve the situation.
*/
if (num_freefile > max_softdeps / 2 && speedup_syncer() == 0)
(void) request_cleanup(FLUSH_REMOVE, 0);
/*
* This sets up the inode de-allocation dependency.
*/
(void) checklimit(&num_freefile, 0);
num_freefile += 1;
MALLOC(freefile, struct freefile *, sizeof(struct freefile),
M_FREEFILE, M_WAITOK);
@ -3774,7 +3785,6 @@ softdep_sync_metadata(ap)
waitfor = MNT_NOWAIT;
top:
if (getdirtybuf(&TAILQ_FIRST(&vp->v_dirtyblkhd), MNT_WAIT) == 0) {
drain_output(vp, 1);
FREE_LOCK(&lk);
return (0);
}
@ -4189,38 +4199,18 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* many dependencies in progress.
*/
static int
checklimit(resource, islocked)
long *resource;
request_cleanup(resource, islocked)
int resource;
int islocked;
{
struct callout_handle handle;
struct proc *p = CURPROC;
int s;
/*
* If we are under our limit, just proceed.
*/
if (*resource < max_softdeps)
return (0);
/*
* We never hold up the filesystem syncer process.
*/
if (p == filesys_syncer)
return (0);
/*
* Our first approach is to speed up the syncer process.
* We never push it to speed up more than half of its
* normal turn time, otherwise it could take over the cpu.
*/
s = splhigh();
if (filesys_syncer->p_wchan == &lbolt)
setrunnable(filesys_syncer);
splx(s);
if (rushjob < syncdelay / 2) {
rushjob += 1;
stat_rush_requests += 1;
return (0);
}
/*
* If we are resource constrained on inode dependencies, try
* flushing some dirty inodes. Otherwise, we are constrained
@ -4228,15 +4218,23 @@ checklimit(resource, islocked)
* with removal dependencies. We would like to do the cleanup
* here, but we probably hold an inode locked at this point and
* that might deadlock against one that we try to clean. So,
* the best that we can do is request the syncer daemon (kick
* started above) to do the cleanup for us.
* the best that we can do is request the syncer daemon to do
* the cleanup for us.
*/
if (resource == &num_inodedep) {
switch (resource) {
case FLUSH_INODES:
stat_ino_limit_push += 1;
req_clear_inodedeps = 1;
} else {
break;
case FLUSH_REMOVE:
stat_blk_limit_push += 1;
req_clear_remove = 1;
break;
default:
panic("request_cleanup: unknown type");
}
/*
* Hopefully the syncer daemon will catch up and awaken us.
@ -4256,10 +4254,16 @@ checklimit(resource, islocked)
untimeout(pause_timer, NULL, handle);
proc_waiting = 0;
} else {
if (resource == &num_inodedep)
switch (resource) {
case FLUSH_INODES:
stat_ino_limit_hit += 1;
else
break;
case FLUSH_REMOVE:
stat_blk_limit_hit += 1;
break;
}
}
if (islocked == 0)
FREE_LOCK(&lk);
@ -4267,7 +4271,7 @@ checklimit(resource, islocked)
}
/*
* Awaken processes pausing in checklimit and clear proc_waiting
* Awaken processes pausing in request_cleanup and clear proc_waiting
* to indicate that there is no longer a timer running.
*/
void

View File

@ -11,7 +11,7 @@
* 2. Absolutely no warranty of function or purpose is made by the author
* John S. Dyson.
*
* $Id: vfs_bio.c,v 1.210 1999/05/06 20:00:26 phk Exp $
* $Id: vfs_bio.c,v 1.211 1999/05/12 22:30:50 peter Exp $
*/
/*
@ -1475,8 +1475,7 @@ dosleep:
else
flags = VFS_BIO_NEED_ANY;
if (rushjob < syncdelay / 2)
++rushjob;
(void) speedup_syncer();
needsbuffer |= flags;
while (needsbuffer & flags) {
if (tsleep(&needsbuffer, (PRIBIO + 4) | slpflag,

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
* $Id: vfs_subr.c,v 1.199 1999/05/24 00:34:10 jb Exp $
* $Id: vfs_subr.c,v 1.200 1999/05/31 11:27:44 phk Exp $
*/
/*
@ -125,8 +125,16 @@ static vm_zone_t vnode_zone;
*/
#define SYNCER_MAXDELAY 32
static int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */
time_t syncdelay = 30;
int rushjob; /* number of slots to run ASAP */
time_t syncdelay = 30; /* max time to delay syncing data */
time_t filedelay = 30; /* time to delay syncing files */
SYSCTL_INT(_kern, OID_AUTO, filedelay, CTLFLAG_RW, &filedelay, 0, "");
time_t dirdelay = 15; /* time to delay syncing directories */
SYSCTL_INT(_kern, OID_AUTO, dirdelay, CTLFLAG_RW, &dirdelay, 0, "");
time_t metadelay = 10; /* time to delay syncing metadata */
SYSCTL_INT(_kern, OID_AUTO, metadelay, CTLFLAG_RW, &metadelay, 0, "");
static int rushjob; /* number of slots to run ASAP */
static int stat_rush_requests; /* number of times I/O speeded up */
SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0, "");
static int syncer_delayno = 0;
static long syncer_mask;
@ -998,6 +1006,28 @@ sched_sync(void)
}
}
/*
* Request the syncer daemon to speed up its work.
* We never push it to speed up more than half of its
* normal turn time, otherwise it could take over the cpu.
*/
int
speedup_syncer()
{
int s;
s = splhigh();
if (updateproc->p_wchan == &lbolt)
setrunnable(updateproc);
splx(s);
if (rushjob < syncdelay / 2) {
rushjob += 1;
stat_rush_requests += 1;
return (1);
}
return(0);
}
/*
* Associate a p-buffer with a vnode.
*
@ -1116,16 +1146,16 @@ reassignbuf(bp, newvp)
if ((newvp->v_flag & VONWORKLST) == 0) {
switch (newvp->v_type) {
case VDIR:
delay = syncdelay / 2;
delay = dirdelay;
break;
case VBLK:
if (newvp->v_specmountpoint != NULL) {
delay = syncdelay / 3;
delay = metadelay;
break;
}
/* fall through */
default:
delay = syncdelay;
delay = filedelay;
}
vn_syncer_add_to_worklist(newvp, delay);
}

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
* $Id: vfs_subr.c,v 1.199 1999/05/24 00:34:10 jb Exp $
* $Id: vfs_subr.c,v 1.200 1999/05/31 11:27:44 phk Exp $
*/
/*
@ -125,8 +125,16 @@ static vm_zone_t vnode_zone;
*/
#define SYNCER_MAXDELAY 32
static int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */
time_t syncdelay = 30;
int rushjob; /* number of slots to run ASAP */
time_t syncdelay = 30; /* max time to delay syncing data */
time_t filedelay = 30; /* time to delay syncing files */
SYSCTL_INT(_kern, OID_AUTO, filedelay, CTLFLAG_RW, &filedelay, 0, "");
time_t dirdelay = 15; /* time to delay syncing directories */
SYSCTL_INT(_kern, OID_AUTO, dirdelay, CTLFLAG_RW, &dirdelay, 0, "");
time_t metadelay = 10; /* time to delay syncing metadata */
SYSCTL_INT(_kern, OID_AUTO, metadelay, CTLFLAG_RW, &metadelay, 0, "");
static int rushjob; /* number of slots to run ASAP */
static int stat_rush_requests; /* number of times I/O speeded up */
SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0, "");
static int syncer_delayno = 0;
static long syncer_mask;
@ -998,6 +1006,28 @@ sched_sync(void)
}
}
/*
* Request the syncer daemon to speed up its work.
* We never push it to speed up more than half of its
* normal turn time, otherwise it could take over the cpu.
*/
int
speedup_syncer()
{
int s;
s = splhigh();
if (updateproc->p_wchan == &lbolt)
setrunnable(updateproc);
splx(s);
if (rushjob < syncdelay / 2) {
rushjob += 1;
stat_rush_requests += 1;
return (1);
}
return(0);
}
/*
* Associate a p-buffer with a vnode.
*
@ -1116,16 +1146,16 @@ reassignbuf(bp, newvp)
if ((newvp->v_flag & VONWORKLST) == 0) {
switch (newvp->v_type) {
case VDIR:
delay = syncdelay / 2;
delay = dirdelay;
break;
case VBLK:
if (newvp->v_specmountpoint != NULL) {
delay = syncdelay / 3;
delay = metadelay;
break;
}
/* fall through */
default:
delay = syncdelay;
delay = filedelay;
}
vn_syncer_add_to_worklist(newvp, delay);
}

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)vnode.h 8.7 (Berkeley) 2/4/94
* $Id: vnode.h,v 1.86 1999/04/17 08:36:06 peter Exp $
* $Id: vnode.h,v 1.87 1999/05/11 19:55:01 phk Exp $
*/
#ifndef _SYS_VNODE_H_
@ -268,8 +268,10 @@ extern int vttoif_tab[];
*/
extern struct vnode *rootvnode; /* root (i.e. "/") vnode */
extern int desiredvnodes; /* number of vnodes desired */
extern time_t syncdelay; /* time to delay syncing vnodes */
extern int rushjob; /* # of slots filesys_syncer should run ASAP */
extern time_t syncdelay; /* max time to delay syncing data */
extern time_t filedelay; /* time to delay syncing files */
extern time_t dirdelay; /* time to delay syncing directories */
extern time_t metadelay; /* time to delay syncing metadata */
extern struct vm_zone *namei_zone;
extern int prtactive; /* nonzero to call vprint() */
extern struct vattr va_null; /* predefined null vattr structure */
@ -484,6 +486,7 @@ void cvtnstat __P((struct stat *sb, struct nstat *nsb));
int getnewvnode __P((enum vtagtype tag,
struct mount *mp, vop_t **vops, struct vnode **vpp));
int lease_check __P((struct vop_lease_args *ap));
int speedup_syncer __P((void));
void vattr_null __P((struct vattr *vap));
int vcount __P((struct vnode *vp));
void vdrop __P((struct vnode *));

View File

@ -52,8 +52,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)ffs_softdep.c 9.38 (McKusick) 5/13/99
* $Id: ffs_softdep.c,v 1.28 1999/05/14 01:26:46 mckusick Exp $
* from: @(#)ffs_softdep.c 9.40 (McKusick) 6/15/99
* $Id: ffs_softdep.c,v 1.29 1999/05/22 04:43:04 julian Exp $
*/
/*
@ -201,7 +201,7 @@ static int inodedep_lookup __P((struct fs *, ino_t, int, struct inodedep **));
static int pagedep_lookup __P((struct inode *, ufs_lbn_t, int,
struct pagedep **));
static void pause_timer __P((void *));
static int checklimit __P((long *, int));
static int request_cleanup __P((int, int));
static void add_to_worklist __P((struct worklist *));
/*
@ -449,11 +449,12 @@ static int tickdelay = 2; /* number of ticks to pause during slowdown */
static int proc_waiting; /* tracks whether we have a timeout posted */
static struct proc *filesys_syncer; /* proc of filesystem syncer process */
static int req_clear_inodedeps; /* syncer process flush some inodedeps */
#define FLUSH_INODES 1
static int req_clear_remove; /* syncer process flush some freeblks */
#define FLUSH_REMOVE 2
/*
* runtime statistics
*/
static int stat_rush_requests; /* number of times I/O speeded up */
static int stat_blk_limit_push; /* number of times block limit neared */
static int stat_ino_limit_push; /* number of times inode limit neared */
static int stat_blk_limit_hit; /* number of times block slowdown imposed */
@ -468,7 +469,6 @@ static int stat_dir_entry; /* bufs redirtied as dir entry cannot write */
#if defined(__FreeBSD__)
SYSCTL_INT(_debug, OID_AUTO, max_softdeps, CTLFLAG_RW, &max_softdeps, 0, "");
SYSCTL_INT(_debug, OID_AUTO, tickdelay, CTLFLAG_RW, &tickdelay, 0, "");
SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0, "");
SYSCTL_INT(_debug, OID_AUTO, blk_limit_push, CTLFLAG_RW, &stat_blk_limit_push, 0,"");
SYSCTL_INT(_debug, OID_AUTO, ino_limit_push, CTLFLAG_RW, &stat_ino_limit_push, 0,"");
SYSCTL_INT(_debug, OID_AUTO, blk_limit_hit, CTLFLAG_RW, &stat_blk_limit_hit, 0, "");
@ -480,7 +480,6 @@ SYSCTL_INT(_debug, OID_AUTO, dir_entry, CTLFLAG_RW, &stat_dir_entry, 0, "");
#else /* !__FreeBSD__ */
struct ctldebug debug20 = { "max_softdeps", &max_softdeps };
struct ctldebug debug21 = { "tickdelay", &tickdelay };
struct ctldebug debug22 = { "rush_requests", &stat_rush_requests };
struct ctldebug debug23 = { "blk_limit_push", &stat_blk_limit_push };
struct ctldebug debug24 = { "ino_limit_push", &stat_ino_limit_push };
struct ctldebug debug25 = { "blk_limit_hit", &stat_blk_limit_hit };
@ -535,8 +534,8 @@ softdep_process_worklist(matchmnt)
int matchcnt;
/*
* Record the process identifier of our caller so that we can
* give this process preferential treatment in checklimit below.
* Record the process identifier of our caller so that we can give
* this process preferential treatment in request_cleanup below.
*/
filesys_syncer = p;
matchcnt = 0;
@ -828,7 +827,11 @@ top:
*inodedeppp = NULL;
return (0);
}
if (firsttry && checklimit(&num_inodedep, 1) == 1) {
/*
* If we are over our limit, try to improve the situation.
*/
if (num_inodedep > max_softdeps && firsttry && speedup_syncer() == 0 &&
request_cleanup(FLUSH_INODES, 1)) {
firsttry = 0;
goto top;
}
@ -1577,7 +1580,11 @@ softdep_setup_freeblocks(ip, length)
fs = ip->i_fs;
if (length != 0)
panic("softde_setup_freeblocks: non-zero length");
(void) checklimit(&num_freeblks, 0);
/*
* If we are over our limit, try to improve the situation.
*/
if (num_freeblks > max_softdeps / 2 && speedup_syncer() == 0)
(void) request_cleanup(FLUSH_REMOVE, 0);
num_freeblks += 1;
MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
M_FREEBLKS, M_WAITOK);
@ -1810,10 +1817,14 @@ softdep_freefile(pvp, ino, mode)
struct inodedep *inodedep;
struct freefile *freefile;
/*
* If we are over our limit, try to improve the situation.
*/
if (num_freefile > max_softdeps / 2 && speedup_syncer() == 0)
(void) request_cleanup(FLUSH_REMOVE, 0);
/*
* This sets up the inode de-allocation dependency.
*/
(void) checklimit(&num_freefile, 0);
num_freefile += 1;
MALLOC(freefile, struct freefile *, sizeof(struct freefile),
M_FREEFILE, M_WAITOK);
@ -3774,7 +3785,6 @@ softdep_sync_metadata(ap)
waitfor = MNT_NOWAIT;
top:
if (getdirtybuf(&TAILQ_FIRST(&vp->v_dirtyblkhd), MNT_WAIT) == 0) {
drain_output(vp, 1);
FREE_LOCK(&lk);
return (0);
}
@ -4189,38 +4199,18 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* many dependencies in progress.
*/
static int
checklimit(resource, islocked)
long *resource;
request_cleanup(resource, islocked)
int resource;
int islocked;
{
struct callout_handle handle;
struct proc *p = CURPROC;
int s;
/*
* If we are under our limit, just proceed.
*/
if (*resource < max_softdeps)
return (0);
/*
* We never hold up the filesystem syncer process.
*/
if (p == filesys_syncer)
return (0);
/*
* Our first approach is to speed up the syncer process.
* We never push it to speed up more than half of its
* normal turn time, otherwise it could take over the cpu.
*/
s = splhigh();
if (filesys_syncer->p_wchan == &lbolt)
setrunnable(filesys_syncer);
splx(s);
if (rushjob < syncdelay / 2) {
rushjob += 1;
stat_rush_requests += 1;
return (0);
}
/*
* If we are resource constrained on inode dependencies, try
* flushing some dirty inodes. Otherwise, we are constrained
@ -4228,15 +4218,23 @@ checklimit(resource, islocked)
* with removal dependencies. We would like to do the cleanup
* here, but we probably hold an inode locked at this point and
* that might deadlock against one that we try to clean. So,
* the best that we can do is request the syncer daemon (kick
* started above) to do the cleanup for us.
* the best that we can do is request the syncer daemon to do
* the cleanup for us.
*/
if (resource == &num_inodedep) {
switch (resource) {
case FLUSH_INODES:
stat_ino_limit_push += 1;
req_clear_inodedeps = 1;
} else {
break;
case FLUSH_REMOVE:
stat_blk_limit_push += 1;
req_clear_remove = 1;
break;
default:
panic("request_cleanup: unknown type");
}
/*
* Hopefully the syncer daemon will catch up and awaken us.
@ -4256,10 +4254,16 @@ checklimit(resource, islocked)
untimeout(pause_timer, NULL, handle);
proc_waiting = 0;
} else {
if (resource == &num_inodedep)
switch (resource) {
case FLUSH_INODES:
stat_ino_limit_hit += 1;
else
break;
case FLUSH_REMOVE:
stat_blk_limit_hit += 1;
break;
}
}
if (islocked == 0)
FREE_LOCK(&lk);
@ -4267,7 +4271,7 @@ checklimit(resource, islocked)
}
/*
* Awaken processes pausing in checklimit and clear proc_waiting
* Awaken processes pausing in request_cleanup and clear proc_waiting
* to indicate that there is no longer a timer running.
*/
void