[PATCH 1/4] ubi: Expose mean erase counter in sysfs

Zhihao Cheng chengzhihao1 at huawei.com
Tue Oct 8 02:10:09 PDT 2024


在 2024/10/4 16:22, Rickard Andersson 写道:
> Currently, only "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. Providing a
> mean erase counter value gives a better understanding of the overall
> flash wear.
> There exists more detailed info in debugfs, but this information is
> only available for debug builds.
> 
> This patch calculates the mean value only when it is requested. This
> calculation typically takes 2.7 ms for an UBI device with 4091 blocks
> running on a single core Cortex-A9 at 792 MHz.
> 
> Signed-off-by: Rickard Andersson <rickard.andersson at axis.com>
> ---
>   drivers/mtd/ubi/build.c | 44 +++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 44 insertions(+)
> 
> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
> index 30be4ed68fad..8bdfc51cacb1 100644
> --- a/drivers/mtd/ubi/build.c
> +++ b/drivers/mtd/ubi/build.c
> @@ -131,6 +131,8 @@ static struct device_attribute dev_volumes_count =
>   	__ATTR(volumes_count, S_IRUGO, dev_attribute_show, NULL);
>   static struct device_attribute dev_max_ec =
>   	__ATTR(max_ec, S_IRUGO, dev_attribute_show, NULL);
> +static struct device_attribute dev_mean_ec =
> +	__ATTR(mean_ec, S_IRUGO, dev_attribute_show, NULL);
>   static struct device_attribute dev_reserved_for_bad =
>   	__ATTR(reserved_for_bad, S_IRUGO, dev_attribute_show, NULL);
>   static struct device_attribute dev_bad_peb_count =
> @@ -340,6 +342,45 @@ int ubi_major2num(int major)
>   	return ubi_num;
>   }
>   
> +/**
> + * ubi_calc_mean_ec - calculate mean erase counter value.
> + * @ubi: UBI device description object
> + *
> + * Returns the mean value of the all blocks of the device.
> + * Returns zero if it was not possible to calculate the mean value.
> + */
> +int ubi_calc_mean_ec(struct ubi_device *ubi)

static int ubi_calc_mean_ec(struct ubi_device *ubi)
> +{
> +	struct ubi_wl_entry *wl;
> +	int peb;
> +	int ec_count = 0;
> +	int mean_ec = 0;
> +	uint64_t ec_sum = 0;
> +
> +	for (peb = 0; peb < ubi->peb_count; peb++) {
> +		int err;
> +
> +		err = ubi_io_is_bad(ubi, peb);
> +		if (err)
> +			continue;
> +
> +		spin_lock(&ubi->wl_lock);
> +
> +		wl = ubi->lookuptbl[peb];
> +		if (wl) {
> +			ec_sum += wl->ec;
> +			ec_count++;
> +		}
> +
> +		spin_unlock(&ubi->wl_lock);
> +	}
> +
> +	if (ec_count > 0)
> +		mean_ec = div_u64(ec_sum, ec_count);
> +
> +	return mean_ec;
> +}
> +
>   /* "Show" method for files in '/<sysfs>/class/ubi/ubiX/' */
>   static ssize_t dev_attribute_show(struct device *dev,
>   				  struct device_attribute *attr, char *buf)
> @@ -369,6 +410,8 @@ static ssize_t dev_attribute_show(struct device *dev,
>   		ret = sprintf(buf, "%d\n", ubi->vol_count - UBI_INT_VOL_COUNT);
>   	else if (attr == &dev_max_ec)
>   		ret = sprintf(buf, "%d\n", ubi->max_ec);
> +	else if (attr == &dev_mean_ec)
> +		ret = sprintf(buf, "%d\n", ubi_calc_mean_ec(ubi));
>   	else if (attr == &dev_reserved_for_bad)
>   		ret = sprintf(buf, "%d\n", ubi->beb_rsvd_pebs);
>   	else if (attr == &dev_bad_peb_count)
> @@ -395,6 +438,7 @@ static struct attribute *ubi_dev_attrs[] = {
>   	&dev_total_eraseblocks.attr,
>   	&dev_volumes_count.attr,
>   	&dev_max_ec.attr,
> +	&dev_mean_ec.attr,
>   	&dev_reserved_for_bad.attr,
>   	&dev_bad_peb_count.attr,
>   	&dev_max_vol_count.attr,
> 




More information about the linux-mtd mailing list