To better understand performance problems with journalled soft updates,
we need to collect the highest level of allocation for each of the different soft update dependency structures. This change collects these statistics and makes them available using `sysctl debug.softdep.highuse'. Reviewed by: kib Tested by: Peter Holm MFC after: 2 weeks
This commit is contained in:
parent
ccc88f7b62
commit
57591d8e78
@ -661,14 +661,16 @@ FEATURE(softupdates, "FFS soft-updates support");
|
|||||||
#define D_LAST D_SENTINEL
|
#define D_LAST D_SENTINEL
|
||||||
|
|
||||||
unsigned long dep_current[D_LAST + 1];
|
unsigned long dep_current[D_LAST + 1];
|
||||||
|
unsigned long dep_highuse[D_LAST + 1];
|
||||||
unsigned long dep_total[D_LAST + 1];
|
unsigned long dep_total[D_LAST + 1];
|
||||||
unsigned long dep_write[D_LAST + 1];
|
unsigned long dep_write[D_LAST + 1];
|
||||||
|
|
||||||
|
|
||||||
static SYSCTL_NODE(_debug, OID_AUTO, softdep, CTLFLAG_RW, 0,
|
static SYSCTL_NODE(_debug, OID_AUTO, softdep, CTLFLAG_RW, 0,
|
||||||
"soft updates stats");
|
"soft updates stats");
|
||||||
static SYSCTL_NODE(_debug_softdep, OID_AUTO, total, CTLFLAG_RW, 0,
|
static SYSCTL_NODE(_debug_softdep, OID_AUTO, total, CTLFLAG_RW, 0,
|
||||||
"total dependencies allocated");
|
"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,
|
static SYSCTL_NODE(_debug_softdep, OID_AUTO, current, CTLFLAG_RW, 0,
|
||||||
"current dependencies allocated");
|
"current dependencies allocated");
|
||||||
static SYSCTL_NODE(_debug_softdep, OID_AUTO, write, CTLFLAG_RW, 0,
|
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, ""); \
|
&dep_total[D_ ## type], 0, ""); \
|
||||||
SYSCTL_ULONG(_debug_softdep_current, OID_AUTO, str, CTLFLAG_RD, \
|
SYSCTL_ULONG(_debug_softdep_current, OID_AUTO, str, CTLFLAG_RD, \
|
||||||
&dep_current[D_ ## type], 0, ""); \
|
&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, \
|
SYSCTL_ULONG(_debug_softdep_write, OID_AUTO, str, CTLFLAG_RD, \
|
||||||
&dep_write[D_ ## type], 0, "");
|
&dep_write[D_ ## type], 0, "");
|
||||||
|
|
||||||
@ -1204,8 +1208,12 @@ jwork_insert(dst, jsegdep)
|
|||||||
*/
|
*/
|
||||||
static void workitem_free(struct worklist *, int);
|
static void workitem_free(struct worklist *, int);
|
||||||
static void workitem_alloc(struct worklist *, int, struct mount *);
|
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
|
static void
|
||||||
workitem_free(item, type)
|
workitem_free(item, type)
|
||||||
@ -1219,16 +1227,22 @@ workitem_free(item, type)
|
|||||||
if (item->wk_state & ONWORKLIST)
|
if (item->wk_state & ONWORKLIST)
|
||||||
panic("workitem_free: %s(0x%X) still on list",
|
panic("workitem_free: %s(0x%X) still on list",
|
||||||
TYPENAME(item->wk_type), item->wk_state);
|
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",
|
panic("workitem_free: type mismatch %s != %s",
|
||||||
TYPENAME(item->wk_type), TYPENAME(type));
|
TYPENAME(item->wk_type), TYPENAME(type));
|
||||||
#endif
|
#endif
|
||||||
if (item->wk_state & IOWAITING)
|
if (item->wk_state & IOWAITING)
|
||||||
wakeup(item);
|
wakeup(item);
|
||||||
ump = VFSTOUFS(item->wk_mp);
|
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)
|
if (--ump->softdep_deps == 0 && ump->softdep_req)
|
||||||
wakeup(&ump->softdep_deps);
|
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));
|
free(item, DtoM(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1247,12 +1261,31 @@ workitem_alloc(item, type, mp)
|
|||||||
ump = VFSTOUFS(mp);
|
ump = VFSTOUFS(mp);
|
||||||
ACQUIRE_LOCK(&lk);
|
ACQUIRE_LOCK(&lk);
|
||||||
dep_current[type]++;
|
dep_current[type]++;
|
||||||
|
if (dep_current[type] > dep_highuse[type])
|
||||||
|
dep_highuse[type] = dep_current[type];
|
||||||
dep_total[type]++;
|
dep_total[type]++;
|
||||||
ump->softdep_deps++;
|
ump->softdep_deps++;
|
||||||
ump->softdep_accdeps++;
|
ump->softdep_accdeps++;
|
||||||
FREE_LOCK(&lk);
|
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
|
* Workitem queue management
|
||||||
*/
|
*/
|
||||||
@ -5122,7 +5155,7 @@ softdep_setup_allocdirect(ip, off, newblkno, oldblkno, newsize, oldsize, bp)
|
|||||||
/*
|
/*
|
||||||
* Convert the newblk to an allocdirect.
|
* Convert the newblk to an allocdirect.
|
||||||
*/
|
*/
|
||||||
newblk->nb_list.wk_type = D_ALLOCDIRECT;
|
WORKITEM_REASSIGN(newblk, D_ALLOCDIRECT);
|
||||||
adp = (struct allocdirect *)newblk;
|
adp = (struct allocdirect *)newblk;
|
||||||
newblk->nb_freefrag = freefrag;
|
newblk->nb_freefrag = freefrag;
|
||||||
adp->ad_offset = off;
|
adp->ad_offset = off;
|
||||||
@ -5478,7 +5511,7 @@ softdep_setup_allocext(ip, off, newblkno, oldblkno, newsize, oldsize, bp)
|
|||||||
/*
|
/*
|
||||||
* Convert the newblk to an allocdirect.
|
* Convert the newblk to an allocdirect.
|
||||||
*/
|
*/
|
||||||
newblk->nb_list.wk_type = D_ALLOCDIRECT;
|
WORKITEM_REASSIGN(newblk, D_ALLOCDIRECT);
|
||||||
adp = (struct allocdirect *)newblk;
|
adp = (struct allocdirect *)newblk;
|
||||||
newblk->nb_freefrag = freefrag;
|
newblk->nb_freefrag = freefrag;
|
||||||
adp->ad_offset = off;
|
adp->ad_offset = off;
|
||||||
@ -5587,7 +5620,7 @@ newallocindir(ip, ptrno, newblkno, oldblkno, lbn)
|
|||||||
panic("new_allocindir: lost block");
|
panic("new_allocindir: lost block");
|
||||||
KASSERT(newblk->nb_list.wk_type == D_NEWBLK,
|
KASSERT(newblk->nb_list.wk_type == D_NEWBLK,
|
||||||
("newallocindir: newblk already initialized"));
|
("newallocindir: newblk already initialized"));
|
||||||
newblk->nb_list.wk_type = D_ALLOCINDIR;
|
WORKITEM_REASSIGN(newblk, D_ALLOCINDIR);
|
||||||
newblk->nb_freefrag = freefrag;
|
newblk->nb_freefrag = freefrag;
|
||||||
aip = (struct allocindir *)newblk;
|
aip = (struct allocindir *)newblk;
|
||||||
aip->ai_offset = ptrno;
|
aip->ai_offset = ptrno;
|
||||||
@ -7218,7 +7251,9 @@ free_newblk(newblk)
|
|||||||
struct worklist *wk;
|
struct worklist *wk;
|
||||||
|
|
||||||
KASSERT(newblk->nb_jnewblk == NULL,
|
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);
|
rw_assert(&lk, RA_WLOCKED);
|
||||||
newblk_freefrag(newblk);
|
newblk_freefrag(newblk);
|
||||||
if (newblk->nb_state & ONDEPLIST)
|
if (newblk->nb_state & ONDEPLIST)
|
||||||
@ -7233,7 +7268,6 @@ free_newblk(newblk)
|
|||||||
while ((indirdep = LIST_FIRST(&newblk->nb_indirdeps)) != NULL)
|
while ((indirdep = LIST_FIRST(&newblk->nb_indirdeps)) != NULL)
|
||||||
indirdep_complete(indirdep);
|
indirdep_complete(indirdep);
|
||||||
handle_jwork(&newblk->nb_jwork);
|
handle_jwork(&newblk->nb_jwork);
|
||||||
newblk->nb_list.wk_type = D_NEWBLK;
|
|
||||||
WORKITEM_FREE(newblk, D_NEWBLK);
|
WORKITEM_FREE(newblk, D_NEWBLK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user