Excessively large stack frames detected.

The 2.6.30 kernel build systems sets -Wframe-larger-than=2048 which causes
a warning to be generated when an individual stack frame exceeds 2048.
This caught the spa_history_log() and dmu_objset_snapshot() functions
which declared a data structure on the stack which contained a char
array of MAXPATHLEN.  This in defined to be 4096 in the linux kernel
and I imagine it is quite large under Solaris as well.  Regardless, the
offending data structures were moved to the heap to correctly keep the
stack depth to a minimum.  We might consider setting this value even
lower to catch additional offenders because we are expecting deep stacks.
This commit is contained in:
Brian Behlendorf 2009-07-29 21:18:48 -07:00
parent 326bb586bd
commit ee435f260c
2 changed files with 30 additions and 22 deletions

View File

@ -816,46 +816,50 @@ dmu_objset_snapshot(char *fsname, char *snapname,
nvlist_t *props, boolean_t recursive) nvlist_t *props, boolean_t recursive)
{ {
dsl_sync_task_t *dst; dsl_sync_task_t *dst;
struct snaparg sn; struct snaparg *sn;
spa_t *spa; spa_t *spa;
int err; int err;
(void) strcpy(sn.failed, fsname); sn = kmem_alloc(sizeof (struct snaparg), KM_SLEEP);
(void) strcpy(sn->failed, fsname);
err = spa_open(fsname, &spa, FTAG); err = spa_open(fsname, &spa, FTAG);
if (err) if (err) {
kmem_free(sn, sizeof (struct snaparg));
return (err); return (err);
}
sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa)); sn->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
sn.snapname = snapname; sn->snapname = snapname;
sn.props = props; sn->props = props;
if (recursive) { if (recursive) {
sn.checkperms = B_TRUE; sn->checkperms = B_TRUE;
err = dmu_objset_find(fsname, err = dmu_objset_find(fsname,
dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN); dmu_objset_snapshot_one, sn, DS_FIND_CHILDREN);
} else { } else {
sn.checkperms = B_FALSE; sn->checkperms = B_FALSE;
err = dmu_objset_snapshot_one(fsname, &sn); err = dmu_objset_snapshot_one(fsname, sn);
} }
if (err == 0) if (err == 0)
err = dsl_sync_task_group_wait(sn.dstg); err = dsl_sync_task_group_wait(sn->dstg);
for (dst = list_head(&sn.dstg->dstg_tasks); dst; for (dst = list_head(&sn->dstg->dstg_tasks); dst;
dst = list_next(&sn.dstg->dstg_tasks, dst)) { dst = list_next(&sn->dstg->dstg_tasks, dst)) {
objset_t *os = dst->dst_arg1; objset_t *os = dst->dst_arg1;
dsl_dataset_t *ds = os->os->os_dsl_dataset; dsl_dataset_t *ds = os->os->os_dsl_dataset;
if (dst->dst_err) if (dst->dst_err)
dsl_dataset_name(ds, sn.failed); dsl_dataset_name(ds, sn->failed);
zil_resume(dmu_objset_zil(os)); zil_resume(dmu_objset_zil(os));
dmu_objset_close(os); dmu_objset_close(os);
} }
if (err) if (err)
(void) strcpy(fsname, sn.failed); (void) strcpy(fsname, sn->failed);
dsl_sync_task_group_destroy(sn.dstg); dsl_sync_task_group_destroy(sn->dstg);
spa_close(spa, FTAG); spa_close(spa, FTAG);
kmem_free(sn, sizeof (struct snaparg));
return (err); return (err);
} }

View File

@ -290,15 +290,19 @@ spa_history_log_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
int int
spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what) spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
{ {
history_arg_t ha; history_arg_t *ha;
int err;
ASSERT(what != LOG_INTERNAL); ASSERT(what != LOG_INTERNAL);
ha.ha_history_str = history_str; ha = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
ha.ha_log_type = what; ha->ha_history_str = history_str;
(void) strlcpy(ha.ha_zone, spa_history_zone(), sizeof (ha.ha_zone)); ha->ha_log_type = what;
return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_history_log_sync, (void) strlcpy(ha->ha_zone, spa_history_zone(), sizeof (ha->ha_zone));
spa, &ha, 0)); err = dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_history_log_sync,
spa, ha, 0);
kmem_free(ha, sizeof (history_arg_t));
return (err);
} }
/* /*