Commit 350130af authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ubifs-for-linus-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs

Pull UBI and UBIFS updates from Richard Weinberger:
 "UBI:
   - New interface to dump detailed erase counters
   - Fixes around wear-leveling

  UBIFS:
   - Minor cleanups
   - Fix for TNC dumping code"

* tag 'ubifs-for-linus-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubi: ubi_get_ec_info: Fix compiling error 'cast specifies array type'
  ubi: Implement ioctl for detailed erase counters
  ubi: Expose interface for detailed erase counters
  ubifs: skip dumping tnc tree when zroot is null
  ubi: Revert "ubi: wl: Close down wear-leveling before nand is suspended"
  ubifs: ubifs_dump_leb: remove return from end of void function
  ubifs: dump_lpt_leb: remove return at end of void function
  ubi: Add a check for ubi_num
parents 2a9f04bd 69146a8c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1537,7 +1537,7 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)
	if (token) {
		int err = kstrtoint(token, 10, &p->ubi_num);

		if (err) {
		if (err || p->ubi_num < UBI_DEV_NUM_AUTO) {
			pr_err("UBI error: bad value for ubi_num parameter: %s\n",
			       token);
			return -EINVAL;
+70 −0
Original line number Diff line number Diff line
@@ -828,6 +828,70 @@ static int rename_volumes(struct ubi_device *ubi,
	return err;
}

static int ubi_get_ec_info(struct ubi_device *ubi, struct ubi_ecinfo_req __user *ureq)
{
	struct ubi_ecinfo_req req;
	struct ubi_wl_entry *wl;
	int read_cnt;
	int peb;
	int end_peb;

	/* Copy the input arguments */
	if (copy_from_user(&req, ureq, sizeof(struct ubi_ecinfo_req)))
		return -EFAULT;

	/* Check input arguments */
	if (req.length <= 0 || req.start < 0 || req.start >= ubi->peb_count)
		return -EINVAL;

	if (check_add_overflow(req.start, req.length, &end_peb))
		return -EINVAL;

	if (end_peb > ubi->peb_count)
		end_peb = ubi->peb_count;

	/* Check access rights before filling erase_counters array */
	if (!access_ok((void __user *)ureq->erase_counters,
		       (end_peb-req.start) * sizeof(int32_t)))
		return -EFAULT;

	/* Fill erase counter array */
	read_cnt = 0;
	for (peb = req.start; peb < end_peb; read_cnt++, peb++) {
		int ec;

		if (ubi_io_is_bad(ubi, peb)) {
			if (__put_user(UBI_UNKNOWN, ureq->erase_counters+read_cnt))
				return -EFAULT;

			continue;
		}

		spin_lock(&ubi->wl_lock);

		wl = ubi->lookuptbl[peb];
		if (wl)
			ec = wl->ec;
		else
			ec = UBI_UNKNOWN;

		spin_unlock(&ubi->wl_lock);

		if (__put_user(ec, ureq->erase_counters+read_cnt))
			return -EFAULT;

	}

	/* Return actual read length */
	req.read_length = read_cnt;

	/* Copy everything except erase counter array */
	if (copy_to_user(ureq, &req, sizeof(struct ubi_ecinfo_req)))
		return -EFAULT;

	return 0;
}

static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
			   unsigned long arg)
{
@@ -991,6 +1055,12 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
		break;
	}

	case UBI_IOCECNFO:
	{
		err = ubi_get_ec_info(ubi, argp);
		break;
	}

	default:
		err = -ENOTTY;
		break;
+0 −2
Original line number Diff line number Diff line
@@ -549,7 +549,6 @@ struct ubi_debug_info {
 * @peb_buf: a buffer of PEB size used for different purposes
 * @buf_mutex: protects @peb_buf
 * @ckvol_mutex: serializes static volume checking when opening
 * @wl_reboot_notifier: close all wear-leveling work before reboot
 *
 * @dbg: debugging information for this UBI device
 */
@@ -652,7 +651,6 @@ struct ubi_device {
	void *peb_buf;
	struct mutex buf_mutex;
	struct mutex ckvol_mutex;
	struct notifier_block wl_reboot_notifier;

	struct ubi_debug_info dbg;
};
+0 −21
Original line number Diff line number Diff line
@@ -89,7 +89,6 @@
#include <linux/crc32.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
#include "ubi.h"
#include "wl.h"

@@ -128,8 +127,6 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
				 struct ubi_wl_entry *e, struct rb_root *root);
static int self_check_in_pq(const struct ubi_device *ubi,
			    struct ubi_wl_entry *e);
static int ubi_wl_reboot_notifier(struct notifier_block *n,
				  unsigned long state, void *cmd);

/**
 * wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -1953,13 +1950,6 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
	if (!ubi->ro_mode && !ubi->fm_disabled)
		ubi_ensure_anchor_pebs(ubi);
#endif

	if (!ubi->wl_reboot_notifier.notifier_call) {
		ubi->wl_reboot_notifier.notifier_call = ubi_wl_reboot_notifier;
		ubi->wl_reboot_notifier.priority = 1; /* Higher than MTD */
		register_reboot_notifier(&ubi->wl_reboot_notifier);
	}

	return 0;

out_free:
@@ -2005,17 +1995,6 @@ void ubi_wl_close(struct ubi_device *ubi)
	kfree(ubi->lookuptbl);
}

static int ubi_wl_reboot_notifier(struct notifier_block *n,
				  unsigned long state, void *cmd)
{
	struct ubi_device *ubi;

	ubi = container_of(n, struct ubi_device, wl_reboot_notifier);
	ubi_wl_close(ubi);

	return NOTIFY_DONE;
}

/**
 * self_check_ec - make sure that the erase counter of a PEB is correct.
 * @ubi: UBI device description object
+13 −10
Original line number Diff line number Diff line
@@ -863,7 +863,6 @@ void ubifs_dump_leb(const struct ubifs_info *c, int lnum)

out:
	vfree(buf);
	return;
}

void ubifs_dump_znode(const struct ubifs_info *c,
@@ -946,6 +945,7 @@ void ubifs_dump_tnc(struct ubifs_info *c)

	pr_err("\n");
	pr_err("(pid %d) start dumping TNC tree\n", current->pid);
	if (c->zroot.znode) {
		znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, NULL);
		level = znode->level;
		pr_err("== Level %d ==\n", level);
@@ -957,6 +957,9 @@ void ubifs_dump_tnc(struct ubifs_info *c)
			ubifs_dump_znode(c, znode);
			znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, znode);
		}
	} else {
		pr_err("empty TNC tree in memory\n");
	}
	pr_err("(pid %d) finish dumping TNC tree\n", current->pid);
}

Loading