Skip to contentSkip to conversation

mtd: ubi: Add sysfs entry to force all pebs' scan

PATCH In review Tanya Brokhman 1 participant 1 message Oct 26, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v2 5/5 mtd: ubi: Add sysfs entry to force all pebs' scan

A given eraseblock can be read many times or not at all.
We do not have the account of such eraseblocks that have
not been accessed since a pre-defined threshold interval.
By means of scanning the entire flash device it is possible to identify all such eraseblocks.

Add a sysfs entry to force scan on all the PEBs on demand basis.

The sysfs entry would be available under /sys/class/ubi/ubiX/peb_scan
- echo 1 to this entry would trigger the scan, ignored if in progress
- On reading returns the scan status (1 = Scan executing, 0 = Scan not executing)

---
 drivers/mtd/ubi/build.c |  32 +++++++++--
 drivers/mtd/ubi/ubi.h   |   3 +
 drivers/mtd/ubi/wl.c    | 143 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 171 insertions(+), 7 deletions(-)
drivers/mtd/ubi/build.c +28 -4
index 34fe23a..a7464f8 100644
@@ -154,6 +154,9 @@ static struct device_attribute dev_dt_threshold =
 static struct device_attribute dev_rd_threshold =
 	__ATTR(rd_threshold, (S_IWUSR | S_IRUGO), dev_attribute_show,
 		   dev_attribute_store);
+static struct device_attribute dev_mtd_trigger_scan =
+	__ATTR(peb_scan, (S_IWUSR | S_IRUGO),
+		dev_attribute_show, dev_attribute_store);
 
 /**
  * ubi_volume_notify - send a volume change notification.
@@ -395,6 +398,8 @@ static ssize_t dev_attribute_show(struct device *dev,
 		ret = sprintf(buf, "%d\n", ubi->dt_threshold);
 	else if (attr == &dev_rd_threshold)
 		ret = sprintf(buf, "%d\n", ubi->rd_threshold);
+	else if (attr == &dev_mtd_trigger_scan)
+		ret = sprintf(buf, "%d\n", ubi->scan_in_progress);
 	else
 		ret = -EINVAL;
 
@@ -406,7 +411,7 @@ static ssize_t dev_attribute_store(struct device *dev,
 			   struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	int value;
+	int value, ret;
 	struct ubi_device *ubi;
 
 	ubi = container_of(dev, struct ubi_device, dev);
@@ -414,8 +419,11 @@ static ssize_t dev_attribute_store(struct device *dev,
 	if (!ubi)
 		return -ENODEV;
 
-	if (kstrtos32(buf, 10, &value))
-		return -EINVAL;
+	ret = count;
+	if (kstrtos32(buf, 10, &value)) {
+		ret = -EINVAL;
+		goto out;
+	}
 	/* Consider triggering full scan if threshods change */
 	else if (attr == &dev_dt_threshold) {
 		if (value < UBI_MAX_DT_THRESHOLD)
@@ -429,9 +437,21 @@ static ssize_t dev_attribute_store(struct device *dev,
 		else
 			pr_err("Max supported threshold value is %d",
 				   UBI_MAX_READCOUNTER);
+	} else if (attr == &dev_mtd_trigger_scan) {
+		if (value != 1) {
+			pr_err("Invalid input. Echo 1 to start trigger");
+			goto out;
+		}
+		if (!ubi->lookuptbl) {
+			pr_err("lookuptbl is null");
+			goto out;
+		}
+		ret = ubi_wl_scan_all(ubi);
 	}
 
-	return count;
+out:
+	ubi_put_device(ubi);
+	return ret;
 }
 
 static void dev_release(struct device *dev)
@@ -500,6 +520,9 @@ static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
 	if (err)
 		return err;
 	err = device_create_file(&ubi->dev, &dev_rd_threshold);
+	if (err)
+		return err;
+	err = device_create_file(&ubi->dev, &dev_mtd_trigger_scan);
 	return err;
 }
 
@@ -509,6 +532,7 @@ static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
  */
 static void ubi_sysfs_close(struct ubi_device *ubi)
 {
+	device_remove_file(&ubi->dev, &dev_mtd_trigger_scan);
 	device_remove_file(&ubi->dev, &dev_mtd_num);
 	device_remove_file(&ubi->dev, &dev_dt_threshold);
 	device_remove_file(&ubi->dev, &dev_rd_threshold);
drivers/mtd/ubi/ubi.h +3 -0
index ed04de2..1079517 100644
@@ -491,6 +491,7 @@ struct ubi_debug_info {
  *				for more info
  * @dt_threshold: data retention threshold. See UBI_DT_THRESHOLD
  *				for more info
+ * @scan_in_progress: true if scanning of device PEBs is in progress
  *
  * @flash_size: underlying MTD device size (in bytes)
  * @peb_count: count of physical eraseblocks on the MTD device
@@ -595,6 +596,7 @@ struct ubi_device {
 	char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
 	int rd_threshold;
 	int dt_threshold;
+	bool scan_in_progress;
 
 
 	/* I/O sub-system's stuff */
@@ -873,6 +875,7 @@ int ubi_is_erase_work(struct ubi_work *wrk);
 void ubi_refill_pools(struct ubi_device *ubi);
 int ubi_ensure_anchor_pebs(struct ubi_device *ubi);
 int ubi_in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root);
+int ubi_wl_scan_all(struct ubi_device *ubi);
 
 /* io.c */
 int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
drivers/mtd/ubi/wl.c +140 -3

168 lines not on this page · raw message

Signature · 3 lines
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, 
a Linux Foundation Collaborative Project