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@nokia.com>
This commit is contained in:
parent
ef6075fbfc
commit
33818bbb84
@ -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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
} 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)
|
|||||||
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,
|
|||||||
/**
|
/**
|
||||||
* 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,
|
|||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user