[PATCH v2 6/6] pmem, btt: fix potential deadlock while clearing errors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With the ACPI NFIT 'DSM' methods, acpi can be called from IO paths.
Specifically, the DSM to clear media errors is called during writes, so
that we can provide a writes-fix-errors model.

However it is easy to imagine a scenario like:
 -> write through the nvdimm driver
   -> acpi allocation
     -> writeback, causes more IO through the nvdimm driver
       -> deadlock

Fix this by using memalloc_noio_{save,restore}, which sets the GFP_NOIO
flag for the current scope when issuing commands/IOs that are expected
to clear errors.

Cc: <linux-acpi@xxxxxxxxxxxxxxx>
Cc: <linux-nvdimm@xxxxxxxxxxxx>
Cc: Dan Williams <dan.j.williams@xxxxxxxxx>
Cc: Robert Moore <robert.moore@xxxxxxxxx>
Cc: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
Signed-off-by: Vishal Verma <vishal.l.verma@xxxxxxxxx>
---
 drivers/nvdimm/btt.c  | 8 +++++++-
 drivers/nvdimm/pmem.c | 4 ++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 48382ca9..25b576d 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -11,6 +11,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  */
+#include <linux/sched/mm.h>
 #include <linux/highmem.h>
 #include <linux/debugfs.h>
 #include <linux/blkdev.h>
@@ -494,17 +495,22 @@ static int arena_clear_freelist_error(struct arena_info *arena, u32 lane)
 	if (arena->freelist[lane].has_err) {
 		u32 lba = arena->freelist[lane].block;
 		u64 nsoff = to_namespace_offset(arena, lba);
+		unsigned int noio_flag;
 		void *zerobuf;
 
+		noio_flag = memalloc_noio_save();
 		zerobuf = kzalloc(arena->sector_size, GFP_KERNEL);
-		if (!zerobuf)
+		if (!zerobuf) {
+			memalloc_noio_restore(noio_flag);
 			return -ENOMEM;
+		}
 
 		mutex_lock(&arena->freelist[lane].err_lock);
 		ret = arena_write_bytes(arena, nsoff, zerobuf,
 			arena->sector_size, 0);
 		arena->freelist[lane].has_err = 0;
 		mutex_unlock(&arena->freelist[lane].err_lock);
+		memalloc_noio_restore(noio_flag);
 		kfree(zerobuf);
 	}
 	return ret;
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 5c45e17..468e032 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -24,6 +24,7 @@
 #include <linux/moduleparam.h>
 #include <linux/badblocks.h>
 #include <linux/memremap.h>
+#include <linux/sched/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/blk-mq.h>
 #include <linux/pfn_t.h>
@@ -53,12 +54,14 @@ static int pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset,
 		unsigned int len)
 {
 	struct device *dev = to_dev(pmem);
+	unsigned int noio_flag;
 	sector_t sector;
 	long cleared;
 	int rc = 0;
 
 	sector = (offset - pmem->data_offset) / 512;
 
+	noio_flag = memalloc_noio_save();
 	cleared = nvdimm_clear_poison(dev, pmem->phys_addr + offset, len);
 	if (cleared < len)
 		rc = -EIO;
@@ -69,6 +72,7 @@ static int pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset,
 				cleared > 1 ? "s" : "");
 		badblocks_clear(&pmem->bb, sector, cleared);
 	}
+	memalloc_noio_restore(noio_flag);
 
 	invalidate_pmem(pmem->virt_addr + offset, len);
 
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux