diff options
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 52 |
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); } |