Reduce stack usage in sg.c
Subsystems (2)
PATCH 1/1 Reduce stack usage in sg.c
Attempt to reduce stack usage in sg.c.
Used checkstack.pl script to measure stack usage and noted follows:
Before patch:sg_ioctl - 412sg_read - 200
After patch:sg_ioctl - 92sg_read - 96
Thanks,
Rayan
drivers/scsi/sg.c +90 -50
@@ -335,109 +335,143 @@Sg_fd *sfp;Sg_request *srp;int req_pack_id =-1 ; -struct sg_header old_hdr; -sg_io_hdr_t new_hdr; +struct sg_header *old_hdr;sg_io_hdr_t *hp; +int retval =0 ; +if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))return -ENXIO ;SCSI_LOG_TIMEOUT (3 ,printk ("sg_read: %s, count=%d\n" , sdp->disk->disk_name, (int ) count)); -if ((k =verify_area (VERIFY_WRITE , buf, count))) -return k; + old_hdr =kmalloc (SZ_SG_HEADER ,GFP_KERNEL ); +if (!old_hdr) +return -ENOMEM ; +if ((k =verify_area (VERIFY_WRITE , buf, count))) { + retval = k; + goto free_old_hdr; + }if (sfp->force_packid && (count >=SZ_SG_HEADER )) { -if (__copy_from_user (&old_hdr, buf,SZ_SG_HEADER )) -return -EFAULT ; -if (old_hdr.reply_len <0 ) { +if (__copy_from_user (old_hdr, buf,SZ_SG_HEADER )){ + retval = -EFAULT ; + goto free_old_hdr; + } +if (old_hdr->reply_len <0 ) {if (count >=SZ_SG_IO_HDR ) { -if (__copy_from_user - (&new_hdr, buf,SZ_SG_IO_HDR )) -return -EFAULT ; - req_pack_id = new_hdr.pack_id; +sg_io_hdr_t *new_hdr; + new_hdr =kmalloc (SZ_SG_IO_HDR ,GFP_KERNEL ); +if (!new_hdr) { + retval = -ENOMEM ; + goto free_old_hdr; + } + retval =__copy_from_user (new_hdr, buf, +SZ_SG_IO_HDR ); + req_pack_id = new_hdr->pack_id; +kfree (new_hdr); +if (retval) { + retval = -EFAULT ; + goto free_old_hdr; + } } }else - req_pack_id = old_hdr.pack_id; + req_pack_id = old_hdr->pack_id; } srp =sg_get_rq_mark (sfp, req_pack_id);if (!srp) {/* now wait on packet to arrive */ -if (sdp->detached) -return -ENODEV ; -if (filp->f_flags &O_NONBLOCK ) -return -EAGAIN ; +if (sdp->detached) { + retval = -ENODEV ; + goto free_old_hdr; + } +if (filp->f_flags &O_NONBLOCK ) { + retval = -EAGAIN ; + goto free_old_hdr; + }while (1 ) { - res =0 ;/* following is a macro that beats race condition */ + res =0 ;/* following macro beats race condition */ __wait_event_interruptible (sfp->read_wait, - (sdp->detached || (srp =sg_get_rq_mark (sfp, req_pack_id))), - res); -if (sdp->detached) -return -ENODEV ; + (sdp->detached || + (srp =sg_get_rq_mark (sfp, req_pack_id))), + res); +if (sdp->detached) { + retval = -ENODEV ; + goto free_old_hdr; + }if (0 == res)break ; -return res;/* -ERESTARTSYS because signal hit process */ + retval = res;/* -ERESTARTSYS as signal hit process */ + goto free_old_hdr; } } -if (srp->header.interface_id !='\0' ) -return sg_new_read (sfp, buf, count, srp); +if (srp->header.interface_id !='\0' ) { + retval =sg_new_read (sfp, buf, count, srp); + goto free_old_hdr; + } hp = &srp->header; -memset (&old_hdr,0 ,SZ_SG_HEADER ); - old_hdr.reply_len = (int ) hp->timeout; - old_hdr.pack_len = old_hdr.reply_len;/* very old, strange behaviour */ - old_hdr.pack_id = hp->pack_id; - old_hdr.twelve_byte = +memset (old_hdr,0 ,SZ_SG_HEADER ); + old_hdr->reply_len = (int ) hp->timeout; + old_hdr->pack_len = old_hdr->reply_len;/* old, strange behaviour */ + old_hdr->pack_id = hp->pack_id; + old_hdr->twelve_byte = ((srp->data.cmd_opcode >=0xc0 ) && (12 == hp->cmd_len)) ?1 :0 ; - old_hdr.target_status = hp->masked_status; - old_hdr.host_status = hp->host_status; - old_hdr.driver_status = hp->driver_status; + old_hdr->target_status = hp->masked_status; + old_hdr->host_status = hp->host_status; + old_hdr->driver_status = hp->driver_status;if ((CHECK_CONDITION & hp->masked_status) || (DRIVER_SENSE & hp->driver_status)) -memcpy (old_hdr.sense_buffer, srp->sense_b, -sizeof (old_hdr.sense_buffer)); +memcpy (old_hdr->sense_buffer, srp->sense_b, +sizeof (old_hdr->sense_buffer));switch (hp->host_status) {/* This setup of 'result' is for backward compatibility and is best ignored by the user who should use target, host + driver status */ case DID_OK :case DID_PASSTHROUGH :case DID_SOFT_ERROR : - old_hdr.result =0 ; + old_hdr->result =0 ;break ;case DID_NO_CONNECT :case DID_BUS_BUSY :case DID_TIME_OUT : - old_hdr.result =EBUSY ; + old_hdr->result =EBUSY ;break ;case DID_BAD_TARGET :case DID_ABORT :case DID_PARITY :case DID_RESET :case DID_BAD_INTR : - old_hdr.result =EIO ; + old_hdr->result =EIO ;break ;case DID_ERROR : - old_hdr.result = (srp->sense_b[0 ] ==0 && + old_hdr->result = (srp->sense_b[0 ] ==0 && hp->masked_status ==GOOD ) ?0 :EIO ;break ;default : - old_hdr.result =EIO ; + old_hdr->result =EIO ;break ; }/* Now copy the result back to the user buffer. */ if (count >=SZ_SG_HEADER ) { -if (__copy_to_user (buf, &old_hdr,SZ_SG_HEADER )) -return -EFAULT ; +if (__copy_to_user (buf, old_hdr,SZ_SG_HEADER )) { + retval = -EFAULT ; + goto free_old_hdr; + } buf +=SZ_SG_HEADER ; -if (count > old_hdr.reply_len) - count = old_hdr.reply_len; +if (count > old_hdr->reply_len) + count = old_hdr->reply_len;if (count >SZ_SG_HEADER ) {if ((res =sg_read_oxfer (srp, buf, count -SZ_SG_HEADER ))) -return -EFAULT ; + retval = -EFAULT ; + goto free_old_hdr; } }else - count = (old_hdr.result ==0 ) ?0 : -EIO ; + count = (old_hdr->result ==0 ) ?0 : -EIO ;sg_finish_rem_req (srp); -return count; + retval = count; +free_old_hdr: +kfree (old_hdr); +return retval; } static ssize_t
@@ -943,8 +977,11 @@if (result)return result;else { -sg_req_info_t rinfo[SG_MAX_QUEUE ]; -Sg_request *srp; +sg_req_info_t *rinfo; + rinfo =kmalloc (SG_MAX_QUEUE *SZ_SG_REQ_INFO , +GFP_KERNEL ); +if (!rinfo) +return -ENOMEM ;read_lock_irqsave (&sfp->rq_list_lock, iflags);for (srp = sfp->headrp, val =0 ; val <SG_MAX_QUEUE ; ++val, srp = srp ? srp->nextrp : srp) {
@@ -966,8 +1003,11 @@ } }read_unlock_irqrestore (&sfp->rq_list_lock, iflags); -return (__copy_to_user (p, rinfo, -SZ_SG_REQ_INFO *SG_MAX_QUEUE ) ? -EFAULT :0 ); + result =__copy_to_user (p, rinfo,SZ_SG_REQ_INFO * +SG_MAX_QUEUE ); + result = result ? -EFAULT :0 ; +kfree (rinfo); +return result; }case SG_EMULATED_HOST :if (sdp->detached)
Quoted 8 lines · Yum Rayan
Attempt to reduce stack usage in
sg.c.Used checkstack.pl script to measure stack usage and noted follows:
Before patch:
sg_ioctl- 412sg_read- 200
Quoted 8 lines
After patch:
sg_ioctl- 92sg_read- 96Thanks,
RayanSigned-off-by Yum Rayan <[email protected]>
Mostly looks OK to me. However, I would rather see patches against the current -bk instead of 2.6.x.y.
This one does not apply to 2.6.12-rc1-bk1.
AFAIK, development is still primarily done against the linus-bk tree and not the x.y release tree.
Hunk #1 FAILED at 335.
Hunk #2 succeeded at 971 with fuzz 2 (offset -6 lines).
Hunk #3 succeeded at 997 (offset -6 lines).
1 out of 3 hunks FAILED -- saving rejects to file drivers/scsi/sg.c.rej
Quoted 64 lines
diff -Nur
linux-2.6.11.5.orig/drivers/scsi/sg.clinux-2.6.11.5/drivers/scsi/sg.cdrivers/scsi/sg.c +30
-14@@ -335,109 +335,143 @@Sg_fd *sfp;Sg_request *srp;int req_pack_id =-1 ; -struct sg_header old_hdr; -sg_io_hdr_t new_hdr; +struct sg_header *old_hdr;sg_io_hdr_t *hp; +int retval =0 ; +if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))return -ENXIO ;SCSI_LOG_TIMEOUT (3 ,printk ("sg_read: %s, count=%d\n" , sdp->disk->disk_name, (int ) count)); -if ((k =verify_area (VERIFY_WRITE , buf, count))) -return k; + old_hdr =kmalloc (SZ_SG_HEADER ,GFP_KERNEL ); +if (!old_hdr) +return -ENOMEM ; +if ((k =verify_area (VERIFY_WRITE , buf, count))) { + retval = k; + goto free_old_hdr; + }if (sfp->force_packid && (count >=SZ_SG_HEADER )) { -if (__copy_from_user (&old_hdr, buf,SZ_SG_HEADER )) -return -EFAULT ; -if (old_hdr.reply_len <0 ) { +if (__copy_from_user (old_hdr, buf,SZ_SG_HEADER )){ + retval = -EFAULT ; + goto free_old_hdr; + } +if (old_hdr->reply_len <0 ) {if (count >=SZ_SG_IO_HDR ) { -if (__copy_from_user - (&new_hdr, buf,SZ_SG_IO_HDR )) -return -EFAULT ; - req_pack_id = new_hdr.pack_id; +sg_io_hdr_t *new_hdr; + new_hdr =kmalloc (SZ_SG_IO_HDR ,GFP_KERNEL ); +if (!new_hdr) { + retval = -ENOMEM ; + goto free_old_hdr; + } + retval =__copy_from_user (new_hdr, buf, +SZ_SG_IO_HDR ); + req_pack_id = new_hdr->pack_id; +kfree (new_hdr); +if (retval) { + retval = -EFAULT ; + goto free_old_hdr; + } } }else - req_pack_id = old_hdr.pack_id; + req_pack_id = old_hdr->pack_id; } srp =sg_get_rq_mark (sfp, req_pack_id);if (!srp) {/* now wait on packet to arrive */ -if (sdp->detached) -return -ENODEV ;
drivers/scsi/sg.c line 388
Quoted 10 lines
drivers/scsi/sg.c +8
-2-if (filp->f_flags &O_NONBLOCK ) -return -EAGAIN ; +if (sdp->detached) { + retval = -ENODEV ; + goto free_old_hdr; + } +if (filp->f_flags &O_NONBLOCK ) { + retval = -EAGAIN ; + goto free_old_hdr; + }
This patch section looks suspect to me:
Notice that the second '+' sign begins an illegal construct, probably missing an 'if' line or 2.
Or the '+' should be '-'.
Quoted 148 lines
drivers/scsi/sg.c +52
-35while (1 ) { - res =0 ;/* following is a macro that beats race condition */ + res =0 ;/* following macro beats race condition */ __wait_event_interruptible (sfp->read_wait, - (sdp->detached || (srp =sg_get_rq_mark (sfp, req_pack_id))), - res); -if (sdp->detached) -return -ENODEV ; + (sdp->detached || + (srp =sg_get_rq_mark (sfp, req_pack_id))), + res); +if (sdp->detached) { + retval = -ENODEV ; + goto free_old_hdr; + }if (0 == res)break ; -return res;/* -ERESTARTSYS because signal hit process */ + retval = res;/* -ERESTARTSYS as signal hit process */ + goto free_old_hdr; } } -if (srp->header.interface_id !='\0' ) -return sg_new_read (sfp, buf, count, srp); +if (srp->header.interface_id !='\0' ) { + retval =sg_new_read (sfp, buf, count, srp); + goto free_old_hdr; + } hp = &srp->header; -memset (&old_hdr,0 ,SZ_SG_HEADER ); - old_hdr.reply_len = (int ) hp->timeout; - old_hdr.pack_len = old_hdr.reply_len;/* very old, strange behaviour */ - old_hdr.pack_id = hp->pack_id; - old_hdr.twelve_byte = +memset (old_hdr,0 ,SZ_SG_HEADER ); + old_hdr->reply_len = (int ) hp->timeout; + old_hdr->pack_len = old_hdr->reply_len;/* old, strange behaviour */ + old_hdr->pack_id = hp->pack_id; + old_hdr->twelve_byte = ((srp->data.cmd_opcode >=0xc0 ) && (12 == hp->cmd_len)) ?1 :0 ; - old_hdr.target_status = hp->masked_status; - old_hdr.host_status = hp->host_status; - old_hdr.driver_status = hp->driver_status; + old_hdr->target_status = hp->masked_status; + old_hdr->host_status = hp->host_status; + old_hdr->driver_status = hp->driver_status;if ((CHECK_CONDITION & hp->masked_status) || (DRIVER_SENSE & hp->driver_status)) -memcpy (old_hdr.sense_buffer, srp->sense_b, -sizeof (old_hdr.sense_buffer)); +memcpy (old_hdr->sense_buffer, srp->sense_b, +sizeof (old_hdr->sense_buffer));switch (hp->host_status) {/* This setup of 'result' is for backward compatibility and is best ignored by the user who should use target, host + driver status */ case DID_OK :case DID_PASSTHROUGH :case DID_SOFT_ERROR : - old_hdr.result =0 ; + old_hdr->result =0 ;break ;case DID_NO_CONNECT :case DID_BUS_BUSY :case DID_TIME_OUT : - old_hdr.result =EBUSY ; + old_hdr->result =EBUSY ;break ;case DID_BAD_TARGET :case DID_ABORT :case DID_PARITY :case DID_RESET :case DID_BAD_INTR : - old_hdr.result =EIO ; + old_hdr->result =EIO ;break ;case DID_ERROR : - old_hdr.result = (srp->sense_b[0 ] ==0 && + old_hdr->result = (srp->sense_b[0 ] ==0 && hp->masked_status ==GOOD ) ?0 :EIO ;break ;default : - old_hdr.result =EIO ; + old_hdr->result =EIO ;break ; }/* Now copy the result back to the user buffer. */ if (count >=SZ_SG_HEADER ) { -if (__copy_to_user (buf, &old_hdr,SZ_SG_HEADER )) -return -EFAULT ; +if (__copy_to_user (buf, old_hdr,SZ_SG_HEADER )) { + retval = -EFAULT ; + goto free_old_hdr; + } buf +=SZ_SG_HEADER ; -if (count > old_hdr.reply_len) - count = old_hdr.reply_len; +if (count > old_hdr->reply_len) + count = old_hdr->reply_len;if (count >SZ_SG_HEADER ) {if ((res =sg_read_oxfer (srp, buf, count -SZ_SG_HEADER ))) -return -EFAULT ; + retval = -EFAULT ; + goto free_old_hdr; } }else - count = (old_hdr.result ==0 ) ?0 : -EIO ; + count = (old_hdr->result ==0 ) ?0 : -EIO ;sg_finish_rem_req (srp); -return count; + retval = count; +free_old_hdr: +kfree (old_hdr); +return retval; } static ssize_t@@ -943,8 +977,11 @@if (result)return result;else { -sg_req_info_t rinfo[SG_MAX_QUEUE ]; -Sg_request *srp; +sg_req_info_t *rinfo; + rinfo =kmalloc (SG_MAX_QUEUE *SZ_SG_REQ_INFO , +GFP_KERNEL ); +if (!rinfo) +return -ENOMEM ;read_lock_irqsave (&sfp->rq_list_lock, iflags);for (srp = sfp->headrp, val =0 ; val <SG_MAX_QUEUE ; ++val, srp = srp ? srp->nextrp : srp) {@@ -966,8 +1003,11 @@ } }read_unlock_irqrestore (&sfp->rq_list_lock, iflags); -return (__copy_to_user (p, rinfo, -SZ_SG_REQ_INFO *SG_MAX_QUEUE ) ? -EFAULT :0 ); + result =__copy_to_user (p, rinfo,SZ_SG_REQ_INFO * +SG_MAX_QUEUE ); + result = result ? -EFAULT :0 ; +kfree (rinfo); +return result; }case SG_EMULATED_HOST :if (sdp->detached) -
Signature · 1 line
~Randy
Quoted 2 lines
Mostly looks OK to me. However, I would rather see patches against the current -bk instead of 2.6.x.y.
Point noted. Dug around for info on BK. Cloned
http://linux.bkbits.net/linux-2.6 and updated with pull from bk://linux-scsi.bkbits.net/scsi-misc-2.6. Generated bk patch with -hdu option. Hope this new little BK grasshoper got it right :)
Quoted 17 lines
This patch section looks suspect to me:
Notice that the second '+' sign begins an illegal construct, probably missing an 'if' line or 2.
Or the '+' should be '-'.Quoted 12 lines
while (1) {(quoted diff) +5
-5- res = 0; /* following is a macro that beats race condition */ + res = 0; /* following macro beats race condition */ __wait_event_interruptible(sfp->read_wait, - (sdp->detached || (srp = sg_get_rq_mark(sfp, req_pack_id))), - res); - if (sdp->detached) - return -ENODEV; + (sdp->detached || + (srp = sg_get_rq_mark(sfp, req_pack_id))), + res); + if (sdp->detached) {
I adjusted long lines in and around my changes to fit in 80 column editor. The second "+" is not a statement but the second argument of the __wait_event_interruptible macro. So this is verified good.
Reworked patch follows.
Regards,
Rayan
Summary: Reduce stack usage in sg_read() and sg_ioctl()
drivers/scsi/sg.c +95 -55
@@ -330,14 +330,13 @@static ssize_t sg_read (struct file *filp,char __user *buf,size_t count,loff_t * ppos) { -int res;Sg_device *sdp;Sg_fd *sfp;Sg_request *srp;int req_pack_id =-1 ; -struct sg_header old_hdr; -sg_io_hdr_t new_hdr; +struct sg_header *old_hdr;sg_io_hdr_t *hp; +int retval =0 ;if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))return -ENXIO ;
@@ -345,99 +344,131 @@ sdp->disk->disk_name, (int) count));if (!access_ok (VERIFY_WRITE , buf, count))return -EFAULT ; + old_hdr =kmalloc (SZ_SG_HEADER ,GFP_KERNEL ); +if (!old_hdr) +return -ENOMEM ;if (sfp->force_packid && (count >=SZ_SG_HEADER )) { -if (__copy_from_user (&old_hdr, buf,SZ_SG_HEADER )) -return -EFAULT ; -if (old_hdr.reply_len <0 ) { +if (__copy_from_user (old_hdr, buf,SZ_SG_HEADER )) { + retval = -EFAULT ; + goto free_old_hdr; + } +if (old_hdr->reply_len <0 ) {if (count >=SZ_SG_IO_HDR ) { -if (__copy_from_user - (&new_hdr, buf,SZ_SG_IO_HDR )) -return -EFAULT ; - req_pack_id = new_hdr.pack_id; +sg_io_hdr_t *new_hdr; + new_hdr =kmalloc (SZ_SG_IO_HDR ,GFP_KERNEL ); +if (!new_hdr) { + retval = -ENOMEM ; + goto free_old_hdr; + } + retval =__copy_from_user + (new_hdr, buf,SZ_SG_IO_HDR ); + req_pack_id = new_hdr->pack_id; +kfree (new_hdr); +if (retval) { + retval = -EFAULT ; + goto free_old_hdr; + } } }else - req_pack_id = old_hdr.pack_id; + req_pack_id = old_hdr->pack_id; } srp =sg_get_rq_mark (sfp, req_pack_id);if (!srp) {/* now wait on packet to arrive */ -if (sdp->detached) -return -ENODEV ; -if (filp->f_flags &O_NONBLOCK ) -return -EAGAIN ; +if (sdp->detached) { + retval = -ENODEV ; + goto free_old_hdr; + } +if (filp->f_flags &O_NONBLOCK ) { + retval = -EAGAIN ; + goto free_old_hdr; + }while (1 ) { - res =0 ;/* following is a macro that beats race condition */ + retval =0 ;/* following macro beats race condition */ __wait_event_interruptible (sfp->read_wait, - (sdp->detached || (srp =sg_get_rq_mark (sfp, req_pack_id))), - res); -if (sdp->detached) -return -ENODEV ; -if (0 == res) + (sdp->detached || + (srp =sg_get_rq_mark (sfp, req_pack_id))), + retval); +if (sdp->detached) { + retval = -ENODEV ; + goto free_old_hdr; + } +if (0 == retval)break ; -return res;/* -ERESTARTSYS because signal hit process */ + +/* -ERESTARTSYS as signal hit process */ + goto free_old_hdr; } } -if (srp->header.interface_id !='\0' ) -return sg_new_read (sfp, buf, count, srp); +if (srp->header.interface_id !='\0' ) { + retval =sg_new_read (sfp, buf, count, srp); + goto free_old_hdr; + } hp = &srp->header; -memset (&old_hdr,0 ,SZ_SG_HEADER ); - old_hdr.reply_len = (int ) hp->timeout; - old_hdr.pack_len = old_hdr.reply_len;/* very old, strange behaviour */ - old_hdr.pack_id = hp->pack_id; - old_hdr.twelve_byte = +memset (old_hdr,0 ,SZ_SG_HEADER ); + old_hdr->reply_len = (int ) hp->timeout; + old_hdr->pack_len = old_hdr->reply_len;/* old, strange behaviour */ + old_hdr->pack_id = hp->pack_id; + old_hdr->twelve_byte = ((srp->data.cmd_opcode >=0xc0 ) && (12 == hp->cmd_len)) ?1 :0 ; - old_hdr.target_status = hp->masked_status; - old_hdr.host_status = hp->host_status; - old_hdr.driver_status = hp->driver_status; + old_hdr->target_status = hp->masked_status; + old_hdr->host_status = hp->host_status; + old_hdr->driver_status = hp->driver_status;if ((CHECK_CONDITION & hp->masked_status) || (DRIVER_SENSE & hp->driver_status)) -memcpy (old_hdr.sense_buffer, srp->sense_b, -sizeof (old_hdr.sense_buffer)); +memcpy (old_hdr->sense_buffer, srp->sense_b, +sizeof (old_hdr->sense_buffer));switch (hp->host_status) {/* This setup of 'result' is for backward compatibility and is best ignored by the user who should use target, host + driver status */ case DID_OK :case DID_PASSTHROUGH :case DID_SOFT_ERROR : - old_hdr.result =0 ; + old_hdr->result =0 ;break ;case DID_NO_CONNECT :case DID_BUS_BUSY :case DID_TIME_OUT : - old_hdr.result =EBUSY ; + old_hdr->result =EBUSY ;break ;case DID_BAD_TARGET :case DID_ABORT :case DID_PARITY :case DID_RESET :case DID_BAD_INTR : - old_hdr.result =EIO ; + old_hdr->result =EIO ;break ;case DID_ERROR : - old_hdr.result = (srp->sense_b[0 ] ==0 && + old_hdr->result = (srp->sense_b[0 ] ==0 && hp->masked_status ==GOOD ) ?0 :EIO ;break ;default : - old_hdr.result =EIO ; + old_hdr->result =EIO ;break ; }/* Now copy the result back to the user buffer. */ if (count >=SZ_SG_HEADER ) { -if (__copy_to_user (buf, &old_hdr,SZ_SG_HEADER )) -return -EFAULT ; +if (__copy_to_user (buf, old_hdr,SZ_SG_HEADER )) { + retval = -EFAULT ; + goto free_old_hdr; + } buf +=SZ_SG_HEADER ; -if (count > old_hdr.reply_len) - count = old_hdr.reply_len; +if (count > old_hdr->reply_len) + count = old_hdr->reply_len;if (count >SZ_SG_HEADER ) { -if ((res = -sg_read_oxfer (srp, buf, count -SZ_SG_HEADER ))) -return -EFAULT ; +if (sg_read_oxfer (srp, buf, count -SZ_SG_HEADER )) { + retval = -EFAULT ; + goto free_old_hdr; + } } }else - count = (old_hdr.result ==0 ) ?0 : -EIO ; + count = (old_hdr->result ==0 ) ?0 : -EIO ;sg_finish_rem_req (srp); -return count; + retval = count; +free_old_hdr: +kfree (old_hdr); +return retval; } static ssize_t
@@ -937,8 +968,11 @@if (!access_ok (VERIFY_WRITE , p,SZ_SG_REQ_INFO *SG_MAX_QUEUE ))return -EFAULT ;else { -sg_req_info_t rinfo[SG_MAX_QUEUE ]; -Sg_request *srp; +sg_req_info_t *rinfo; + rinfo =kmalloc (SZ_SG_REQ_INFO *SG_MAX_QUEUE , +GFP_KERNEL ); +if (!rinfo) +return -ENOMEM ;read_lock_irqsave (&sfp->rq_list_lock, iflags);for (srp = sfp->headrp, val =0 ; val <SG_MAX_QUEUE ; ++val, srp = srp ? srp->nextrp : srp) {
@@ -954,14 +988,20 @@jiffies_to_msecs ( jiffies - srp->header.duration); rinfo[val].orphan = srp->orphan; - rinfo[val].sg_io_owned = srp->sg_io_owned; - rinfo[val].pack_id = srp->header.pack_id; - rinfo[val].usr_ptr = srp->header.usr_ptr; + rinfo[val].sg_io_owned = + srp->sg_io_owned; + rinfo[val].pack_id = + srp->header.pack_id; + rinfo[val].usr_ptr = + srp->header.usr_ptr; } }read_unlock_irqrestore (&sfp->rq_list_lock, iflags); -return (__copy_to_user (p, rinfo, -SZ_SG_REQ_INFO *SG_MAX_QUEUE ) ? -EFAULT :0 ); + result =__copy_to_user (p, rinfo, +SZ_SG_REQ_INFO *SG_MAX_QUEUE ); + result = result ? -EFAULT :0 ; +kfree (rinfo); +return result; }case SG_EMULATED_HOST :if (sdp->detached)