Skip to contentSkip to conversation

UBI: introduce atomic LEB change ioctl

PATCH In review Artem Bityutskiy 2 participants 4 messages Jan 24, 2008 – Jan 28, 2008

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

PATCH 1/1 UBI: introduce atomic LEB change ioctl

Quoted 1 line

From e405cf1dc645e7931df0e47ee7408d5251e2d9d0 Mon Sep 17 00:00:00 2001

From: Artem Bityutskiy <[email protected]>
Date: Thu, 24 Jan 2008 16:15:14 +0200
Subject: [PATCH] UBI: introduce atomic LEB change ioctl

We have to be able to change individual LEBs for utilities like ubifsck, ubifstune. For example, ubifsck has to be able to fix errors on the media, ubifstune has to be able to change the the superblock, hence this ioctl.

---
 include/linux/mtd/ubi.h |   17 ---------------
 include/mtd/ubi-user.h  |   51 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 47 insertions(+), 21 deletions(-)
include/linux/mtd/ubi.h +0 -17
index c4abe03..f71201d 100644
@@ -26,23 +26,6 @@
 #include <mtd/ubi-user.h>
 
 /*
- * UBI data type hint constants.
- *
- * UBI_LONGTERM: long-term data
- * UBI_SHORTTERM: short-term data
- * UBI_UNKNOWN: data persistence is unknown
- *
- * These constants are used when data is written to UBI volumes in order to
- * help the UBI wear-leveling unit to find more appropriate physical
- * eraseblocks.
- */
-enum {
-	UBI_LONGTERM = 1,
-	UBI_SHORTTERM,
-	UBI_UNKNOWN
-};
-
-/*
  * enum ubi_open_mode - UBI volume open mode constants.
  *
  * UBI_READONLY: read-only mode
include/mtd/ubi-user.h +47 -4

96 lines not on this page · raw message

Signature · 1 line
1.5.3.4
#1 lore raw

PATCH 1/1 UBI: implement atomic LEB change ioctl

Quoted 1 line

From 7e8210bd9165ba279ddacd0e4fb28891318b9b66 Mon Sep 17 00:00:00 2001

From: Artem Bityutskiy <[email protected]>
Date: Thu, 24 Jan 2008 18:48:21 +0200
Subject: [PATCH] UBI: implement atomic LEB change ioctl

---
 drivers/mtd/ubi/cdev.c |   72 +++++++++++++++++++++++++++++------
 drivers/mtd/ubi/ubi.h  |   27 +++++++++++--
 drivers/mtd/ubi/upd.c  |   99 ++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 178 insertions(+), 20 deletions(-)
drivers/mtd/ubi/cdev.c +60 -12
index 0c4044d..9d6aae5 100644
@@ -132,8 +132,15 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
 	if (vol->updating) {
 		ubi_warn("update of volume %d not finished, volume is damaged",
 			 vol->vol_id);
+		ubi_assert(!vol->changing_leb);
 		vol->updating = 0;
 		vfree(vol->upd_buf);
+	} else if (vol->changing_leb) {
+		dbg_msg("only %lld of %lld bytes received for atomic LEB change"
+			" for volume %d:%d, cancel", vol->upd_received,
+			vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id);
+		vol->changing_leb = 0;
+		vfree(vol->upd_buf);
 	}
 
 	ubi_close_volume(desc);
@@ -351,24 +358,32 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
 	struct ubi_volume *vol = desc->vol;
 	struct ubi_device *ubi = vol->ubi;
 
-	if (!vol->updating)
+	if (!vol->updating && !vol->changing_leb)
 		return vol_cdev_direct_write(file, buf, count, offp);
 
-	err = ubi_more_update_data(ubi, vol, buf, count);
+	if (vol->updating)
+		err = ubi_more_update_data(ubi, vol, buf, count);
+	else
+		err = ubi_more_leb_change_data(ubi, vol, buf, count);
+
 	if (err < 0) {
-		ubi_err("cannot write %zd bytes of update data, error %d",
+		ubi_err("cannot accept more %zd bytes of data, error %d",
 			count, err);
 		return err;
 	}
 
 	if (err) {
 		/*
-		 * Update is finished, @err contains number of actually written
-		 * bytes now.
+		 * The operation is finished, @err contains number of actually
+		 * written bytes.
 		 */
 		count = err;
 
-		vol->updating = 0;
+		if (vol->changing_leb) {
+			revoke_exclusive(desc, UBI_READWRITE);
+			return count;
+		}
+
 		err = ubi_check_volume(ubi, vol->vol_id);
 		if (err < 0)
 			return err;
@@ -433,6 +448,43 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
 		break;
 	}
 
+	/* Atomic logical eraseblock change command */
+	case UBI_IOCEBCH:
+	{
+		struct ubi_leb_change_req req;
+
+		err = copy_from_user(&req, argp,
+				     sizeof(struct ubi_leb_change_req));
+		if (err) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (desc->mode == UBI_READONLY ||
+		    vol->vol_type == UBI_STATIC_VOLUME) {
+			err = -EROFS;
+			break;
+		}
+
+		/* Validate the request */
+		err = -EINVAL;
+		if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
+		    req.bytes < 0 || req.lnum >= vol->usable_leb_size)
+			break;
+		if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
+		    req.dtype != UBI_UNKNOWN)
+			break;
+
+		err = get_exclusive(desc);
+		if (err < 0)
+			break;
+
+		err = ubi_start_leb_change(ubi, vol, &req);
+		if (req.bytes == 0)
+			revoke_exclusive(desc, UBI_READWRITE);
+		break;
+	}
+
 #ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
 	/* Logical eraseblock erasure command */
 	case UBI_IOCEBER:
@@ -445,7 +497,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
 			break;
 		}
 
-		if (desc->mode == UBI_READONLY) {
+		if (desc->mode == UBI_READONLY ||
+		    vol->vol_type == UBI_STATIC_VOLUME) {
 			err = -EROFS;
 			break;
 		}
@@ -455,11 +508,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
 			break;
 		}
 
-		if (vol->vol_type != UBI_DYNAMIC_VOLUME) {
-			err = -EROFS;
-			break;
-		}
-
 		dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
 		err = ubi_eba_unmap_leb(ubi, vol, lnum);
 		if (err)
drivers/mtd/ubi/ubi.h +23 -4
index 3a88cf1..4577106 100644
@@ -158,15 +158,23 @@ struct ubi_volume_desc;
  * @name: volume name
  *
  * @upd_ebs: how many eraseblocks are expected to be updated
- * @upd_bytes: how many bytes are expected to be received
- * @upd_received: how many update bytes were already received
- * @upd_buf: update buffer which is used to collect update data
+ * @ch_lnum: LEB number which is being changing by the atomic LEB change
+ *           operation
+ * @ch_dtype: data persistency type which is being changing by the atomic LEB
+ *            change operation
+ * @upd_bytes: how many bytes are expected to be received for volume update or
+ *             atomic LEB change
+ * @upd_received: how many bytes were already received for volume update or
+ *                atomic LEB change
+ * @upd_buf: update buffer which is used to collect update data or data for
+ *           atomic LEB change
  *
  * @eba_tbl: EBA table of this volume (LEB->PEB mapping)
  * @checked: %1 if this static volume was checked
  * @corrupted: %1 if the volume is corrupted (static volumes only)
  * @upd_marker: %1 if the update marker is set for this volume
  * @updating: %1 if the volume is being updated
+ * @changing_leb: %1 if the atomic LEB change ioctl command is in progress
  *
  * @gluebi_desc: gluebi UBI volume descriptor
  * @gluebi_refcount: reference count of the gluebi MTD device
@@ -202,6 +210,8 @@ struct ubi_volume {
 	char name[UBI_VOL_NAME_MAX+1];
 
 	int upd_ebs;
+	int ch_lnum;
+	int ch_dtype;
 	long long upd_bytes;
 	long long upd_received;
 	void *upd_buf;
@@ -211,9 +221,14 @@ struct ubi_volume {
 	int corrupted:1;
 	int upd_marker:1;
 	int updating:1;
+	int changing_leb:1;
 
 #ifdef CONFIG_MTD_UBI_GLUEBI
-	/* Gluebi-related stuff may be compiled out */
+	/*
+	 * Gluebi-related stuff may be compiled out.
+	 * TODO: this should not be built into UBI but should be a separate
+	 * ubimtd driver which works on top of UBI and emulates MTD devices.
+	 */
 	struct ubi_volume_desc *gluebi_desc;
 	int gluebi_refcount;
 	struct mtd_info gluebi_mtd;
@@ -427,6 +442,10 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
 		     long long bytes);
 int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
 			 const void __user *buf, int count);
+int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
+			 const struct ubi_leb_change_req *req);
+int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
+			     const void __user *buf, int count);
 
 /* misc.c */
 int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length);
drivers/mtd/ubi/upd.c +95 -4

132 lines not on this page · raw message

Signature · 1 line
1.5.3.4
#2 lore raw
In reply to Artem Bityutskiy
Quoted 9 lines · On Thu, 24 Jan 2008 18:54:53 +0200 Artem Bityutskiy <[email protected]>…
Quoted 1 line

From e405cf1dc645e7931df0e47ee7408d5251e2d9d0 Mon Sep 17 00:00:00 2001

From: Artem Bityutskiy <[email protected]>
Date: Thu, 24 Jan 2008 16:15:14 +0200
Subject: [PATCH] UBI: introduce atomic LEB change ioctl

We have to be able to change individual LEBs for utilities like ubifsck, ubifstune. For example, ubifsck has to be able to fix errors on the media, ubifstune has to be able to change the the superblock, hence this ioctl.

Could you explain a bit more? What exactly does "atomic" mean?

This seems like it's similar to volume update, only on a LEB level right? If so, could you make volume update just use this or somehow combine them?

Maybe I've just been away from UBI too long. It sounds cool, but I don't fully understand what the intention is.

josh

#3 lore raw
Quoted 8 lines · Josh Boyer

Could you explain a bit more? What exactly does "atomic" mean?

This seems like it's similar to volume update, only on a LEB level right? If so, could you make volume update just use this or somehow combine them?

Maybe I've just been away from UBI too long. It sounds cool, but I don't fully understand what the intention is.

Josh,

I've updated the UBI documentation in order to answer your question. Any documentation improvements and spelling fixes are welcome.

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)