This pull request contains updates for UBI and UBIFS:
UBI: - New interface to dump detailed erase counters - Fixes around wear-leveling UBIFS: - Minor cleanups - Fix for TNC dumping code -----BEGIN PGP SIGNATURE----- iQJKBAABCAA0FiEEdgfidid8lnn52cLTZvlZhesYu8EFAmeb8cgWHHJpY2hhcmRA c2lnbWEtc3Rhci5hdAAKCRBm+VmF6xi7wRUPEADos2ZdLleilKSAuPV6osItbNjo UAkwFAu4suQMzChZv4V/b7uisu1vBQiOMGiqCZQdU6aIzSUsUlqNQSn8L3f6cPD1 P9Kae1SNCFdlmrfiaduWyxHsl1pxBDfXQ8qt3hcVpNf3LEuYJfu25Fefqavg9IvI Egp0Akk89C4AzNoHUDhzCp8oHAV0nwX5kBN8SVc28G6sb/SQG6+1kU9Op+d6qjoX 8UTfeyETkDIzpx+wjl4bn5o4lagtaJqS/TI6UfhE736KjPUnGK0oEWoHA6AGCqu4 E158pqYh69LHTQ7Wxo7wQ+9Pc9xoE2qTrKUF5b/u9GzsbHMtd4q/pg9Aa8OOcZur ir7pjrRqGkybYGfnhs/b/9Jq7rr7nQNl0j413nmNHb3Wf9+qjwmxYvPQusd6/bLr nHfRymIGCXhuOqgB37t+F+iuQkwfnatVJHJ+Q0r8pJ35LgXj/+PTKZycYF5Jg72q tcth9CXoVCF78e6AJX6GioSOfBUMA5EXK8bqWKr20ZHPbVP8W7gOg7G8PFoNOnj+ KiRMvOqXavPUCcrRxDbp1T50NC+dQYX0FuyCtjuX5vH+0YpgdgvA0trkGPOgMeqw x6py7J+u7jhCWoVecw2DL4ZwEdr4QcvEiTra8i+v4PyRkdrUZenuty+pbeSnUsNk rHKJZkie9Z2xycLJAA== =bgVN -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
350130afc2
|
@ -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;
|
||||
|
|
|
@ -828,6 +828,70 @@ out_free:
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,16 +945,20 @@ void ubifs_dump_tnc(struct ubifs_info *c)
|
|||
|
||||
pr_err("\n");
|
||||
pr_err("(pid %d) start dumping TNC tree\n", current->pid);
|
||||
znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, NULL);
|
||||
level = znode->level;
|
||||
pr_err("== Level %d ==\n", level);
|
||||
while (znode) {
|
||||
if (level != znode->level) {
|
||||
level = znode->level;
|
||||
pr_err("== Level %d ==\n", level);
|
||||
if (c->zroot.znode) {
|
||||
znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, NULL);
|
||||
level = znode->level;
|
||||
pr_err("== Level %d ==\n", level);
|
||||
while (znode) {
|
||||
if (level != znode->level) {
|
||||
level = znode->level;
|
||||
pr_err("== Level %d ==\n", level);
|
||||
}
|
||||
ubifs_dump_znode(c, znode);
|
||||
znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, znode);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1932,7 +1932,6 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
|
|||
pr_err("(pid %d) finish dumping LEB %d\n", current->pid, lnum);
|
||||
out:
|
||||
vfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -175,6 +175,8 @@
|
|||
#define UBI_IOCRPEB _IOW(UBI_IOC_MAGIC, 4, __s32)
|
||||
/* Force scrubbing on the specified PEB */
|
||||
#define UBI_IOCSPEB _IOW(UBI_IOC_MAGIC, 5, __s32)
|
||||
/* Read detailed device erase counter information */
|
||||
#define UBI_IOCECNFO _IOWR(UBI_IOC_MAGIC, 6, struct ubi_ecinfo_req)
|
||||
|
||||
/* ioctl commands of the UBI control character device */
|
||||
|
||||
|
@ -412,6 +414,37 @@ struct ubi_rnvol_req {
|
|||
} ents[UBI_MAX_RNVOL];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct ubi_ecinfo_req - a data structure used for requesting and receiving
|
||||
* erase block counter information from a UBI device.
|
||||
*
|
||||
* @start: index of first physical erase block to read (in)
|
||||
* @length: number of erase counters to read (in)
|
||||
* @read_length: number of erase counters that was actually read (out)
|
||||
* @padding: reserved for future, not used, has to be zeroed
|
||||
* @erase_counters: array of erase counter values (out)
|
||||
*
|
||||
* This structure is used to retrieve erase counter information for a specified
|
||||
* range of PEBs on a UBI device.
|
||||
* Erase counters are read from @start and attempts to read @length number of
|
||||
* erase counters.
|
||||
* The retrieved values are stored in the @erase_counters array. It is the
|
||||
* responsibility of the caller to allocate enough memory for storing @length
|
||||
* elements in the @erase_counters array.
|
||||
* If a block is bad or if the erase counter is unknown the corresponding value
|
||||
* in the array will be set to -1.
|
||||
* The @read_length field will indicate the number of erase counters actually
|
||||
* read. Typically @read_length will be limited due to memory or the number of
|
||||
* PEBs on the UBI device.
|
||||
*/
|
||||
struct ubi_ecinfo_req {
|
||||
__s32 start;
|
||||
__s32 length;
|
||||
__s32 read_length;
|
||||
__s8 padding[16];
|
||||
__s32 erase_counters[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct ubi_leb_change_req - a data structure used in atomic LEB change
|
||||
* requests.
|
||||
|
|
Loading…
Reference in New Issue