Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bef22ee authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'upstream-4.4-rc7' of git://git.infradead.org/linux-ubifs

Pull UBI bug fixes from Richard Weinberger:
 "This contains four bug fixes for UBI"

* tag 'upstream-4.4-rc7' of git://git.infradead.org/linux-ubifs:
  mtd: ubi: don't leak e if schedule_erase() fails
  mtd: ubi: fixup error correction in do_sync_erase()
  UBI: fix use of "VID" vs. "EC" in header self-check
  UBI: fix return error code
parents e2b0a161 6b238de1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -236,7 +236,7 @@ int ubi_debugfs_init(void)

	dfs_rootdir = debugfs_create_dir("ubi", NULL);
	if (IS_ERR_OR_NULL(dfs_rootdir)) {
		int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
		int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV;

		pr_err("UBI error: cannot create \"ubi\" debugfs directory, error %d\n",
		       err);
+1 −1
Original line number Diff line number Diff line
@@ -1299,7 +1299,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
	if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
		goto exit;

	crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
	crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
	hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
	if (hdr_crc != crc) {
		ubi_err(ubi, "bad VID header CRC at PEB %d, calculated %#08x, read %#08x",
+29 −24
Original line number Diff line number Diff line
@@ -603,6 +603,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
	return 0;
}

static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk);
/**
 * do_sync_erase - run the erase worker synchronously.
 * @ubi: UBI device description object
@@ -615,20 +616,16 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
			 int vol_id, int lnum, int torture)
{
	struct ubi_work *wl_wrk;
	struct ubi_work wl_wrk;

	dbg_wl("sync erase of PEB %i", e->pnum);

	wl_wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
	if (!wl_wrk)
		return -ENOMEM;

	wl_wrk->e = e;
	wl_wrk->vol_id = vol_id;
	wl_wrk->lnum = lnum;
	wl_wrk->torture = torture;
	wl_wrk.e = e;
	wl_wrk.vol_id = vol_id;
	wl_wrk.lnum = lnum;
	wl_wrk.torture = torture;

	return erase_worker(ubi, wl_wrk, 0);
	return __erase_worker(ubi, &wl_wrk);
}

/**
@@ -1014,7 +1011,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi, int nested)
}

/**
 * erase_worker - physical eraseblock erase worker function.
 * __erase_worker - physical eraseblock erase worker function.
 * @ubi: UBI device description object
 * @wl_wrk: the work object
 * @shutdown: non-zero if the worker has to free memory and exit
@@ -1025,8 +1022,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi, int nested)
 * needed. Returns zero in case of success and a negative error code in case of
 * failure.
 */
static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
			int shutdown)
static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
{
	struct ubi_wl_entry *e = wl_wrk->e;
	int pnum = e->pnum;
@@ -1034,21 +1030,11 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
	int lnum = wl_wrk->lnum;
	int err, available_consumed = 0;

	if (shutdown) {
		dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
		kfree(wl_wrk);
		wl_entry_destroy(ubi, e);
		return 0;
	}

	dbg_wl("erase PEB %d EC %d LEB %d:%d",
	       pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);

	err = sync_erase(ubi, e, wl_wrk->torture);
	if (!err) {
		/* Fine, we've erased it successfully */
		kfree(wl_wrk);

		spin_lock(&ubi->wl_lock);
		wl_tree_add(e, &ubi->free);
		ubi->free_count++;
@@ -1066,7 +1052,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
	}

	ubi_err(ubi, "failed to erase PEB %d, error %d", pnum, err);
	kfree(wl_wrk);

	if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
	    err == -EBUSY) {
@@ -1075,6 +1060,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
		/* Re-schedule the LEB for erasure */
		err1 = schedule_erase(ubi, e, vol_id, lnum, 0);
		if (err1) {
			wl_entry_destroy(ubi, e);
			err = err1;
			goto out_ro;
		}
@@ -1150,6 +1136,25 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
	return err;
}

static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
			  int shutdown)
{
	int ret;

	if (shutdown) {
		struct ubi_wl_entry *e = wl_wrk->e;

		dbg_wl("cancel erasure of PEB %d EC %d", e->pnum, e->ec);
		kfree(wl_wrk);
		wl_entry_destroy(ubi, e);
		return 0;
	}

	ret = __erase_worker(ubi, wl_wrk);
	kfree(wl_wrk);
	return ret;
}

/**
 * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
 * @ubi: UBI device description object