[svn-commits] sruffell: linux/trunk r6890 - /linux/trunk/drivers/dahdi/dahdi-base.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Jul 23 17:01:08 CDT 2009
Author: sruffell
Date: Thu Jul 23 17:01:04 2009
New Revision: 6890
URL: http://svn.asterisk.org/svn-view/dahdi?view=rev&rev=6890
Log:
dahdi-base: Reduce the stack usage of ioctl_load_zone.
Modified:
linux/trunk/drivers/dahdi/dahdi-base.c
Modified: linux/trunk/drivers/dahdi/dahdi-base.c
URL: http://svn.asterisk.org/svn-view/dahdi/linux/trunk/drivers/dahdi/dahdi-base.c?view=diff&rev=6890&r1=6889&r2=6890
==============================================================================
--- linux/trunk/drivers/dahdi/dahdi-base.c (original)
+++ linux/trunk/drivers/dahdi/dahdi-base.c Thu Jul 23 17:01:04 2009
@@ -2929,47 +2929,61 @@
*/
static int ioctl_load_zone(unsigned long data)
{
- struct dahdi_tone *samples[MAX_TONES] = { NULL, };
- short next[MAX_TONES] = { 0, };
- struct dahdi_tone_def_header th;
- struct dahdi_tone_def td;
- struct dahdi_zone *z;
- struct dahdi_tone *t;
- void *slab, *ptr;
- int x;
+ struct load_zone_workarea {
+ struct dahdi_tone *samples[MAX_TONES];
+ short next[MAX_TONES];
+ struct dahdi_tone_def_header th;
+ struct dahdi_tone_def td;
+ } *work;
+
size_t space;
size_t size;
int res;
-
- if (copy_from_user(&th, (struct dahdi_tone_def_header *) data, sizeof(th)))
+ int x;
+ void *slab, *ptr;
+ struct dahdi_zone *z;
+ struct dahdi_tone *t;
+
+ work = kzalloc(sizeof(*work), GFP_KERNEL);
+ if (!work)
+ return -ENOMEM;
+
+ if (copy_from_user(&work->th, (struct dahdi_tone_def_header *) data, sizeof(work->th))) {
+ kfree(work);
return -EFAULT;
-
- data += sizeof(th);
-
- if ((th.count < 0) || (th.count > MAX_TONES)) {
+ }
+
+ data += sizeof(work->th);
+
+ if ((work->th.count < 0) || (work->th.count > MAX_TONES)) {
module_printk(KERN_NOTICE, "Too many tones included\n");
+ kfree(work);
return -EINVAL;
}
- space = size = sizeof(*z) + th.count * sizeof(*t);
-
- if (size > MAX_SIZE)
+ space = size = sizeof(*z) + work->th.count * sizeof(*t);
+
+ if (size > MAX_SIZE) {
+ kfree(work);
return -E2BIG;
-
- if (!(z = ptr = slab = kzalloc(size, GFP_KERNEL)))
+ }
+
+ if (!(z = ptr = slab = kzalloc(size, GFP_KERNEL))) {
+ kfree(work);
return -ENOMEM;
+ }
ptr += sizeof(*z);
space -= sizeof(*z);
- dahdi_copy_string(z->name, th.name, sizeof(z->name));
+ dahdi_copy_string(z->name, work->th.name, sizeof(z->name));
for (x = 0; x < DAHDI_MAX_CADENCE; x++)
- z->ringcadence[x] = th.ringcadence[x];
+ z->ringcadence[x] = work->th.ringcadence[x];
atomic_set(&z->refcount, 0);
- for (x = 0; x < th.count; x++) {
+ for (x = 0; x < work->th.count; x++) {
enum {
REGULAR_TONE,
DTMF_TONE,
@@ -2980,82 +2994,86 @@
if (space < sizeof(*t)) {
kfree(slab);
+ kfree(work);
module_printk(KERN_NOTICE, "Insufficient tone zone space\n");
return -EINVAL;
}
- if (copy_from_user(&td, (struct dahdi_tone_def *) data, sizeof(td))) {
+ if (copy_from_user(&work->td, (struct dahdi_tone_def *) data, sizeof(work->td))) {
kfree(slab);
+ kfree(work);
return -EFAULT;
}
- data += sizeof(td);
-
- if ((td.tone >= 0) && (td.tone < DAHDI_TONE_MAX)) {
+ data += sizeof(work->td);
+
+ if ((work->td.tone >= 0) && (work->td.tone < DAHDI_TONE_MAX)) {
tone_type = REGULAR_TONE;
- t = samples[x] = ptr;
+ t = work->samples[x] = ptr;
space -= sizeof(*t);
ptr += sizeof(*t);
- /* Remember which sample is next */
- next[x] = td.next;
+ /* Remember which sample is work->next */
+ work->next[x] = work->td.next;
/* Make sure the "next" one is sane */
- if ((next[x] >= th.count) || (next[x] < 0)) {
- module_printk(KERN_NOTICE, "Invalid 'next' pointer: %d\n", next[x]);
+ if ((work->next[x] >= work->th.count) || (work->next[x] < 0)) {
+ module_printk(KERN_NOTICE, "Invalid 'next' pointer: %d\n", work->next[x]);
kfree(slab);
+ kfree(work);
return -EINVAL;
}
- } else if ((td.tone >= DAHDI_TONE_DTMF_BASE) &&
- (td.tone <= DAHDI_TONE_DTMF_MAX)) {
+ } else if ((work->td.tone >= DAHDI_TONE_DTMF_BASE) &&
+ (work->td.tone <= DAHDI_TONE_DTMF_MAX)) {
tone_type = DTMF_TONE;
- td.tone -= DAHDI_TONE_DTMF_BASE;
- t = &z->dtmf[td.tone];
- } else if ((td.tone >= DAHDI_TONE_MFR1_BASE) &&
- (td.tone <= DAHDI_TONE_MFR1_MAX)) {
+ work->td.tone -= DAHDI_TONE_DTMF_BASE;
+ t = &z->dtmf[work->td.tone];
+ } else if ((work->td.tone >= DAHDI_TONE_MFR1_BASE) &&
+ (work->td.tone <= DAHDI_TONE_MFR1_MAX)) {
tone_type = MFR1_TONE;
- td.tone -= DAHDI_TONE_MFR1_BASE;
- t = &z->mfr1[td.tone];
- } else if ((td.tone >= DAHDI_TONE_MFR2_FWD_BASE) &&
- (td.tone <= DAHDI_TONE_MFR2_FWD_MAX)) {
+ work->td.tone -= DAHDI_TONE_MFR1_BASE;
+ t = &z->mfr1[work->td.tone];
+ } else if ((work->td.tone >= DAHDI_TONE_MFR2_FWD_BASE) &&
+ (work->td.tone <= DAHDI_TONE_MFR2_FWD_MAX)) {
tone_type = MFR2_FWD_TONE;
- td.tone -= DAHDI_TONE_MFR2_FWD_BASE;
- t = &z->mfr2_fwd[td.tone];
- } else if ((td.tone >= DAHDI_TONE_MFR2_REV_BASE) &&
- (td.tone <= DAHDI_TONE_MFR2_REV_MAX)) {
+ work->td.tone -= DAHDI_TONE_MFR2_FWD_BASE;
+ t = &z->mfr2_fwd[work->td.tone];
+ } else if ((work->td.tone >= DAHDI_TONE_MFR2_REV_BASE) &&
+ (work->td.tone <= DAHDI_TONE_MFR2_REV_MAX)) {
tone_type = MFR2_REV_TONE;
- td.tone -= DAHDI_TONE_MFR2_REV_BASE;
- t = &z->mfr2_rev[td.tone];
+ work->td.tone -= DAHDI_TONE_MFR2_REV_BASE;
+ t = &z->mfr2_rev[work->td.tone];
} else {
- module_printk(KERN_NOTICE, "Invalid tone (%d) defined\n", td.tone);
+ module_printk(KERN_NOTICE, "Invalid tone (%d) defined\n", work->td.tone);
kfree(slab);
+ kfree(work);
return -EINVAL;
}
- t->fac1 = td.fac1;
- t->init_v2_1 = td.init_v2_1;
- t->init_v3_1 = td.init_v3_1;
- t->fac2 = td.fac2;
- t->init_v2_2 = td.init_v2_2;
- t->init_v3_2 = td.init_v3_2;
- t->modulate = td.modulate;
+ t->fac1 = work->td.fac1;
+ t->init_v2_1 = work->td.init_v2_1;
+ t->init_v3_1 = work->td.init_v3_1;
+ t->fac2 = work->td.fac2;
+ t->init_v2_2 = work->td.init_v2_2;
+ t->init_v3_2 = work->td.init_v3_2;
+ t->modulate = work->td.modulate;
switch (tone_type) {
case REGULAR_TONE:
- t->tonesamples = td.samples;
- if (!z->tones[td.tone])
- z->tones[td.tone] = t;
+ t->tonesamples = work->td.samples;
+ if (!z->tones[work->td.tone])
+ z->tones[work->td.tone] = t;
break;
case DTMF_TONE:
t->tonesamples = global_dialparams.dtmf_tonelen;
t->next = &dtmf_silence;
- z->dtmf_continuous[td.tone] = *t;
- z->dtmf_continuous[td.tone].next = &z->dtmf_continuous[td.tone];
+ z->dtmf_continuous[work->td.tone] = *t;
+ z->dtmf_continuous[work->td.tone].next = &z->dtmf_continuous[work->td.tone];
break;
case MFR1_TONE:
- switch (td.tone + DAHDI_TONE_MFR1_BASE) {
+ switch (work->td.tone + DAHDI_TONE_MFR1_BASE) {
case DAHDI_TONE_MFR1_KP:
case DAHDI_TONE_MFR1_ST:
case DAHDI_TONE_MFR1_STP:
@@ -3073,31 +3091,32 @@
case MFR2_FWD_TONE:
t->tonesamples = global_dialparams.mfr2_tonelen;
t->next = &dtmf_silence;
- z->mfr2_fwd_continuous[td.tone] = *t;
- z->mfr2_fwd_continuous[td.tone].next = &z->mfr2_fwd_continuous[td.tone];
+ z->mfr2_fwd_continuous[work->td.tone] = *t;
+ z->mfr2_fwd_continuous[work->td.tone].next = &z->mfr2_fwd_continuous[work->td.tone];
break;
case MFR2_REV_TONE:
t->tonesamples = global_dialparams.mfr2_tonelen;
t->next = &dtmf_silence;
- z->mfr2_rev_continuous[td.tone] = *t;
- z->mfr2_rev_continuous[td.tone].next = &z->mfr2_rev_continuous[td.tone];
+ z->mfr2_rev_continuous[work->td.tone] = *t;
+ z->mfr2_rev_continuous[work->td.tone].next = &z->mfr2_rev_continuous[work->td.tone];
break;
}
}
- for (x = 0; x < th.count; x++) {
- if (samples[x])
- samples[x]->next = samples[next[x]];
- }
-
- if ((res = dahdi_register_tone_zone(th.zone, z))) {
+ for (x = 0; x < work->th.count; x++) {
+ if (work->samples[x])
+ work->samples[x]->next = work->samples[work->next[x]];
+ }
+
+ if ((res = dahdi_register_tone_zone(work->th.zone, z))) {
kfree(slab);
} else {
if ( -1 == default_zone ) {
- dahdi_set_default_zone(th.zone);
- }
- }
-
+ dahdi_set_default_zone(work->th.zone);
+ }
+ }
+
+ kfree(work);
return res;
}
More information about the svn-commits
mailing list