summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ufs/ffs/ffs_softdep.c17
-rw-r--r--sys/ufs/ufs/ufsmount.h1
2 files changed, 13 insertions, 5 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 78383d6..872433d 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -499,6 +499,7 @@ static int num_on_worklist; /* number of worklist items to be processed */
static int softdep_worklist_busy; /* 1 => trying to do unmount */
static int softdep_worklist_req; /* serialized waiters */
static int max_softdeps; /* maximum number of structs before slowdown */
+static int maxindirdeps = 50; /* max number of indirdeps before slowdown */
static int tickdelay = 2; /* number of ticks to pause during slowdown */
static int proc_waiting; /* tracks whether we have a timeout posted */
static int *stat_countp; /* statistic to count in proc_waiting timeout */
@@ -527,6 +528,7 @@ static int stat_dir_entry; /* bufs redirtied as dir entry cannot write */
#include <sys/sysctl.h>
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, maxindirdeps, CTLFLAG_RW, &maxindirdeps, 0, "");
SYSCTL_INT(_debug, OID_AUTO, worklist_push, CTLFLAG_RW, &stat_worklist_push, 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,"");
@@ -1862,8 +1864,7 @@ setup_allocindir_phase2(bp, ip, aip)
handle_workitem_freefrag(freefrag);
}
if (newindirdep) {
- if (indirdep->ir_savebp != NULL)
- brelse(newindirdep->ir_savebp);
+ brelse(newindirdep->ir_savebp);
WORKITEM_FREE((caddr_t)newindirdep, D_INDIRDEP);
}
if (indirdep)
@@ -2125,6 +2126,7 @@ deallocate_dependencies(bp, inodedep)
panic("deallocate_dependencies: already gone");
}
indirdep->ir_state |= GOINGAWAY;
+ VFSTOUFS(bp->b_vp->v_mount)->um_numindirdeps += 1;
while ((aip = LIST_FIRST(&indirdep->ir_deplisthd)) != 0)
free_allocindir(aip, inodedep);
if (bp->b_lblkno >= 0 ||
@@ -2564,6 +2566,7 @@ indir_trunc(freeblks, dbn, level, lbn, countp)
FREE_LOCK(&lk);
panic("indir_trunc: dangling dep");
}
+ VFSTOUFS(freeblks->fb_mnt)->um_numindirdeps -= 1;
FREE_LOCK(&lk);
} else {
FREE_LOCK(&lk);
@@ -3454,7 +3457,8 @@ softdep_disk_io_initiation(bp)
* dependency can be freed.
*/
if (LIST_FIRST(&indirdep->ir_deplisthd) == NULL) {
- indirdep->ir_savebp->b_flags |= B_INVAL | B_NOCACHE;
+ indirdep->ir_savebp->b_flags |=
+ B_INVAL | B_NOCACHE;
brelse(indirdep->ir_savebp);
/* inline expand WORKLIST_REMOVE(wk); */
wk->wk_state &= ~ONWORKLIST;
@@ -5410,8 +5414,11 @@ softdep_slowdown(vp)
max_softdeps_hard = max_softdeps * 11 / 10;
if (num_dirrem < max_softdeps_hard / 2 &&
- num_inodedep < max_softdeps_hard)
- return (0);
+ num_inodedep < max_softdeps_hard &&
+ VFSTOUFS(vp->v_mount)->um_numindirdeps < maxindirdeps)
+ return (0);
+ if (VFSTOUFS(vp->v_mount)->um_numindirdeps >= maxindirdeps)
+ speedup_syncer();
stat_sync_limit_hit += 1;
return (1);
}
diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h
index 30391fd..2b9cd44 100644
--- a/sys/ufs/ufs/ufsmount.h
+++ b/sys/ufs/ufs/ufsmount.h
@@ -73,6 +73,7 @@ struct ufsmount {
u_long um_nindir; /* indirect ptrs per block */
u_long um_bptrtodb; /* indir ptr to disk block */
u_long um_seqinc; /* inc between seq blocks */
+ long um_numindirdeps; /* indirdeps for this filesys */
time_t um_btime[MAXQUOTAS]; /* block quota time limit */
time_t um_itime[MAXQUOTAS]; /* inode quota time limit */
char um_qflags[MAXQUOTAS]; /* quota specific flags */
OpenPOWER on IntegriCloud