UBI: allocate memory with GFP_NOFS

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Sun Oct 14 09:59:01 EDT 2007


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=33818bbb84cd371b63ed8849cc5264d24c8b3aa2
Commit:     33818bbb84cd371b63ed8849cc5264d24c8b3aa2
Parent:     ef6075fbfca9139f428d52d60e671da38aa2e212
Author:     Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
AuthorDate: Tue Aug 28 21:29:32 2007 +0300
Committer:  Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
CommitDate: Sun Oct 14 13:10:20 2007 +0300

    UBI: allocate memory with GFP_NOFS
    
    Use GFP_NOFS flag when allocating memory on I/O path, because otherwise
    we may deadlock the filesystem which works on top of us. We observed
    the deadlocks with UBIFS. Example:
    
    VFS->FS lock a lock->UBI->kmalloc()->VFS writeback->FS locks the same
    lock again.
    
    Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 drivers/mtd/ubi/eba.c  |   12 ++++++------
 drivers/mtd/ubi/io.c   |    4 ++--
 drivers/mtd/ubi/scan.c |    4 ++--
 drivers/mtd/ubi/ubi.h  |    6 ++++--
 drivers/mtd/ubi/vtbl.c |    2 +-
 drivers/mtd/ubi/wl.c   |   12 ++++++------
 6 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 7c5e29e..8919310 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -157,7 +157,7 @@ static struct ltree_entry *ltree_add_entry(struct ubi_device *ubi, int vol_id,
 {
 	struct ltree_entry *le, *le1, *le_free;
 
-	le = kmem_cache_alloc(ltree_slab, GFP_KERNEL);
+	le = kmem_cache_alloc(ltree_slab, GFP_NOFS);
 	if (!le)
 		return ERR_PTR(-ENOMEM);
 
@@ -397,7 +397,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
 
 retry:
 	if (check) {
-		vid_hdr = ubi_zalloc_vid_hdr(ubi);
+		vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 		if (!vid_hdr) {
 			err = -ENOMEM;
 			goto out_unlock;
@@ -497,7 +497,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
 	struct ubi_vid_hdr *vid_hdr;
 	unsigned char *new_buf;
 
-	vid_hdr = ubi_zalloc_vid_hdr(ubi);
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr) {
 		return -ENOMEM;
 	}
@@ -627,7 +627,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, int vol_id, int lnum,
 	 * The logical eraseblock is not mapped. We have to get a free physical
 	 * eraseblock and write the volume identifier header there first.
 	 */
-	vid_hdr = ubi_zalloc_vid_hdr(ubi);
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr) {
 		leb_write_unlock(ubi, vol_id, lnum);
 		return -ENOMEM;
@@ -738,7 +738,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum,
 	else
 		ubi_assert(len % ubi->min_io_size == 0);
 
-	vid_hdr = ubi_zalloc_vid_hdr(ubi);
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr)
 		return -ENOMEM;
 
@@ -844,7 +844,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum,
 	if (ubi->ro_mode)
 		return -EROFS;
 
-	vid_hdr = ubi_zalloc_vid_hdr(ubi);
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr)
 		return -ENOMEM;
 
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 9284763..ba5bc4a 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -1099,7 +1099,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
 	uint32_t crc, hdr_crc;
 	struct ubi_ec_hdr *ec_hdr;
 
-	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
 	if (!ec_hdr)
 		return -ENOMEM;
 
@@ -1179,7 +1179,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
 	struct ubi_vid_hdr *vid_hdr;
 	void *p;
 
-	vid_hdr = ubi_zalloc_vid_hdr(ubi);
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr)
 		return -ENOMEM;
 
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 18c347b..1c1401d 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -323,7 +323,7 @@ static int compare_lebs(const struct ubi_device *ubi,
 	} else {
 		pnum = seb->pnum;
 
-		vh = ubi_zalloc_vid_hdr(ubi);
+		vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 		if (!vh)
 			return -ENOMEM;
 
@@ -948,7 +948,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
 	if (!ech)
 		goto out_si;
 
-	vidh = ubi_zalloc_vid_hdr(ubi);
+	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 	if (!vidh)
 		goto out_ech;
 
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 5959f91..3296631 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -439,16 +439,18 @@ int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum,
 /**
  * ubi_zalloc_vid_hdr - allocate a volume identifier header object.
  * @ubi: UBI device description object
+ * @gfp_flags: GFP flags to allocate with
  *
  * This function returns a pointer to the newly allocated and zero-filled
  * volume identifier header object in case of success and %NULL in case of
  * failure.
  */
-static inline struct ubi_vid_hdr *ubi_zalloc_vid_hdr(const struct ubi_device *ubi)
+static inline struct ubi_vid_hdr *
+ubi_zalloc_vid_hdr(const struct ubi_device *ubi, gfp_t gfp_flags)
 {
 	void *vid_hdr;
 
-	vid_hdr = kzalloc(ubi->vid_hdr_alsize, GFP_KERNEL);
+	vid_hdr = kzalloc(ubi->vid_hdr_alsize, gfp_flags);
 	if (!vid_hdr)
 		return NULL;
 
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index bc5df50..b0a1e84 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -264,7 +264,7 @@ static int create_vtbl(const struct ubi_device *ubi, struct ubi_scan_info *si,
 
 	ubi_msg("create volume table (copy #%d)", copy + 1);
 
-	vid_hdr = ubi_zalloc_vid_hdr(ubi);
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 	if (!vid_hdr)
 		return -ENOMEM;
 
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 12b25e5..248ff9e 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -508,7 +508,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
 	ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
 		   dtype == UBI_UNKNOWN);
 
-	pe = kmalloc(sizeof(struct ubi_wl_prot_entry), GFP_KERNEL);
+	pe = kmalloc(sizeof(struct ubi_wl_prot_entry), GFP_NOFS);
 	if (!pe)
 		return -ENOMEM;
 
@@ -645,7 +645,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int tortur
 	if (err > 0)
 		return -EINVAL;
 
-	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
 	if (!ec_hdr)
 		return -ENOMEM;
 
@@ -768,7 +768,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
 	dbg_wl("schedule erasure of PEB %d, EC %d, torture %d",
 	       e->pnum, e->ec, torture);
 
-	wl_wrk = kmalloc(sizeof(struct ubi_work), GFP_KERNEL);
+	wl_wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
 	if (!wl_wrk)
 		return -ENOMEM;
 
@@ -802,7 +802,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 	if (cancel)
 		return 0;
 
-	vid_hdr = ubi_zalloc_vid_hdr(ubi);
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr)
 		return -ENOMEM;
 
@@ -1028,7 +1028,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
 	ubi->wl_scheduled = 1;
 	spin_unlock(&ubi->wl_lock);
 
-	wrk = kmalloc(sizeof(struct ubi_work), GFP_KERNEL);
+	wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
 	if (!wrk) {
 		err = -ENOMEM;
 		goto out_cancel;
@@ -1631,7 +1631,7 @@ static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec)
 	long long read_ec;
 	struct ubi_ec_hdr *ec_hdr;
 
-	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
 	if (!ec_hdr)
 		return -ENOMEM;
 



More information about the linux-mtd-cvs mailing list