From: Greg Kroah-Hartman Date: Tue, 10 Mar 2020 12:18:35 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v4.4.216~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=55a992ff33a04152e463ecd6ff5f85c6c0ebc60d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: dm-integrity-fix-a-deadlock-due-to-offloading-to-an-incorrect-workqueue.patch scsi-pm80xx-fixed-kernel-panic-during-error-recovery-for-sata-drive.patch --- diff --git a/queue-4.19/dm-integrity-fix-a-deadlock-due-to-offloading-to-an-incorrect-workqueue.patch b/queue-4.19/dm-integrity-fix-a-deadlock-due-to-offloading-to-an-incorrect-workqueue.patch new file mode 100644 index 00000000000..6a786f5c848 --- /dev/null +++ b/queue-4.19/dm-integrity-fix-a-deadlock-due-to-offloading-to-an-incorrect-workqueue.patch @@ -0,0 +1,95 @@ +From 53770f0ec5fd417429775ba006bc4abe14002335 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Mon, 17 Feb 2020 07:43:03 -0500 +Subject: dm integrity: fix a deadlock due to offloading to an incorrect workqueue + +From: Mikulas Patocka + +commit 53770f0ec5fd417429775ba006bc4abe14002335 upstream. + +If we need to perform synchronous I/O in dm_integrity_map_continue(), +we must make sure that we are not in the map function - in order to +avoid the deadlock due to bio queuing in generic_make_request. To +avoid the deadlock, we offload the request to metadata_wq. + +However, metadata_wq also processes metadata updates for write requests. +If there are too many requests that get offloaded to metadata_wq at the +beginning of dm_integrity_map_continue, the workqueue metadata_wq +becomes clogged and the system is incapable of processing any metadata +updates. + +This causes a deadlock because all the requests that need to do metadata +updates wait for metadata_wq to proceed and metadata_wq waits inside +wait_and_add_new_range until some existing request releases its range +lock (which doesn't happen because the range lock is released after +metadata update). + +In order to fix the deadlock, we create a new workqueue offload_wq and +offload requests to it - so that processing of offload_wq is independent +from processing of metadata_wq. + +Fixes: 7eada909bfd7 ("dm: add integrity target") +Cc: stable@vger.kernel.org # v4.12+ +Reported-by: Heinz Mauelshagen +Tested-by: Heinz Mauelshagen +Signed-off-by: Heinz Mauelshagen +Signed-off-by: Mikulas Patocka +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-integrity.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/md/dm-integrity.c ++++ b/drivers/md/dm-integrity.c +@@ -198,6 +198,7 @@ struct dm_integrity_c { + struct list_head wait_list; + wait_queue_head_t endio_wait; + struct workqueue_struct *wait_wq; ++ struct workqueue_struct *offload_wq; + + unsigned char commit_seq; + commit_id_t commit_ids[N_COMMIT_IDS]; +@@ -1237,7 +1238,7 @@ static void dec_in_flight(struct dm_inte + dio->range.logical_sector += dio->range.n_sectors; + bio_advance(bio, dio->range.n_sectors << SECTOR_SHIFT); + INIT_WORK(&dio->work, integrity_bio_wait); +- queue_work(ic->wait_wq, &dio->work); ++ queue_work(ic->offload_wq, &dio->work); + return; + } + do_endio_flush(ic, dio); +@@ -1657,7 +1658,7 @@ static void dm_integrity_map_continue(st + + if (need_sync_io && from_map) { + INIT_WORK(&dio->work, integrity_bio_wait); +- queue_work(ic->metadata_wq, &dio->work); ++ queue_work(ic->offload_wq, &dio->work); + return; + } + +@@ -3308,6 +3309,14 @@ static int dm_integrity_ctr(struct dm_ta + goto bad; + } + ++ ic->offload_wq = alloc_workqueue("dm-integrity-offload", WQ_MEM_RECLAIM, ++ METADATA_WORKQUEUE_MAX_ACTIVE); ++ if (!ic->offload_wq) { ++ ti->error = "Cannot allocate workqueue"; ++ r = -ENOMEM; ++ goto bad; ++ } ++ + ic->commit_wq = alloc_workqueue("dm-integrity-commit", WQ_MEM_RECLAIM, 1); + if (!ic->commit_wq) { + ti->error = "Cannot allocate workqueue"; +@@ -3544,6 +3553,8 @@ static void dm_integrity_dtr(struct dm_t + destroy_workqueue(ic->metadata_wq); + if (ic->wait_wq) + destroy_workqueue(ic->wait_wq); ++ if (ic->offload_wq) ++ destroy_workqueue(ic->offload_wq); + if (ic->commit_wq) + destroy_workqueue(ic->commit_wq); + if (ic->writer_wq) diff --git a/queue-4.19/scsi-pm80xx-fixed-kernel-panic-during-error-recovery-for-sata-drive.patch b/queue-4.19/scsi-pm80xx-fixed-kernel-panic-during-error-recovery-for-sata-drive.patch new file mode 100644 index 00000000000..33f93adee58 --- /dev/null +++ b/queue-4.19/scsi-pm80xx-fixed-kernel-panic-during-error-recovery-for-sata-drive.patch @@ -0,0 +1,71 @@ +From 196ba6629cf95e51403337235d09742fcdc3febd Mon Sep 17 00:00:00 2001 +From: Deepak Ukey +Date: Tue, 9 Jul 2019 15:30:48 +0530 +Subject: scsi: pm80xx: Fixed kernel panic during error recovery for SATA drive + +From: Deepak Ukey + +commit 196ba6629cf95e51403337235d09742fcdc3febd upstream. + +Disabling the SATA drive interface cause kernel panic. When the drive +Interface is disabled, device should be deregistered after aborting all +pending I/Os. Also changed the port recovery timeout to 10000 ms for +PM8006 controller. + +Signed-off-by: Deepak Ukey +Signed-off-by: Viswas G +Reviewed-by: Jack Wang +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/pm8001/pm8001_sas.c | 6 +++++- + drivers/scsi/pm8001/pm80xx_hwi.c | 2 +- + drivers/scsi/pm8001/pm80xx_hwi.h | 2 ++ + 3 files changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/pm8001/pm8001_sas.c ++++ b/drivers/scsi/pm8001/pm8001_sas.c +@@ -866,6 +866,8 @@ static void pm8001_dev_gone_notify(struc + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , + dev, 1, 0); ++ while (pm8001_dev->running_req) ++ msleep(20); + spin_lock_irqsave(&pm8001_ha->lock, flags); + } + PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id); +@@ -1238,8 +1240,10 @@ int pm8001_abort_task(struct sas_task *t + PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("Waiting for Port reset\n")); + wait_for_completion(&completion_reset); +- if (phy->port_reset_status) ++ if (phy->port_reset_status) { ++ pm8001_dev_gone_notify(dev); + goto out; ++ } + + /* + * 4. SATA Abort ALL +--- a/drivers/scsi/pm8001/pm80xx_hwi.c ++++ b/drivers/scsi/pm8001/pm80xx_hwi.c +@@ -604,7 +604,7 @@ static void update_main_config_table(str + pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= + 0x0000ffff; + pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |= +- 0x140000; ++ CHIP_8006_PORT_RECOVERY_TIMEOUT; + } + pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer); +--- a/drivers/scsi/pm8001/pm80xx_hwi.h ++++ b/drivers/scsi/pm8001/pm80xx_hwi.h +@@ -228,6 +228,8 @@ + #define SAS_MAX_AIP 0x200000 + #define IT_NEXUS_TIMEOUT 0x7D0 + #define PORT_RECOVERY_TIMEOUT ((IT_NEXUS_TIMEOUT/100) + 30) ++/* Port recovery timeout, 10000 ms for PM8006 controller */ ++#define CHIP_8006_PORT_RECOVERY_TIMEOUT 0x640000 + + #ifdef __LITTLE_ENDIAN_BITFIELD + struct sas_identify_frame_local { diff --git a/queue-4.19/series b/queue-4.19/series index 0951b75e858..26a0b420c5a 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -83,3 +83,5 @@ dmaengine-coh901318-fix-a-double-lock-bug-in-dma_tc_handle.patch powerpc-fix-hardware-pmu-exception-bug-on-powervm-compatibility-mode-systems.patch efi-x86-align-guids-to-their-size-in-the-mixed-mode-runtime-wrapper.patch efi-x86-handle-by-ref-arguments-covering-multiple-pages-in-mixed-mode.patch +dm-integrity-fix-a-deadlock-due-to-offloading-to-an-incorrect-workqueue.patch +scsi-pm80xx-fixed-kernel-panic-during-error-recovery-for-sata-drive.patch