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

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
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -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;

+2 −2
Original line number Diff line number Diff line
@@ -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;

+2 −2
Original line number Diff line number Diff line
@@ -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;

+4 −2
Original line number Diff line number Diff line
@@ -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;

+1 −1
Original line number Diff line number Diff line
@@ -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;

Loading