Skip to contentSkip to conversation

UBI: implement per-volume update

RFC PATCH In review Artem Bityutskiy 4 participants 7 messages Feb 1, 2007

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

cover UBI: implement per-volume update

Hello Alexander,

I've implemented per-volume update based on your patch. Thank you for your work - I have added a credit statement for you in the code.

In addition to what your patch does, this patch cleans-up and more comments and makes them consistent to new update marker stuff. It also removes the insane ivol_data from the VID header. It refines semantics of 'corrupted' flag better.

Please, review it and try it.

#1 lore raw

RFC PATCH 1/1 UBI: implement per-volume update

From: Artem Bityutskiy <[email protected]>
Date: Thu, 1 Feb 2007 12:01:02 +0200
Subject: [PATCH] [MTD] UBI: implement per-volume update

This patch removes the global update marker support and everything related to it. Now we have per-volume update marker bit in the volume table. This makes us incompatible with older UBI images but this is not a big deal - UBI is not used so widely so far and we can afford dropping legacy stuff now.

This patch is based on Alexander Schmidt's patch.

---
 drivers/mtd/ubi/cdev.c    |    2 +-
 drivers/mtd/ubi/debug.c   |    1 +
 drivers/mtd/ubi/eba.c     |    8 +--
 drivers/mtd/ubi/eba.h     |    5 +-
 drivers/mtd/ubi/gluebi.c  |    3 +-
 drivers/mtd/ubi/misc.c    |   26 -----
 drivers/mtd/ubi/misc.h    |   11 --
 drivers/mtd/ubi/sysfs.c   |   25 +++++
 drivers/mtd/ubi/uif.c     |    2 +-
 drivers/mtd/ubi/upd.c     |  247 ++++++++-------------------------------------
 drivers/mtd/ubi/upd.h     |   24 +----
 drivers/mtd/ubi/volmgmt.c |    4 -
 drivers/mtd/ubi/vtbl.c    |  125 ++++++++++++++++-------
 drivers/mtd/ubi/vtbl.h    |   29 ++++--
 include/mtd/ubi-header.h  |  160 ++++++++++++-----------------
 15 files changed, 250 insertions(+), 422 deletions(-)
drivers/mtd/ubi/cdev.c +1 -1
index 1ca67a3..8a201aa 100644
@@ -1031,7 +1031,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
 			 len, vol_id, lnum, off);
 
 		err = ubi_eba_write_leb(ubi, vol_id, lnum, tbuf, off, len,
-					UBI_DATA_UNKNOWN, &written, NULL);
+					UBI_DATA_UNKNOWN, &written);
 		if (unlikely(err)) {
 			count -= written;
 			*offp += written;
drivers/mtd/ubi/debug.c +1 -0
index c52716c..ec2e6ea 100644
@@ -846,6 +846,7 @@ void ubi_dbg_dump_vol_tbl_record(const struct ubi_vol_tbl_record *r)
 	dump_msg("alignment       %d", ubi32_to_cpu(r->alignment));
 	dump_msg("data_pad        %d", ubi32_to_cpu(r->data_pad));
 	dump_msg("vol_type        %d", (int)r->vol_type);
+	dump_msg("upd_marker      %d", (int)r->upd_marker);
 	dump_msg("name_len        %zd", name_len);
 
 	if (r->name[0] == '\0') {
drivers/mtd/ubi/eba.c +1 -7
index 331897d..1999d79 100644
@@ -503,8 +503,7 @@ out_unlock:
 
 int ubi_eba_write_leb(const struct ubi_info *ubi, int vol_id, int lnum,
 		      const void *buf, int offset, size_t len,
-		      enum ubi_data_type dtype, size_t *written,
-		      const void *ivol_data)
+		      enum ubi_data_type dtype, size_t *written)
 {
 	int err, pnum, tries = 0;
 	uint32_t leb_ver;
@@ -573,11 +572,6 @@ retry:
 	vid_hdr->lnum = cpu_to_ubi32(lnum);
 	vid_hdr->compat = ubi_vtbl_get_compat(ubi, vol_id);
 	vid_hdr->data_pad = cpu_to_ubi32(vtr->data_pad);
-	if (ivol_data) {
-		ubi_assert(ubi_is_ivol(vol_id));
-		memcpy(&vid_hdr->ivol_data[0], ivol_data,
-		       UBI_VID_HDR_IVOL_DATA_SIZE);
-	}
 
 	pnum = ubi_wl_get_peb(ubi, dtype);
 	if (unlikely(pnum < 0)) {
drivers/mtd/ubi/eba.h +1 -4
index d0e4c48..f58b5e6 100644
@@ -138,8 +138,6 @@ int ubi_eba_read_leb(const struct ubi_info *ubi, int vol_id, int lnum,
  * @len: how many bytes to write
  * @dtype: data type
  * @written: how many bytes were actually written
- * @ivol_data: private data to put to the VID header (used only for internal
- * volumes)
  *
  * This function writes data to a logical eraseblock of a dynamic volume.
  * Returns zero in case of success and a negative error code in case of
@@ -148,8 +146,7 @@ int ubi_eba_read_leb(const struct ubi_info *ubi, int vol_id, int lnum,
  */
 int ubi_eba_write_leb(const struct ubi_info *ubi, int vol_id, int lnum,
 		      const void *buf, int offset, size_t len,
-		      enum ubi_data_type dtype, size_t *written,
-		      const void *ivol_data);
+		      enum ubi_data_type dtype, size_t *written);
 
 /**
  * ubi_eba_write_leb_st - write data to a logical eraseblock of a static volume.
drivers/mtd/ubi/gluebi.c +1 -2
index 4250854..924e8f4 100644
@@ -283,8 +283,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
 			   to_write, vol->vol_id, lnum, offs);
 
 		err = ubi_eba_write_leb(ubi, vol->vol_id, lnum, buf, offs,
-					to_write, UBI_DATA_UNKNOWN, retlen,
-					NULL);
+					to_write, UBI_DATA_UNKNOWN, retlen);
 		written += *retlen;
 		if (unlikely(err))
 			break;
drivers/mtd/ubi/misc.c +0 -26
index 49eb4fa..1a80fc2 100644
@@ -26,7 +26,6 @@
 #include "debug.h"
 #include "eba.h"
 #include "alloc.h"
-#include "wl.h"
 #include "io.h"
 #include "account.h"
 #include "background.h"
@@ -103,31 +102,6 @@ int ubi_calc_data_len(const struct ubi_info *ubi, const uint8_t *buf,
 	return length;
 }
 
-int ubi_wipe_out_volume(const struct ubi_info *ubi, int vol_id)
-{
-	int i, err;
-	const struct ubi_vtbl_vtr *vtr;
-
-	ubi_assert(vol_id >= 0 && vol_id < ubi->acc->max_volumes);
-
-	vtr = ubi_vtbl_get_vtr(ubi, vol_id);
-	for (i = 0; i < vtr->reserved_pebs; i++) {
-		cond_resched();
-
-		err = ubi_eba_erase_leb(ubi, vol_id, i);
-		if (unlikely(err))
-			return err;
-	}
-
-	err = ubi_wl_erase_flush(ubi);
-	if (err)
-		return err;
-
-	ubi_vtbl_set_data_len(ubi, vol_id, 0);
-
-	return 0;
-}
-
 void ubi_ro_mode(const struct ubi_info *ubi)
 {
 	ubi_bgt_disable(ubi);
drivers/mtd/ubi/misc.h +0 -11
index dc45b7b..f6f2ced 100644
@@ -112,17 +112,6 @@ int ubi_calc_data_len(const struct ubi_info *ubi, const uint8_t *buf,
 		      size_t length);
 
 /**
- * ubi_wipe_out_volume - wipe out an UBI volume.
- *
- * @ubi: the UBI device description object
- * @vol_id: ID of the volume to free
- *
- * This function erases all the volume's eraseblocks. Returns zero in case of
- * success, and a negative error code in case of failure.
- */
-int ubi_wipe_out_volume(const struct ubi_info *ubi, int vol_id);
-
-/**
  * ubi_ro_mode - switch UBI to read-only mode.
  *
  * @ubi: the UBI device description object
drivers/mtd/ubi/sysfs.c +25 -0
index 182d1c1..6ead635 100644
@@ -205,6 +205,7 @@ static ssize_t vol_corrupted_show(struct class_device *dev, char *buf);
 static ssize_t vol_alignment_show(struct class_device *dev, char *buf);
 static ssize_t vol_usable_eb_size_show(struct class_device *dev, char *buf);
 static ssize_t vol_data_bytes_show(struct class_device *dev, char *buf);
+static ssize_t vol_upd_marker_show(struct class_device *dev, char *buf);
 
 /*
  * Class device attributes corresponding to files in
@@ -224,6 +225,8 @@ static struct class_device_attribute vol_usable_eb_size =
 	__ATTR(usable_eb_size, S_IRUGO, vol_usable_eb_size_show, NULL);
 static struct class_device_attribute vol_data_bytes =
 	__ATTR(data_bytes, S_IRUGO, vol_data_bytes_show, NULL);
+static struct class_device_attribute vol_upd_marker =
+	__ATTR(upd_marker, S_IRUGO, vol_upd_marker_show, NULL);
 
 /*
  * Note, this function does not free allocated resources in case of failure -
@@ -264,11 +267,15 @@ int ubi_sysfs_vol_init(const struct ubi_info *ubi, struct ubi_uif_volume *vol)
 	err = class_device_create_file(&vol->dev, &vol_data_bytes);
 	if (err)
 		return err;
+	err = class_device_create_file(&vol->dev, &vol_upd_marker);
+	if (err)
+		return err;
 	return 0;
 }
 
 void ubi_sysfs_vol_close(struct ubi_uif_volume *vol)
 {
+	class_device_remove_file(&vol->dev, &vol_upd_marker);
 	class_device_remove_file(&vol->dev, &vol_data_bytes);
 	class_device_remove_file(&vol->dev, &vol_usable_eb_size);
 	class_device_remove_file(&vol->dev, &vol_alignment);
@@ -549,3 +556,21 @@ static ssize_t vol_data_bytes_show(struct class_device *dev, char *buf)
 	spin_unlock(&vol->vol_lock);
 	return ret;
 }
+
+static ssize_t vol_upd_marker_show(struct class_device *dev, char *buf)
+{
+	int ret;
+	const struct ubi_vtbl_vtr *vtr;
+	struct ubi_uif_volume *vol = dev2vol(dev);
+
+	spin_lock(&vol->vol_lock);
+	if (vol->removed) {
+		spin_unlock(&vol->vol_lock);
+		dbg_uif("volume %d was removed", vol->vol_id);
+		return -EIO;
+	}
+	vtr = ubi_vtbl_get_vtr(vol->ubi, vol->vol_id);
+	ret = sprintf(buf, "%lld\n", vtr->upd_marker);
+	spin_unlock(&vol->vol_lock);
+	return ret;
+}
drivers/mtd/ubi/uif.c +1 -1
index bc0d6fe..6fa4945 100644
@@ -462,7 +462,7 @@ int ubi_eraseblock_write(struct ubi_vol_desc *udesc, int lnum, const void *buf,
 	}
 
 	return ubi_eba_write_leb(ubi, vol_id, lnum, buf, offset, len, dtype,
-				 written, NULL);
+				 written);
 }
 EXPORT_SYMBOL_GPL(ubi_eraseblock_write);
 
drivers/mtd/ubi/upd.c +44 -203

358 lines not on this page · raw message

drivers/mtd/ubi/upd.h +4 -20
index ba05e10..69a9e5e 100644
@@ -31,6 +31,9 @@
  *
  * Note, in general it is possible to implement the update operation as a
  * transaction with a possibility to roll-back. But this is far more complex.
+ *
+ * This implementation does not support concurrent updates but it is not
+ * difficult to implement this.
  */
 
 #ifndef __UBI_UPD_H__
@@ -38,7 +41,6 @@
 
 #include <linux/mutex.h>
 #include <linux/types.h>
-#include <mtd/ubi-header.h>
 
 struct ubi_info;
 struct ubi_scan_info;
@@ -92,21 +94,6 @@ int ubi_upd_write_data(const struct ubi_info *ubi, int vol_id,
 int ubi_upd_abort(const struct ubi_info *ubi, int vol_id);
 
 /**
- * ubi_upd_clean - clean the update marker.
- *
- * @ubi: the UBI device description object
- * @vol_id: ID of the volume to clean
- *
- * This function cleans the update state of volume @vol_id, i.e., if there is
- * an update marker belonging to this volume, the update marker is removed.
- * This function returns zero in case of success and a negative error code in
- * case of failure.
- *
- * TODO: to be removed.
- */
-int ubi_upd_clean(const struct ubi_info *ubi, int vol_id);
-
-/**
  * ubi_upd_init_scan - initialize the update volume unit using scanning
  * information.
  *
@@ -129,14 +116,12 @@ void ubi_upd_close(const struct ubi_info *ubi);
  * struct ubi_upd_info - UBI update unit description data structure.
  *
  * @updating: if any volume is being updated at the moment
- * @vol_id: which volume utilizes the update marker at the moment (%-1 means
- * the update marker is not used)
+ * @vol_id: which volume utilizes the update marker at the moment
  * @upd_ebs: how many eraseblocks are going to be updated
  * @upd_received: how many bytes were already received by the update unit
  * @upd_bytes: how many more bytes are expected to be received
  * @upd_buf: a buffer which is used to collect update data during the update
  * operation
- * @hdr_data: data put to the VID header of the update marker eraseblock
  * @mutex: serializes access to the volume update capability
  */
 struct ubi_upd_info {
@@ -146,7 +131,6 @@ struct ubi_upd_info {
 	long long upd_received;              /* private */
 	long long upd_bytes;                 /* private */
 	void *upd_buf;                       /* private */
-	struct ubi_vid_hdr_upd_vol hdr_data; /* private */
 	struct mutex mutex;                  /* private */
 };
 
drivers/mtd/ubi/volmgmt.c +0 -4
index 8a9bcb1..bd1f709 100644
@@ -151,10 +151,6 @@ int ubi_vmt_rmvol(const struct ubi_info *ubi, int vol_id)
 	if (err)
 		goto out_unlock;
 
-	err = ubi_upd_clean(ubi, vol_id);
-	if (err)
-		goto out_unlock;
-
 	err = ubi_eba_rmvol(ubi, vol_id);
 	if (err)
 		goto out_unlock;
drivers/mtd/ubi/vtbl.c +85 -40

227 lines not on this page · raw message

drivers/mtd/ubi/vtbl.h +20 -9
index 331886d..df7480c 100644
@@ -123,19 +123,30 @@ int ubi_vtbl_rmvol(const struct ubi_info *ubi, int vol_id);
 int ubi_vtbl_rsvol(const struct ubi_info *ubi, int vol_id, int reserved_pebs);
 
 /**
- * ubi_vtbl_set_data_len - set new volume data length.
+ * ubi_vtbl_set_upd_marker - set the update marker flag.
  *
  * @ubi: the UBI device description object
- * @vol_id: ID of the volume to set data fields for
+ * @vol_id: ID of the volume
+ *
+ * This function sets the update marker flag for volumr @vol_id. Returns zero
+ * in case of success and a negative error code in case of failure.
+ */
+int ubi_vtbl_set_upd_marker(const struct ubi_info *ubi, int vol_id);
+
+/**
+ * ubi_vtbl_clear_upd_marker - clear the update marker flag.
+ *
+ * @ubi: the UBI device description object
+ * @vol_id: ID of the volume
  * @bytes: new data size in bytes
  *
- * This function sets new volume data size and cleans the "corrupted" flag. As
- * UBI does not care about the contents of dynamic volume, this function just
- * returns in case of a dynamic volume. This function returns zero in case of
- * success and a negative error code in case of failure.
+ * This function clears the update marker for volume @vol_id, sets new volume
+ * data size and cleans the "corrupted" flag (static volume s only). This
+ * function returns zero in case of success and a negative error code in case
+ * of failure.
  */
-int ubi_vtbl_set_data_len(const struct ubi_info *ubi, int vol_id,
-			  long long bytes);
+int ubi_vtbl_clear_upd_marker(const struct ubi_info *ubi, int vol_id,
+			      long long bytes);
 
 /**
  * ubi_vtbl_set_corrupted - mark a volume as 'corrupted'.
@@ -199,7 +210,7 @@ static inline int ubi_is_ivol(int vol_id)
  */
 static inline int ubi_ivol_is_known(int vol_id)
 {
-	return vol_id == UBI_LAYOUT_VOL_ID || vol_id == UBI_UPDATE_VOL_ID;
+	return vol_id == UBI_LAYOUT_VOL_ID;
 }
 
 /**
include/mtd/ubi-header.h +66 -94

274 lines not on this page · raw message

Signature · 1 line
1.4.4.2
#2 lore raw
Quoted 5 lines · Artem Bityutskiy

This patch removes the global update marker support and everything related to it. Now we have per-volume update marker bit in the volume table. This makes us incompatible with older UBI images but this is not a big deal - UBI is not used so widely so far and we can afford dropping legacy stuff now.

Uuurgh. Incompatible in what way ? Does this mean you cannot boot from an existing image anymore ?

tglx

#3 lore raw
Quoted 9 lines · Thomas Gleixner
Quoted 5 lines · Artem Bityutskiy

This patch removes the global update marker support and everything related to it. Now we have per-volume update marker bit in the volume table. This makes us incompatible with older UBI images but this is not a big deal - UBI is not used so widely so far and we can afford dropping legacy stuff now.

Uuurgh. Incompatible in what way ? Does this mean you cannot boot from an existing image anymore ?

Right - it will reject it. Does it hurt you much?

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
#4 lore raw
In reply to Thomas Gleixner
Quoted 9 lines · Thomas Gleixner
Quoted 5 lines · Artem Bityutskiy

This patch removes the global update marker support and everything related to it. Now we have per-volume update marker bit in the volume table. This makes us incompatible with older UBI images but this is not a big deal - UBI is not used so widely so far and we can afford dropping legacy stuff now.

Uuurgh. Incompatible in what way ? Does this mean you cannot boot from an existing image anymore ?

Err, actually only those which have update marker on flash. If you do not have it - it should be fine.

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
#5 lore raw
In reply to Thomas Gleixner

Hi Thomas,

Quoted 9 lines · Thomas Gleixner
Quoted 5 lines · Artem Bityutskiy

This patch removes the global update marker support and everything related to it. Now we have per-volume update marker bit in the volume table. This makes us incompatible with older UBI images but this is not a big deal - UBI is not used so widely so far and we can afford dropping legacy stuff now.

Uuurgh. Incompatible in what way ? Does this mean you cannot boot from an existing image anymore ?

No if that would be the case, I would have objected to the patch. What it should do is to remove the need to have the update marker block. Instead of the update marker block Alexander is using a flag in the volume info table per volume to indicate that an update is going on.

Quoted 2 lines

tglx

The compatibility issue is that if you want to update a system with a not yet cleaned up "old style update marker" the new kernel does not know what to do with the now unknown ubi-update-volume. The compatibility flag we decided for the update-volume is "reject", which will cause ubi not to accept the mtd.

Frank

#6 lore raw
In reply to Artem Bityutskiy

Hi Artem,

I have tested and reviewed the patch, it works fine!

Regards,
Alexander Schmidt

Quoted 16 lines · Artem Bityutskiy

Hello Alexander,

I've implemented per-volume update based on your patch. Thank you for your work - I have added a credit statement for you in the code.

In addition to what your patch does, this patch cleans-up and more comments and makes them consistent to new update marker stuff. It also removes the insane ivol_data from the VID header. It refines semantics of 'corrupted' flag better.

Please, review it and try it.

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/