Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] sg: fix incorrect last scatg length

For certain LLDs the sg driver can cause on oops
when the transfer length is large and not a
multiple of PAGE_SIZE.

ChangeLog:
- correct the length of the last scatter gather
list element.
- fix some printk()s that have the wrong function
name.

Signed-off-by: Douglas Gilbert <dougg@torque.net>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

authored by

Douglas Gilbert and committed by
James Bottomley
7ca63cb4 4039c30e

+13 -12
+13 -12
drivers/scsi/sg.c
··· 60 60 61 61 #ifdef CONFIG_SCSI_PROC_FS 62 62 #include <linux/proc_fs.h> 63 - static char *sg_version_date = "20060920"; 63 + static char *sg_version_date = "20061027"; 64 64 65 65 static int sg_proc_init(void); 66 66 static void sg_proc_cleanup(void); ··· 710 710 (int) cmnd[0], (int) hp->cmd_len)); 711 711 712 712 if ((k = sg_start_req(srp))) { 713 - SCSI_LOG_TIMEOUT(1, printk("sg_write: start_req err=%d\n", k)); 713 + SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k)); 714 714 sg_finish_rem_req(srp); 715 715 return k; /* probably out of space --> ENOMEM */ 716 716 } 717 717 if ((k = sg_write_xfer(srp))) { 718 - SCSI_LOG_TIMEOUT(1, printk("sg_write: write_xfer, bad address\n")); 718 + SCSI_LOG_TIMEOUT(1, printk("sg_common_write: write_xfer, bad address\n")); 719 719 sg_finish_rem_req(srp); 720 720 return k; 721 721 } ··· 746 746 hp->dxfer_len, srp->data.k_use_sg, timeout, 747 747 SG_DEFAULT_RETRIES, srp, sg_cmd_done, 748 748 GFP_ATOMIC)) { 749 - SCSI_LOG_TIMEOUT(1, printk("sg_write: scsi_execute_async failed\n")); 749 + SCSI_LOG_TIMEOUT(1, printk("sg_common_write: scsi_execute_async failed\n")); 750 750 /* 751 751 * most likely out of mem, but could also be a bad map 752 752 */ ··· 1283 1283 sg_finish_rem_req(srp); 1284 1284 srp = NULL; 1285 1285 if (NULL == sfp->headrp) { 1286 - SCSI_LOG_TIMEOUT(1, printk("sg...bh: already closed, final cleanup\n")); 1286 + SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, final cleanup\n")); 1287 1287 if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */ 1288 1288 scsi_device_put(sdp->device); 1289 1289 } ··· 1512 1512 POLL_HUP); 1513 1513 } 1514 1514 } 1515 - SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k)); 1515 + SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", k)); 1516 1516 if (NULL == sdp->headfp) { 1517 1517 sg_dev_arr[k] = NULL; 1518 1518 } 1519 1519 } else { /* nothing active, simple case */ 1520 - SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k)); 1520 + SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", k)); 1521 1521 sg_dev_arr[k] = NULL; 1522 1522 } 1523 1523 sg_nr_dev--; ··· 1876 1876 } 1877 1877 } 1878 1878 sg->page = p; 1879 - sg->length = ret_sz; 1879 + sg->length = (ret_sz > num) ? num : ret_sz; 1880 1880 1881 - SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n", 1882 - k, p, ret_sz)); 1881 + SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " 1882 + "ret_sz=%d\n", k, num, ret_sz)); 1883 1883 } /* end of for loop */ 1884 1884 1885 1885 schp->k_use_sg = k; 1886 - SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz)); 1886 + SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, " 1887 + "rem_sz=%d\n", k, rem_sz)); 1887 1888 1888 1889 schp->bufflen = blk_size; 1889 1890 if (rem_sz > 0) /* must have failed */ ··· 2015 2014 for (k = 0; (k < schp->k_use_sg) && sg->page; 2016 2015 ++k, ++sg) { 2017 2016 SCSI_LOG_TIMEOUT(5, printk( 2018 - "sg_remove_scat: k=%d, a=0x%p, len=%d\n", 2017 + "sg_remove_scat: k=%d, pg=0x%p, len=%d\n", 2019 2018 k, sg->page, sg->length)); 2020 2019 sg_page_free(sg->page, sg->length); 2021 2020 }