* [PATCH v4 1/2] ubi: Expose interface for detailed erase counters @ 2024-12-09 11:48 Rickard Andersson 2024-12-09 11:48 ` [PATCH v4 2/2] ubi: Implement ioctl " Rickard Andersson 0 siblings, 1 reply; 3+ messages in thread From: Rickard Andersson @ 2024-12-09 11:48 UTC (permalink / raw) To: richard, chengzhihao1, linux-mtd, rickard314.andersson Cc: rickard.andersson, kernel Using the ioctl command 'UBI_IOCECNFO' user space can obtain detailed erase counter information of all blocks of a device. Signed-off-by: Rickard Andersson <rickard.andersson@axis.com> Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com> --- include/uapi/mtd/ubi-user.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/include/uapi/mtd/ubi-user.h b/include/uapi/mtd/ubi-user.h index e1571603175e..aa872a41ffb9 100644 --- a/include/uapi/mtd/ubi-user.h +++ b/include/uapi/mtd/ubi-user.h @@ -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. -- 2.30.2 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v4 2/2] ubi: Implement ioctl for detailed erase counters 2024-12-09 11:48 [PATCH v4 1/2] ubi: Expose interface for detailed erase counters Rickard Andersson @ 2024-12-09 11:48 ` Rickard Andersson 2024-12-09 13:54 ` Zhihao Cheng 0 siblings, 1 reply; 3+ messages in thread From: Rickard Andersson @ 2024-12-09 11:48 UTC (permalink / raw) To: richard, chengzhihao1, linux-mtd, rickard314.andersson Cc: rickard.andersson, kernel Currently, "max_ec" can be read from sysfs, which provides a limited view of the flash device’s wear. In certain cases, such as bugs in the wear-leveling algorithm, specific blocks can be worn down more than others, resulting in uneven wear distribution. Also some use cases can wear the erase blocks of the fastmap area more heavily than other parts of flash. Providing detailed erase counter values give a better understanding of the overall flash wear and is needed to be able to calculate for example expected life time. There exists more detailed info in debugfs, but this information is only available for debug builds. Signed-off-by: Rickard Andersson <rickard.andersson@axis.com> --- drivers/mtd/ubi/cdev.c | 69 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 0d8f04cf03c5..e2f2581e9f09 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -828,6 +828,69 @@ 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(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 +1054,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; -- 2.30.2 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v4 2/2] ubi: Implement ioctl for detailed erase counters 2024-12-09 11:48 ` [PATCH v4 2/2] ubi: Implement ioctl " Rickard Andersson @ 2024-12-09 13:54 ` Zhihao Cheng 0 siblings, 0 replies; 3+ messages in thread From: Zhihao Cheng @ 2024-12-09 13:54 UTC (permalink / raw) To: Rickard Andersson, richard, linux-mtd, rickard314.andersson; +Cc: kernel 在 2024/12/9 19:48, Rickard Andersson 写道: > Currently, "max_ec" can be read from sysfs, which provides a limited > view of the flash device’s wear. In certain cases, such as bugs in > the wear-leveling algorithm, specific blocks can be worn down more > than others, resulting in uneven wear distribution. Also some use cases > can wear the erase blocks of the fastmap area more heavily than other > parts of flash. > Providing detailed erase counter values give a better understanding of > the overall flash wear and is needed to be able to calculate for example > expected life time. > There exists more detailed info in debugfs, but this information is > only available for debug builds. > > Signed-off-by: Rickard Andersson <rickard.andersson@axis.com> > --- > drivers/mtd/ubi/cdev.c | 69 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 69 insertions(+) > It works, feel free to add Tested-by: Zhihao Cheng <chengzhihao1@huawei.com> Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com> > diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c > index 0d8f04cf03c5..e2f2581e9f09 100644 > --- a/drivers/mtd/ubi/cdev.c > +++ b/drivers/mtd/ubi/cdev.c > @@ -828,6 +828,69 @@ 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(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 +1054,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; > ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-12-09 13:59 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-12-09 11:48 [PATCH v4 1/2] ubi: Expose interface for detailed erase counters Rickard Andersson 2024-12-09 11:48 ` [PATCH v4 2/2] ubi: Implement ioctl " Rickard Andersson 2024-12-09 13:54 ` Zhihao Cheng
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox