Commit 33818bbb authored by Artem Bityutskiy's avatar Artem Bityutskiy

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: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent ef6075fb
...@@ -157,7 +157,7 @@ static struct ltree_entry *ltree_add_entry(struct ubi_device *ubi, int vol_id, ...@@ -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; 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) if (!le)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -397,7 +397,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, ...@@ -397,7 +397,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
retry: retry:
if (check) { if (check) {
vid_hdr = ubi_zalloc_vid_hdr(ubi); vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr) { if (!vid_hdr) {
err = -ENOMEM; err = -ENOMEM;
goto out_unlock; goto out_unlock;
...@@ -497,7 +497,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -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; struct ubi_vid_hdr *vid_hdr;
unsigned char *new_buf; unsigned char *new_buf;
vid_hdr = ubi_zalloc_vid_hdr(ubi); vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr) { if (!vid_hdr) {
return -ENOMEM; return -ENOMEM;
} }
...@@ -627,7 +627,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, int vol_id, int lnum, ...@@ -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 * The logical eraseblock is not mapped. We have to get a free physical
* eraseblock and write the volume identifier header there first. * 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) { if (!vid_hdr) {
leb_write_unlock(ubi, vol_id, lnum); leb_write_unlock(ubi, vol_id, lnum);
return -ENOMEM; return -ENOMEM;
...@@ -738,7 +738,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum, ...@@ -738,7 +738,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum,
else else
ubi_assert(len % ubi->min_io_size == 0); 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) if (!vid_hdr)
return -ENOMEM; return -ENOMEM;
...@@ -844,7 +844,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum, ...@@ -844,7 +844,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum,
if (ubi->ro_mode) if (ubi->ro_mode)
return -EROFS; return -EROFS;
vid_hdr = ubi_zalloc_vid_hdr(ubi); vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr) if (!vid_hdr)
return -ENOMEM; return -ENOMEM;
......
...@@ -1099,7 +1099,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) ...@@ -1099,7 +1099,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
uint32_t crc, hdr_crc; uint32_t crc, hdr_crc;
struct ubi_ec_hdr *ec_hdr; 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) if (!ec_hdr)
return -ENOMEM; return -ENOMEM;
...@@ -1179,7 +1179,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) ...@@ -1179,7 +1179,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
void *p; void *p;
vid_hdr = ubi_zalloc_vid_hdr(ubi); vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr) if (!vid_hdr)
return -ENOMEM; return -ENOMEM;
......
...@@ -323,7 +323,7 @@ static int compare_lebs(const struct ubi_device *ubi, ...@@ -323,7 +323,7 @@ static int compare_lebs(const struct ubi_device *ubi,
} else { } else {
pnum = seb->pnum; pnum = seb->pnum;
vh = ubi_zalloc_vid_hdr(ubi); vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vh) if (!vh)
return -ENOMEM; return -ENOMEM;
...@@ -948,7 +948,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) ...@@ -948,7 +948,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
if (!ech) if (!ech)
goto out_si; goto out_si;
vidh = ubi_zalloc_vid_hdr(ubi); vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vidh) if (!vidh)
goto out_ech; goto out_ech;
......
...@@ -439,16 +439,18 @@ int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum, ...@@ -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_zalloc_vid_hdr - allocate a volume identifier header object.
* @ubi: UBI device description 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 * 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 * volume identifier header object in case of success and %NULL in case of
* failure. * 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; void *vid_hdr;
vid_hdr = kzalloc(ubi->vid_hdr_alsize, GFP_KERNEL); vid_hdr = kzalloc(ubi->vid_hdr_alsize, gfp_flags);
if (!vid_hdr) if (!vid_hdr)
return NULL; return NULL;
......
...@@ -264,7 +264,7 @@ static int create_vtbl(const struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -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); 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) if (!vid_hdr)
return -ENOMEM; return -ENOMEM;
......
...@@ -508,7 +508,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) ...@@ -508,7 +508,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM || ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
dtype == UBI_UNKNOWN); 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) if (!pe)
return -ENOMEM; return -ENOMEM;
...@@ -645,7 +645,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int tortur ...@@ -645,7 +645,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int tortur
if (err > 0) if (err > 0)
return -EINVAL; return -EINVAL;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
if (!ec_hdr) if (!ec_hdr)
return -ENOMEM; return -ENOMEM;
...@@ -768,7 +768,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, ...@@ -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", dbg_wl("schedule erasure of PEB %d, EC %d, torture %d",
e->pnum, e->ec, torture); 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) if (!wl_wrk)
return -ENOMEM; return -ENOMEM;
...@@ -802,7 +802,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -802,7 +802,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
if (cancel) if (cancel)
return 0; return 0;
vid_hdr = ubi_zalloc_vid_hdr(ubi); vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr) if (!vid_hdr)
return -ENOMEM; return -ENOMEM;
...@@ -1028,7 +1028,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi) ...@@ -1028,7 +1028,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
ubi->wl_scheduled = 1; ubi->wl_scheduled = 1;
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
wrk = kmalloc(sizeof(struct ubi_work), GFP_KERNEL); wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
if (!wrk) { if (!wrk) {
err = -ENOMEM; err = -ENOMEM;
goto out_cancel; goto out_cancel;
...@@ -1631,7 +1631,7 @@ static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec) ...@@ -1631,7 +1631,7 @@ static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec)
long long read_ec; long long read_ec;
struct ubi_ec_hdr *ec_hdr; 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) if (!ec_hdr)
return -ENOMEM; return -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment