summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ufs/ffs/ffs_softdep.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 9ec7b46..640151b 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -661,14 +661,16 @@ FEATURE(softupdates, "FFS soft-updates support");
#define D_LAST D_SENTINEL
unsigned long dep_current[D_LAST + 1];
+unsigned long dep_highuse[D_LAST + 1];
unsigned long dep_total[D_LAST + 1];
unsigned long dep_write[D_LAST + 1];
-
static SYSCTL_NODE(_debug, OID_AUTO, softdep, CTLFLAG_RW, 0,
"soft updates stats");
static SYSCTL_NODE(_debug_softdep, OID_AUTO, total, CTLFLAG_RW, 0,
"total dependencies allocated");
+static SYSCTL_NODE(_debug_softdep, OID_AUTO, highuse, CTLFLAG_RW, 0,
+ "high use dependencies allocated");
static SYSCTL_NODE(_debug_softdep, OID_AUTO, current, CTLFLAG_RW, 0,
"current dependencies allocated");
static SYSCTL_NODE(_debug_softdep, OID_AUTO, write, CTLFLAG_RW, 0,
@@ -680,6 +682,8 @@ static SYSCTL_NODE(_debug_softdep, OID_AUTO, write, CTLFLAG_RW, 0,
&dep_total[D_ ## type], 0, ""); \
SYSCTL_ULONG(_debug_softdep_current, OID_AUTO, str, CTLFLAG_RD, \
&dep_current[D_ ## type], 0, ""); \
+ SYSCTL_ULONG(_debug_softdep_highuse, OID_AUTO, str, CTLFLAG_RD, \
+ &dep_highuse[D_ ## type], 0, ""); \
SYSCTL_ULONG(_debug_softdep_write, OID_AUTO, str, CTLFLAG_RD, \
&dep_write[D_ ## type], 0, "");
@@ -1204,8 +1208,12 @@ jwork_insert(dst, jsegdep)
*/
static void workitem_free(struct worklist *, int);
static void workitem_alloc(struct worklist *, int, struct mount *);
+static void workitem_reassign(struct worklist *, int);
-#define WORKITEM_FREE(item, type) workitem_free((struct worklist *)(item), (type))
+#define WORKITEM_FREE(item, type) \
+ workitem_free((struct worklist *)(item), (type))
+#define WORKITEM_REASSIGN(item, type) \
+ workitem_reassign((struct worklist *)(item), (type))
static void
workitem_free(item, type)
@@ -1219,16 +1227,22 @@ workitem_free(item, type)
if (item->wk_state & ONWORKLIST)
panic("workitem_free: %s(0x%X) still on list",
TYPENAME(item->wk_type), item->wk_state);
- if (item->wk_type != type)
+ if (item->wk_type != type && type != D_NEWBLK)
panic("workitem_free: type mismatch %s != %s",
TYPENAME(item->wk_type), TYPENAME(type));
#endif
if (item->wk_state & IOWAITING)
wakeup(item);
ump = VFSTOUFS(item->wk_mp);
+ KASSERT(ump->softdep_deps > 0,
+ ("workitem_free: %s: softdep_deps going negative",
+ ump->um_fs->fs_fsmnt));
if (--ump->softdep_deps == 0 && ump->softdep_req)
wakeup(&ump->softdep_deps);
- dep_current[type]--;
+ KASSERT(dep_current[item->wk_type] > 0,
+ ("workitem_free: %s: dep_current[%s] going negative",
+ ump->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
+ dep_current[item->wk_type]--;
free(item, DtoM(type));
}
@@ -1247,12 +1261,31 @@ workitem_alloc(item, type, mp)
ump = VFSTOUFS(mp);
ACQUIRE_LOCK(&lk);
dep_current[type]++;
+ if (dep_current[type] > dep_highuse[type])
+ dep_highuse[type] = dep_current[type];
dep_total[type]++;
ump->softdep_deps++;
ump->softdep_accdeps++;
FREE_LOCK(&lk);
}
+static void
+workitem_reassign(item, newtype)
+ struct worklist *item;
+ int newtype;
+{
+
+ KASSERT(dep_current[item->wk_type] > 0,
+ ("workitem_reassign: %s: dep_current[%s] going negative",
+ VFSTOUFS(item->wk_mp)->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
+ dep_current[item->wk_type]--;
+ dep_current[newtype]++;
+ if (dep_current[newtype] > dep_highuse[newtype])
+ dep_highuse[newtype] = dep_current[newtype];
+ dep_total[newtype]++;
+ item->wk_type = newtype;
+}
+
/*
* Workitem queue management
*/
@@ -5122,7 +5155,7 @@ softdep_setup_allocdirect(ip, off, newblkno, oldblkno, newsize, oldsize, bp)
/*
* Convert the newblk to an allocdirect.
*/
- newblk->nb_list.wk_type = D_ALLOCDIRECT;
+ WORKITEM_REASSIGN(newblk, D_ALLOCDIRECT);
adp = (struct allocdirect *)newblk;
newblk->nb_freefrag = freefrag;
adp->ad_offset = off;
@@ -5478,7 +5511,7 @@ softdep_setup_allocext(ip, off, newblkno, oldblkno, newsize, oldsize, bp)
/*
* Convert the newblk to an allocdirect.
*/
- newblk->nb_list.wk_type = D_ALLOCDIRECT;
+ WORKITEM_REASSIGN(newblk, D_ALLOCDIRECT);
adp = (struct allocdirect *)newblk;
newblk->nb_freefrag = freefrag;
adp->ad_offset = off;
@@ -5587,7 +5620,7 @@ newallocindir(ip, ptrno, newblkno, oldblkno, lbn)
panic("new_allocindir: lost block");
KASSERT(newblk->nb_list.wk_type == D_NEWBLK,
("newallocindir: newblk already initialized"));
- newblk->nb_list.wk_type = D_ALLOCINDIR;
+ WORKITEM_REASSIGN(newblk, D_ALLOCINDIR);
newblk->nb_freefrag = freefrag;
aip = (struct allocindir *)newblk;
aip->ai_offset = ptrno;
@@ -7218,7 +7251,9 @@ free_newblk(newblk)
struct worklist *wk;
KASSERT(newblk->nb_jnewblk == NULL,
- ("free_newblk; jnewblk %p still attached", newblk->nb_jnewblk));
+ ("free_newblk: jnewblk %p still attached", newblk->nb_jnewblk));
+ KASSERT(newblk->nb_list.wk_type != D_NEWBLK,
+ ("free_newblk: unclaimed newblk"));
rw_assert(&lk, RA_WLOCKED);
newblk_freefrag(newblk);
if (newblk->nb_state & ONDEPLIST)
@@ -7233,7 +7268,6 @@ free_newblk(newblk)
while ((indirdep = LIST_FIRST(&newblk->nb_indirdeps)) != NULL)
indirdep_complete(indirdep);
handle_jwork(&newblk->nb_jwork);
- newblk->nb_list.wk_type = D_NEWBLK;
WORKITEM_FREE(newblk, D_NEWBLK);
}
OpenPOWER on IntegriCloud