diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh.c | 9 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 23 | ||||
-rw-r--r-- | drivers/scsi/pmcraid.c | 3 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 24 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 16 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 19 |
6 files changed, 49 insertions, 45 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 564e6ecd17c2..0119b8147797 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c | |||
@@ -394,12 +394,14 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) | |||
394 | unsigned long flags; | 394 | unsigned long flags; |
395 | struct scsi_device *sdev; | 395 | struct scsi_device *sdev; |
396 | struct scsi_device_handler *scsi_dh = NULL; | 396 | struct scsi_device_handler *scsi_dh = NULL; |
397 | struct device *dev = NULL; | ||
397 | 398 | ||
398 | spin_lock_irqsave(q->queue_lock, flags); | 399 | spin_lock_irqsave(q->queue_lock, flags); |
399 | sdev = q->queuedata; | 400 | sdev = q->queuedata; |
400 | if (sdev && sdev->scsi_dh_data) | 401 | if (sdev && sdev->scsi_dh_data) |
401 | scsi_dh = sdev->scsi_dh_data->scsi_dh; | 402 | scsi_dh = sdev->scsi_dh_data->scsi_dh; |
402 | if (!scsi_dh || !get_device(&sdev->sdev_gendev) || | 403 | dev = get_device(&sdev->sdev_gendev); |
404 | if (!scsi_dh || !dev || | ||
403 | sdev->sdev_state == SDEV_CANCEL || | 405 | sdev->sdev_state == SDEV_CANCEL || |
404 | sdev->sdev_state == SDEV_DEL) | 406 | sdev->sdev_state == SDEV_DEL) |
405 | err = SCSI_DH_NOSYS; | 407 | err = SCSI_DH_NOSYS; |
@@ -410,12 +412,13 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) | |||
410 | if (err) { | 412 | if (err) { |
411 | if (fn) | 413 | if (fn) |
412 | fn(data, err); | 414 | fn(data, err); |
413 | return err; | 415 | goto out; |
414 | } | 416 | } |
415 | 417 | ||
416 | if (scsi_dh->activate) | 418 | if (scsi_dh->activate) |
417 | err = scsi_dh->activate(sdev, fn, data); | 419 | err = scsi_dh->activate(sdev, fn, data); |
418 | put_device(&sdev->sdev_gendev); | 420 | out: |
421 | put_device(dev); | ||
419 | return err; | 422 | return err; |
420 | } | 423 | } |
421 | EXPORT_SYMBOL_GPL(scsi_dh_activate); | 424 | EXPORT_SYMBOL_GPL(scsi_dh_activate); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 1c6d2b405eef..d72f1f2b1392 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
@@ -688,6 +688,13 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
688 | goto out; | 688 | goto out; |
689 | } | 689 | } |
690 | 690 | ||
691 | /* Check for overflow and wraparound */ | ||
692 | if (karg.data_sge_offset * 4 > ioc->request_sz || | ||
693 | karg.data_sge_offset > (UINT_MAX / 4)) { | ||
694 | ret = -EINVAL; | ||
695 | goto out; | ||
696 | } | ||
697 | |||
691 | /* copy in request message frame from user */ | 698 | /* copy in request message frame from user */ |
692 | if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { | 699 | if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { |
693 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, | 700 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, |
@@ -1963,7 +1970,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1963 | Mpi2DiagBufferPostReply_t *mpi_reply; | 1970 | Mpi2DiagBufferPostReply_t *mpi_reply; |
1964 | int rc, i; | 1971 | int rc, i; |
1965 | u8 buffer_type; | 1972 | u8 buffer_type; |
1966 | unsigned long timeleft; | 1973 | unsigned long timeleft, request_size, copy_size; |
1967 | u16 smid; | 1974 | u16 smid; |
1968 | u16 ioc_status; | 1975 | u16 ioc_status; |
1969 | u8 issue_reset = 0; | 1976 | u8 issue_reset = 0; |
@@ -1999,6 +2006,8 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1999 | return -ENOMEM; | 2006 | return -ENOMEM; |
2000 | } | 2007 | } |
2001 | 2008 | ||
2009 | request_size = ioc->diag_buffer_sz[buffer_type]; | ||
2010 | |||
2002 | if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { | 2011 | if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { |
2003 | printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " | 2012 | printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " |
2004 | "or bytes_to_read are not 4 byte aligned\n", ioc->name, | 2013 | "or bytes_to_read are not 4 byte aligned\n", ioc->name, |
@@ -2006,13 +2015,23 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
2006 | return -EINVAL; | 2015 | return -EINVAL; |
2007 | } | 2016 | } |
2008 | 2017 | ||
2018 | if (karg.starting_offset > request_size) | ||
2019 | return -EINVAL; | ||
2020 | |||
2009 | diag_data = (void *)(request_data + karg.starting_offset); | 2021 | diag_data = (void *)(request_data + karg.starting_offset); |
2010 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " | 2022 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " |
2011 | "offset(%d), sz(%d)\n", ioc->name, __func__, | 2023 | "offset(%d), sz(%d)\n", ioc->name, __func__, |
2012 | diag_data, karg.starting_offset, karg.bytes_to_read)); | 2024 | diag_data, karg.starting_offset, karg.bytes_to_read)); |
2013 | 2025 | ||
2026 | /* Truncate data on requests that are too large */ | ||
2027 | if ((diag_data + karg.bytes_to_read < diag_data) || | ||
2028 | (diag_data + karg.bytes_to_read > request_data + request_size)) | ||
2029 | copy_size = request_size - karg.starting_offset; | ||
2030 | else | ||
2031 | copy_size = karg.bytes_to_read; | ||
2032 | |||
2014 | if (copy_to_user((void __user *)uarg->diagnostic_data, | 2033 | if (copy_to_user((void __user *)uarg->diagnostic_data, |
2015 | diag_data, karg.bytes_to_read)) { | 2034 | diag_data, copy_size)) { |
2016 | printk(MPT2SAS_ERR_FMT "%s: Unable to write " | 2035 | printk(MPT2SAS_ERR_FMT "%s: Unable to write " |
2017 | "mpt_diag_read_buffer_t data @ %p\n", ioc->name, | 2036 | "mpt_diag_read_buffer_t data @ %p\n", ioc->name, |
2018 | __func__, diag_data); | 2037 | __func__, diag_data); |
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 96d5ad0c1e42..7f636b118287 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c | |||
@@ -3814,6 +3814,9 @@ static long pmcraid_ioctl_passthrough( | |||
3814 | rc = -EFAULT; | 3814 | rc = -EFAULT; |
3815 | goto out_free_buffer; | 3815 | goto out_free_buffer; |
3816 | } | 3816 | } |
3817 | } else if (request_size < 0) { | ||
3818 | rc = -EINVAL; | ||
3819 | goto out_free_buffer; | ||
3817 | } | 3820 | } |
3818 | 3821 | ||
3819 | /* check if we have any additional command parameters */ | 3822 | /* check if we have any additional command parameters */ |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ab55c2fa7ce2..0bac91e72370 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -400,10 +400,15 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost) | |||
400 | static void scsi_run_queue(struct request_queue *q) | 400 | static void scsi_run_queue(struct request_queue *q) |
401 | { | 401 | { |
402 | struct scsi_device *sdev = q->queuedata; | 402 | struct scsi_device *sdev = q->queuedata; |
403 | struct Scsi_Host *shost = sdev->host; | 403 | struct Scsi_Host *shost; |
404 | LIST_HEAD(starved_list); | 404 | LIST_HEAD(starved_list); |
405 | unsigned long flags; | 405 | unsigned long flags; |
406 | 406 | ||
407 | /* if the device is dead, sdev will be NULL, so no queue to run */ | ||
408 | if (!sdev) | ||
409 | return; | ||
410 | |||
411 | shost = sdev->host; | ||
407 | if (scsi_target(sdev)->single_lun) | 412 | if (scsi_target(sdev)->single_lun) |
408 | scsi_single_lun_run(sdev); | 413 | scsi_single_lun_run(sdev); |
409 | 414 | ||
@@ -411,8 +416,6 @@ static void scsi_run_queue(struct request_queue *q) | |||
411 | list_splice_init(&shost->starved_list, &starved_list); | 416 | list_splice_init(&shost->starved_list, &starved_list); |
412 | 417 | ||
413 | while (!list_empty(&starved_list)) { | 418 | while (!list_empty(&starved_list)) { |
414 | int flagset; | ||
415 | |||
416 | /* | 419 | /* |
417 | * As long as shost is accepting commands and we have | 420 | * As long as shost is accepting commands and we have |
418 | * starved queues, call blk_run_queue. scsi_request_fn | 421 | * starved queues, call blk_run_queue. scsi_request_fn |
@@ -435,20 +438,7 @@ static void scsi_run_queue(struct request_queue *q) | |||
435 | continue; | 438 | continue; |
436 | } | 439 | } |
437 | 440 | ||
438 | spin_unlock(shost->host_lock); | 441 | blk_run_queue_async(sdev->request_queue); |
439 | |||
440 | spin_lock(sdev->request_queue->queue_lock); | ||
441 | flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) && | ||
442 | !test_bit(QUEUE_FLAG_REENTER, | ||
443 | &sdev->request_queue->queue_flags); | ||
444 | if (flagset) | ||
445 | queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue); | ||
446 | __blk_run_queue(sdev->request_queue); | ||
447 | if (flagset) | ||
448 | queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue); | ||
449 | spin_unlock(sdev->request_queue->queue_lock); | ||
450 | |||
451 | spin_lock(shost->host_lock); | ||
452 | } | 442 | } |
453 | /* put any unprocessed entries back */ | 443 | /* put any unprocessed entries back */ |
454 | list_splice(&starved_list, &shost->starved_list); | 444 | list_splice(&starved_list, &shost->starved_list); |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index e44ff64233fd..e63912510fb9 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -322,14 +322,8 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) | |||
322 | kfree(evt); | 322 | kfree(evt); |
323 | } | 323 | } |
324 | 324 | ||
325 | if (sdev->request_queue) { | 325 | /* NULL queue means the device can't be used */ |
326 | sdev->request_queue->queuedata = NULL; | 326 | sdev->request_queue = NULL; |
327 | /* user context needed to free queue */ | ||
328 | scsi_free_queue(sdev->request_queue); | ||
329 | /* temporary expedient, try to catch use of queue lock | ||
330 | * after free of sdev */ | ||
331 | sdev->request_queue = NULL; | ||
332 | } | ||
333 | 327 | ||
334 | scsi_target_reap(scsi_target(sdev)); | 328 | scsi_target_reap(scsi_target(sdev)); |
335 | 329 | ||
@@ -937,6 +931,12 @@ void __scsi_remove_device(struct scsi_device *sdev) | |||
937 | if (sdev->host->hostt->slave_destroy) | 931 | if (sdev->host->hostt->slave_destroy) |
938 | sdev->host->hostt->slave_destroy(sdev); | 932 | sdev->host->hostt->slave_destroy(sdev); |
939 | transport_destroy_device(dev); | 933 | transport_destroy_device(dev); |
934 | |||
935 | /* cause the request function to reject all I/O requests */ | ||
936 | sdev->request_queue->queuedata = NULL; | ||
937 | |||
938 | /* Freeing the queue signals to block that we're done */ | ||
939 | scsi_free_queue(sdev->request_queue); | ||
940 | put_device(dev); | 940 | put_device(dev); |
941 | } | 941 | } |
942 | 942 | ||
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 28c33506e4ad..815069d13f9b 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -3816,28 +3816,17 @@ fail_host_msg: | |||
3816 | static void | 3816 | static void |
3817 | fc_bsg_goose_queue(struct fc_rport *rport) | 3817 | fc_bsg_goose_queue(struct fc_rport *rport) |
3818 | { | 3818 | { |
3819 | int flagset; | ||
3820 | unsigned long flags; | ||
3821 | |||
3822 | if (!rport->rqst_q) | 3819 | if (!rport->rqst_q) |
3823 | return; | 3820 | return; |
3824 | 3821 | ||
3822 | /* | ||
3823 | * This get/put dance makes no sense | ||
3824 | */ | ||
3825 | get_device(&rport->dev); | 3825 | get_device(&rport->dev); |
3826 | 3826 | blk_run_queue_async(rport->rqst_q); | |
3827 | spin_lock_irqsave(rport->rqst_q->queue_lock, flags); | ||
3828 | flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && | ||
3829 | !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); | ||
3830 | if (flagset) | ||
3831 | queue_flag_set(QUEUE_FLAG_REENTER, rport->rqst_q); | ||
3832 | __blk_run_queue(rport->rqst_q); | ||
3833 | if (flagset) | ||
3834 | queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); | ||
3835 | spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags); | ||
3836 | |||
3837 | put_device(&rport->dev); | 3827 | put_device(&rport->dev); |
3838 | } | 3828 | } |
3839 | 3829 | ||
3840 | |||
3841 | /** | 3830 | /** |
3842 | * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD | 3831 | * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD |
3843 | * @q: rport request queue | 3832 | * @q: rport request queue |