Commit de83f63b authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[PATCH] excessive stack usage in cdrom

CD-ROM puts struct cdrom_changer_info on the stack in a few places, this
is a bad idea since it's big (a bit over 1kb).  This makes us allocate
it instead.

Noticed by Anton.
parent c73dbf24
...@@ -689,21 +689,28 @@ static int cdrom_read_mech_status(struct cdrom_device_info *cdi, ...@@ -689,21 +689,28 @@ static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot) static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
{ {
struct cdrom_changer_info info; struct cdrom_changer_info *info;
int ret; int ret;
cdinfo(CD_CHANGER, "entering cdrom_slot_status()\n"); cdinfo(CD_CHANGER, "entering cdrom_slot_status()\n");
if (cdi->sanyo_slot) if (cdi->sanyo_slot)
return CDS_NO_INFO; return CDS_NO_INFO;
if ((ret = cdrom_read_mech_status(cdi, &info))) info = kmalloc(sizeof(*info), GFP_KERNEL);
return ret; if (!info)
return -ENOMEM;
if ((ret = cdrom_read_mech_status(cdi, info)))
goto out_free;
if (info.slots[slot].disc_present) if (info->slots[slot].disc_present)
return CDS_DISC_OK; ret = CDS_DISC_OK;
else else
return CDS_NO_DISC; ret = CDS_NO_DISC;
out_free:
kfree(info);
return ret;
} }
/* Return the number of slots for an ATAPI/SCSI cdrom, /* Return the number of slots for an ATAPI/SCSI cdrom,
...@@ -713,15 +720,20 @@ int cdrom_number_of_slots(struct cdrom_device_info *cdi) ...@@ -713,15 +720,20 @@ int cdrom_number_of_slots(struct cdrom_device_info *cdi)
{ {
int status; int status;
int nslots = 1; int nslots = 1;
struct cdrom_changer_info info; struct cdrom_changer_info *info;
cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()\n"); cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()\n");
/* cdrom_read_mech_status requires a valid value for capacity: */ /* cdrom_read_mech_status requires a valid value for capacity: */
cdi->capacity = 0; cdi->capacity = 0;
if ((status = cdrom_read_mech_status(cdi, &info)) == 0) info = kmalloc(sizeof(*info), GFP_KERNEL);
nslots = info.hdr.nslots; if (!info)
return -ENOMEM;
if ((status = cdrom_read_mech_status(cdi, info)) == 0)
nslots = info->hdr.nslots;
kfree(info);
return nslots; return nslots;
} }
...@@ -755,7 +767,7 @@ static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot) ...@@ -755,7 +767,7 @@ static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
{ {
struct cdrom_changer_info info; struct cdrom_changer_info *info;
int curslot; int curslot;
int ret; int ret;
...@@ -771,10 +783,17 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) ...@@ -771,10 +783,17 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
return cdrom_load_unload(cdi, -1); return cdrom_load_unload(cdi, -1);
} }
if ((ret = cdrom_read_mech_status(cdi, &info))) info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if ((ret = cdrom_read_mech_status(cdi, info))) {
kfree(info);
return ret; return ret;
}
curslot = info.hdr.curslot; curslot = info->hdr.curslot;
kfree(info);
if (cdi->use_count > 1 || keeplocked) { if (cdi->use_count > 1 || keeplocked) {
if (slot == CDSL_CURRENT) { if (slot == CDSL_CURRENT) {
...@@ -1502,7 +1521,8 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, ...@@ -1502,7 +1521,8 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
} }
case CDROM_MEDIA_CHANGED: { case CDROM_MEDIA_CHANGED: {
struct cdrom_changer_info info; struct cdrom_changer_info *info;
int changed;
cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
if (!CDROM_CAN(CDC_MEDIA_CHANGED)) if (!CDROM_CAN(CDC_MEDIA_CHANGED))
...@@ -1515,10 +1535,18 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, ...@@ -1515,10 +1535,18 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
if ((unsigned int)arg >= cdi->capacity) if ((unsigned int)arg >= cdi->capacity)
return -EINVAL; return -EINVAL;
if ((ret = cdrom_read_mech_status(cdi, &info))) info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if ((ret = cdrom_read_mech_status(cdi, info))) {
kfree(info);
return ret; return ret;
}
return info.slots[arg].change; changed = info->slots[arg].change;
kfree(info);
return changed;
} }
case CDROM_SET_OPTIONS: { case CDROM_SET_OPTIONS: {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment