From 33818bbb84cd371b63ed8849cc5264d24c8b3aa2 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 28 Aug 2007 21:29:32 +0300 Subject: [PATCH] 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 --- 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 7c5e29eaf118..89193104c6c8 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 928476394d55..ba5bc4a5379e 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 18c347b24e27..1c1401d6958b 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 5959f91be240..329663188772 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 bc5df50813d6..b0a1e8426456 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 12b25e5b7b81..248ff9e477e7 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;