From: Greg Kroah-Hartman Date: Mon, 26 Aug 2013 18:56:04 +0000 (-0700) Subject: 3.0-stable patches X-Git-Tag: v3.0.94~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=75b6234d31537058044d9952a1d95fa2e382f835;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch libata-apply-behavioral-quirks-to-sil3826-pmp.patch scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch --- diff --git a/queue-3.0/hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch b/queue-3.0/hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch new file mode 100644 index 00000000000..ca5359f9b81 --- /dev/null +++ b/queue-3.0/hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch @@ -0,0 +1,34 @@ +From 909bd5926d474e275599094acad986af79671ac9 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 9 Aug 2013 12:52:31 +0300 +Subject: Hostap: copying wrong data prism2_ioctl_giwaplist() + +From: Dan Carpenter + +commit 909bd5926d474e275599094acad986af79671ac9 upstream. + +We want the data stored in "addr" and "qual", but the extra ampersands +mean we are copying stack data instead. + +Signed-off-by: Dan Carpenter +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/hostap/hostap_ioctl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/hostap/hostap_ioctl.c ++++ b/drivers/net/wireless/hostap/hostap_ioctl.c +@@ -521,9 +521,9 @@ static int prism2_ioctl_giwaplist(struct + + data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1); + +- memcpy(extra, &addr, sizeof(struct sockaddr) * data->length); ++ memcpy(extra, addr, sizeof(struct sockaddr) * data->length); + data->flags = 1; /* has quality information */ +- memcpy(extra + sizeof(struct sockaddr) * data->length, &qual, ++ memcpy(extra + sizeof(struct sockaddr) * data->length, qual, + sizeof(struct iw_quality) * data->length); + + kfree(addr); diff --git a/queue-3.0/libata-apply-behavioral-quirks-to-sil3826-pmp.patch b/queue-3.0/libata-apply-behavioral-quirks-to-sil3826-pmp.patch new file mode 100644 index 00000000000..a7fd1f8198e --- /dev/null +++ b/queue-3.0/libata-apply-behavioral-quirks-to-sil3826-pmp.patch @@ -0,0 +1,66 @@ +From 8ffff94d20b7eb446e848e0046107d51b17a20a8 Mon Sep 17 00:00:00 2001 +From: Terry Suereth +Date: Sat, 17 Aug 2013 15:53:12 -0400 +Subject: libata: apply behavioral quirks to sil3826 PMP + +From: Terry Suereth + +commit 8ffff94d20b7eb446e848e0046107d51b17a20a8 upstream. + +Fixing support for the Silicon Image 3826 port multiplier, by applying +to it the same quirks applied to the Silicon Image 3726. Specifically +fixes the repeated timeout/reset process which previously afflicted +the 3726, as described from line 290. Slightly based on notes from: + +https://bugzilla.redhat.com/show_bug.cgi?id=890237 + +Signed-off-by: Terry Suereth +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-pmp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/ata/libata-pmp.c ++++ b/drivers/ata/libata-pmp.c +@@ -288,24 +288,24 @@ static int sata_pmp_configure(struct ata + + /* Disable sending Early R_OK. + * With "cached read" HDD testing and multiple ports busy on a SATA +- * host controller, 3726 PMP will very rarely drop a deferred ++ * host controller, 3x26 PMP will very rarely drop a deferred + * R_OK that was intended for the host. Symptom will be all + * 5 drives under test will timeout, get reset, and recover. + */ +- if (vendor == 0x1095 && devid == 0x3726) { ++ if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { + u32 reg; + + err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®); + if (err_mask) { + rc = -EIO; +- reason = "failed to read Sil3726 Private Register"; ++ reason = "failed to read Sil3x26 Private Register"; + goto fail; + } + reg &= ~0x1; + err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg); + if (err_mask) { + rc = -EIO; +- reason = "failed to write Sil3726 Private Register"; ++ reason = "failed to write Sil3x26 Private Register"; + goto fail; + } + } +@@ -383,8 +383,8 @@ static void sata_pmp_quirks(struct ata_p + u16 devid = sata_pmp_gscr_devid(gscr); + struct ata_link *link; + +- if (vendor == 0x1095 && devid == 0x3726) { +- /* sil3726 quirks */ ++ if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { ++ /* sil3x26 quirks */ + ata_for_each_link(link, ap, EDGE) { + /* link reports offline after LPM */ + link->flags |= ATA_LFLAG_NO_LPM; diff --git a/queue-3.0/scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch b/queue-3.0/scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch new file mode 100644 index 00000000000..dd7620b1ec3 --- /dev/null +++ b/queue-3.0/scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch @@ -0,0 +1,158 @@ +From d79ff142624e1be080ad8d09101f7004d79c36e1 Mon Sep 17 00:00:00 2001 +From: Martin Peschke +Date: Thu, 22 Aug 2013 17:45:36 +0200 +Subject: SCSI: zfcp: fix lock imbalance by reworking request queue locking + +From: Martin Peschke + +commit d79ff142624e1be080ad8d09101f7004d79c36e1 upstream. + +This patch adds wait_event_interruptible_lock_irq_timeout(), which is a +straight-forward descendant of wait_event_interruptible_timeout() and +wait_event_interruptible_lock_irq(). + +The zfcp driver used to call wait_event_interruptible_timeout() +in combination with some intricate and error-prone locking. Using +wait_event_interruptible_lock_irq_timeout() as a replacement +nicely cleans up that locking. + +This rework removes a situation that resulted in a locking imbalance +in zfcp_qdio_sbal_get(): + +BUG: workqueue leaked lock or atomic: events/1/0xffffff00/10 + last function: zfcp_fc_wka_port_offline+0x0/0xa0 [zfcp] + +It was introduced by commit c2af7545aaff3495d9bf9a7608c52f0af86fb194 +"[SCSI] zfcp: Do not wait for SBALs on stopped queue", which had a new +code path related to ZFCP_STATUS_ADAPTER_QDIOUP that took an early exit +without a required lock being held. The problem occured when a +special, non-SCSI I/O request was being submitted in process context, +when the adapter's queues had been torn down. In this case the bug +surfaced when the Fibre Channel port connection for a well-known address +was closed during a concurrent adapter shut-down procedure, which is a +rare constellation. + +This patch also fixes these warnings from the sparse tool (make C=1): + +drivers/s390/scsi/zfcp_qdio.c:224:12: warning: context imbalance in + 'zfcp_qdio_sbal_check' - wrong count at exit +drivers/s390/scsi/zfcp_qdio.c:244:5: warning: context imbalance in + 'zfcp_qdio_sbal_get' - unexpected unlock + +Last but not least, we get rid of that crappy lock-unlock-lock +sequence at the beginning of the critical section. + +It is okay to call zfcp_erp_adapter_reopen() with req_q_lock held. + +Reported-by: Mikulas Patocka +Reported-by: Heiko Carstens +Signed-off-by: Martin Peschke +Signed-off-by: Steffen Maier +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_qdio.c | 8 +---- + include/linux/wait.h | 57 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 59 insertions(+), 6 deletions(-) + +--- a/drivers/s390/scsi/zfcp_qdio.c ++++ b/drivers/s390/scsi/zfcp_qdio.c +@@ -199,11 +199,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_ + + static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) + { +- spin_lock_irq(&qdio->req_q_lock); + if (atomic_read(&qdio->req_q_free) || + !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) + return 1; +- spin_unlock_irq(&qdio->req_q_lock); + return 0; + } + +@@ -221,9 +219,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio + { + long ret; + +- spin_unlock_irq(&qdio->req_q_lock); +- ret = wait_event_interruptible_timeout(qdio->req_q_wq, +- zfcp_qdio_sbal_check(qdio), 5 * HZ); ++ ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq, ++ zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ); + + if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) + return -EIO; +@@ -237,7 +234,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio + zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1"); + } + +- spin_lock_irq(&qdio->req_q_lock); + return -EIO; + } + +--- a/include/linux/wait.h ++++ b/include/linux/wait.h +@@ -530,6 +530,63 @@ do { \ + ? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1)) + + ++#define __wait_event_interruptible_lock_irq_timeout(wq, condition, \ ++ lock, ret) \ ++do { \ ++ DEFINE_WAIT(__wait); \ ++ \ ++ for (;;) { \ ++ prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ ++ if (condition) \ ++ break; \ ++ if (signal_pending(current)) { \ ++ ret = -ERESTARTSYS; \ ++ break; \ ++ } \ ++ spin_unlock_irq(&lock); \ ++ ret = schedule_timeout(ret); \ ++ spin_lock_irq(&lock); \ ++ if (!ret) \ ++ break; \ ++ } \ ++ finish_wait(&wq, &__wait); \ ++} while (0) ++ ++/** ++ * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses. ++ * The condition is checked under the lock. This is expected ++ * to be called with the lock taken. ++ * @wq: the waitqueue to wait on ++ * @condition: a C expression for the event to wait for ++ * @lock: a locked spinlock_t, which will be released before schedule() ++ * and reacquired afterwards. ++ * @timeout: timeout, in jiffies ++ * ++ * The process is put to sleep (TASK_INTERRUPTIBLE) until the ++ * @condition evaluates to true or signal is received. The @condition is ++ * checked each time the waitqueue @wq is woken up. ++ * ++ * wake_up() has to be called after changing any variable that could ++ * change the result of the wait condition. ++ * ++ * This is supposed to be called while holding the lock. The lock is ++ * dropped before going to sleep and is reacquired afterwards. ++ * ++ * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it ++ * was interrupted by a signal, and the remaining jiffies otherwise ++ * if the condition evaluated to true before the timeout elapsed. ++ */ ++#define wait_event_interruptible_lock_irq_timeout(wq, condition, lock, \ ++ timeout) \ ++({ \ ++ int __ret = timeout; \ ++ \ ++ if (!(condition)) \ ++ __wait_event_interruptible_lock_irq_timeout( \ ++ wq, condition, lock, __ret); \ ++ __ret; \ ++}) ++ + + #define __wait_event_killable(wq, condition, ret) \ + do { \ diff --git a/queue-3.0/series b/queue-3.0/series index 2f2a79fa179..6f9d602d274 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -3,3 +3,7 @@ xen-events-initialize-local-per-cpu-mask-for-all-possible-events.patch of-fdt-fix-memory-initialization-for-expanded-dt.patch nilfs2-remove-double-bio_put-in-nilfs_end_bio_write-for-bio_eopnotsupp-error.patch nilfs2-fix-issue-with-counting-number-of-bio-requests-for-bio_eopnotsupp-error-detection.patch +hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch +libata-apply-behavioral-quirks-to-sil3826-pmp.patch +scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch +zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch diff --git a/queue-3.0/zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch b/queue-3.0/zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch new file mode 100644 index 00000000000..4abbbab5de1 --- /dev/null +++ b/queue-3.0/zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch @@ -0,0 +1,170 @@ +From 924dd584b198a58aa7cb3efefd8a03326550ce8f Mon Sep 17 00:00:00 2001 +From: Martin Peschke +Date: Thu, 22 Aug 2013 17:45:37 +0200 +Subject: SCSI: zfcp: fix schedule-inside-lock in scsi_device list loops + +From: Martin Peschke + +commit 924dd584b198a58aa7cb3efefd8a03326550ce8f upstream. + +BUG: sleeping function called from invalid context at kernel/workqueue.c:2752 +in_atomic(): 1, irqs_disabled(): 1, pid: 360, name: zfcperp0.0.1700 +CPU: 1 Not tainted 3.9.3+ #69 +Process zfcperp0.0.1700 (pid: 360, task: 0000000075b7e080, ksp: 000000007476bc30) + +Call Trace: +([<00000000001165de>] show_trace+0x106/0x154) + [<00000000001166a0>] show_stack+0x74/0xf4 + [<00000000006ff646>] dump_stack+0xc6/0xd4 + [<000000000017f3a0>] __might_sleep+0x128/0x148 + [<000000000015ece8>] flush_work+0x54/0x1f8 + [<00000000001630de>] __cancel_work_timer+0xc6/0x128 + [<00000000005067ac>] scsi_device_dev_release_usercontext+0x164/0x23c + [<0000000000161816>] execute_in_process_context+0x96/0xa8 + [<00000000004d33d8>] device_release+0x60/0xc0 + [<000000000048af48>] kobject_release+0xa8/0x1c4 + [<00000000004f4bf2>] __scsi_iterate_devices+0xfa/0x130 + [<000003ff801b307a>] zfcp_erp_strategy+0x4da/0x1014 [zfcp] + [<000003ff801b3caa>] zfcp_erp_thread+0xf6/0x2b0 [zfcp] + [<000000000016b75a>] kthread+0xf2/0xfc + [<000000000070c9de>] kernel_thread_starter+0x6/0xc + [<000000000070c9d8>] kernel_thread_starter+0x0/0xc + +Apparently, the ref_count for some scsi_device drops down to zero, +triggering device removal through execute_in_process_context(), while +the lldd error recovery thread iterates through a scsi device list. +Unfortunately, execute_in_process_context() decides to immediately +execute that device removal function, instead of scheduling asynchronous +execution, since it detects process context and thinks it is safe to do +so. But almost all calls to shost_for_each_device() in our lldd are +inside spin_lock_irq, even in thread context. Obviously, schedule() +inside spin_lock_irq sections is a bad idea. + +Change the lldd to use the proper iterator function, +__shost_for_each_device(), in combination with required locking. + +Occurences that need to be changed include all calls in zfcp_erp.c, +since those might be executed in zfcp error recovery thread context +with a lock held. + +Other occurences of shost_for_each_device() in zfcp_fsf.c do not +need to be changed (no process context, no surrounding locking). + +The problem was introduced in Linux 2.6.37 by commit +b62a8d9b45b971a67a0f8413338c230e3117dff5 +"[SCSI] zfcp: Use SCSI device data zfcp_scsi_dev instead of zfcp_unit". + +Reported-by: Christian Borntraeger +Signed-off-by: Martin Peschke +Signed-off-by: Steffen Maier +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_erp.c | 29 ++++++++++++++++++++++------- + 1 file changed, 22 insertions(+), 7 deletions(-) + +--- a/drivers/s390/scsi/zfcp_erp.c ++++ b/drivers/s390/scsi/zfcp_erp.c +@@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port + + if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) + zfcp_erp_action_dismiss(&port->erp_action); +- else +- shost_for_each_device(sdev, port->adapter->scsi_host) ++ else { ++ spin_lock(port->adapter->scsi_host->host_lock); ++ __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) + zfcp_erp_action_dismiss_lun(sdev); ++ spin_unlock(port->adapter->scsi_host->host_lock); ++ } + } + + static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) +@@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(str + { + struct scsi_device *sdev; + +- shost_for_each_device(sdev, port->adapter->scsi_host) ++ spin_lock(port->adapter->scsi_host->host_lock); ++ __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) + _zfcp_erp_lun_reopen(sdev, clear, id, 0); ++ spin_unlock(port->adapter->scsi_host->host_lock); + } + + static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) +@@ -1435,8 +1440,10 @@ void zfcp_erp_set_adapter_status(struct + atomic_set_mask(common_mask, &port->status); + read_unlock_irqrestore(&adapter->port_list_lock, flags); + +- shost_for_each_device(sdev, adapter->scsi_host) ++ spin_lock_irqsave(adapter->scsi_host->host_lock, flags); ++ __shost_for_each_device(sdev, adapter->scsi_host) + atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); ++ spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); + } + + /** +@@ -1470,11 +1477,13 @@ void zfcp_erp_clear_adapter_status(struc + } + read_unlock_irqrestore(&adapter->port_list_lock, flags); + +- shost_for_each_device(sdev, adapter->scsi_host) { ++ spin_lock_irqsave(adapter->scsi_host->host_lock, flags); ++ __shost_for_each_device(sdev, adapter->scsi_host) { + atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); + if (clear_counter) + atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); + } ++ spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); + } + + /** +@@ -1488,16 +1497,19 @@ void zfcp_erp_set_port_status(struct zfc + { + struct scsi_device *sdev; + u32 common_mask = mask & ZFCP_COMMON_FLAGS; ++ unsigned long flags; + + atomic_set_mask(mask, &port->status); + + if (!common_mask) + return; + +- shost_for_each_device(sdev, port->adapter->scsi_host) ++ spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); ++ __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) + atomic_set_mask(common_mask, + &sdev_to_zfcp(sdev)->status); ++ spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); + } + + /** +@@ -1512,6 +1524,7 @@ void zfcp_erp_clear_port_status(struct z + struct scsi_device *sdev; + u32 common_mask = mask & ZFCP_COMMON_FLAGS; + u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; ++ unsigned long flags; + + atomic_clear_mask(mask, &port->status); + +@@ -1521,13 +1534,15 @@ void zfcp_erp_clear_port_status(struct z + if (clear_counter) + atomic_set(&port->erp_counter, 0); + +- shost_for_each_device(sdev, port->adapter->scsi_host) ++ spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); ++ __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) { + atomic_clear_mask(common_mask, + &sdev_to_zfcp(sdev)->status); + if (clear_counter) + atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); + } ++ spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); + } + + /**