From: Artem Bityutskiy <dedekind@infradead.org>
To: Alexander Schmidt <alexs@linux.vnet.ibm.com>
Cc: linux-mtd@lists.infradead.org
Subject: [RFC] [PATCH 1/1] [MTD] UBI: implement per-volume update
Date: Thu, 01 Feb 2007 12:21:11 +0200 [thread overview]
Message-ID: <20070201102111.15629.24289.sendpatchset@localhost.localdomain> (raw)
In-Reply-To: <20070201102105.15629.61206.sendpatchset@localhost.localdomain>
From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
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.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
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 ++++--
| 160 ++++++++++++-----------------
15 files changed, 250 insertions(+), 422 deletions(-)
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 1ca67a3..8a201aa 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -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;
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index c52716c..ec2e6ea 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -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') {
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 331897d..1999d79 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -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)) {
diff --git a/drivers/mtd/ubi/eba.h b/drivers/mtd/ubi/eba.h
index d0e4c48..f58b5e6 100644
--- a/drivers/mtd/ubi/eba.h
+++ b/drivers/mtd/ubi/eba.h
@@ -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.
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index 4250854..924e8f4 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -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;
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 49eb4fa..1a80fc2 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -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);
diff --git a/drivers/mtd/ubi/misc.h b/drivers/mtd/ubi/misc.h
index dc45b7b..f6f2ced 100644
--- a/drivers/mtd/ubi/misc.h
+++ b/drivers/mtd/ubi/misc.h
@@ -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
diff --git a/drivers/mtd/ubi/sysfs.c b/drivers/mtd/ubi/sysfs.c
index 182d1c1..6ead635 100644
--- a/drivers/mtd/ubi/sysfs.c
+++ b/drivers/mtd/ubi/sysfs.c
@@ -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;
+}
diff --git a/drivers/mtd/ubi/uif.c b/drivers/mtd/ubi/uif.c
index bc0d6fe..6fa4945 100644
--- a/drivers/mtd/ubi/uif.c
+++ b/drivers/mtd/ubi/uif.c
@@ -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);
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 55db023..0773b98 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -17,6 +17,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Artem B. Bityutskiy
+ *
+ * Jan 2007: Alexander Schmidt, hacked per-volume update.
*/
#include <linux/mutex.h>
@@ -25,7 +27,6 @@
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/div64.h>
-#include <mtd/ubi-header.h>
#include "ubi.h"
#include "upd.h"
#include "wl.h"
@@ -38,12 +39,11 @@
#include "scan.h"
#include "debug.h"
-static int put_marker(const struct ubi_info *ubi, int vol_id);
-static int finish_update(const struct ubi_info *ubi);
+static int ubi_wipe_out_volume(const struct ubi_info *ubi, int vol_id);
int ubi_upd_start(const struct ubi_info *ubi, int vol_id, long long bytes)
{
- int err, rem, marker_present = 0;
+ int err, rem;
uint64_t tmp;
const struct ubi_vtbl_vtr *vtr;
struct ubi_upd_info *upd = ubi->upd;
@@ -57,45 +57,30 @@ int ubi_upd_start(const struct ubi_info *ubi, int vol_id, long long bytes)
bytes <= vtr->usable_leb_size * vtr->reserved_pebs);
mutex_lock(&upd->mutex);
- if (upd->vol_id != -1) {
- /* Hmm, the update marker is busy */
- err = -EBUSY;
- if (upd->updating) {
- dbg_upd("volume %d is being updated, update marker "
- "busy", upd->vol_id);
- goto out_unlock;
- } else if (upd->vol_id != vol_id) {
- dbg_upd("update was interrupted and the update marker "
- "is held by volume %d", upd->vol_id);
- goto out_unlock;
- }
- /*
- * The update marker on the flash media corresponds to our
- * volume. Proceed with the update operation.
- */
- marker_present = 1;
+ if (upd->updating == 1) {
+ dbg_err("volume %d is being updated", upd->vol_id);
+ mutex_unlock(&upd->mutex);
+ return -EBUSY;
}
upd->updating = 1;
upd->vol_id = vol_id;
- if (!marker_present) {
- err = put_marker(ubi, vol_id);
- if (err)
- goto out_unlock;
- }
+ /* Set the update marker first */
+ err = ubi_vtbl_set_upd_marker(ubi, vol_id);
+ if (err)
+ goto out_unlock;
- /* Before updating, we wipe out volume */
+ /* Before updating, we wipe out the volume */
err = ubi_wipe_out_volume(ubi, vol_id);
if (err)
goto out_unlock;
if (bytes == 0) {
/* Zero bytes means the volume just has to be erased */
- err = finish_update(ubi);
- if (err)
- goto out_unlock;
+ err = ubi_vtbl_clear_upd_marker(ubi, vol_id, 0);
+ goto out_unlock;
}
tmp = bytes;
@@ -138,11 +123,8 @@ int ubi_upd_write_data(const struct ubi_info *ubi, int vol_id,
mutex_lock(&upd->mutex);
- if (!upd->updating || upd->vol_id != vol_id) {
+ if (unlikely(!upd->updating || upd->vol_id != vol_id)) {
dbg_err("volume %d update was not started", vol_id);
- if (upd->vol_id != -1)
- dbg_err("update marker belongs to volume %d",
- upd->vol_id);
err = -EINVAL;
goto out_unlock;
}
@@ -249,9 +231,11 @@ int ubi_upd_write_data(const struct ubi_info *ubi, int vol_id,
ubi_assert(upd->upd_received <= upd->upd_bytes);
if (upd->upd_received == upd->upd_bytes) {
- err = finish_update(ubi);
- if (err == 0)
- err = 1;
+ /* The update is finished, clear the update marker */
+ upd->updating = 0;
+ err = ubi_vtbl_clear_upd_marker(ubi, vol_id, upd->upd_bytes);
+ if (err == 0)
+ err = 1;
}
out_unlock:
@@ -261,53 +245,28 @@ out_unlock:
int ubi_upd_abort(const struct ubi_info *ubi, int vol_id)
{
+ int err = 0;
struct ubi_upd_info *upd = ubi->upd;
mutex_lock(&upd->mutex);
- if (upd->vol_id == vol_id) {
+ if (upd->updating && upd->vol_id == vol_id) {
dbg_upd("aborting volume %d update - it is damaged since now",
vol_id);
upd->updating = 0;
- } else
+ } else {
dbg_upd("volume %d is not under update", vol_id);
+ err = -EINVAL;
+ }
mutex_unlock(&upd->mutex);
- return 0;
-}
-
-static int remove_marker(const struct ubi_info *ubi);
-
-int ubi_upd_clean(const struct ubi_info *ubi, int vol_id)
-{
- int err = 0;
- struct ubi_upd_info *upd = ubi->upd;
-
- mutex_lock(&upd->mutex);
-
- if (!upd->updating || vol_id != upd->vol_id)
- goto out_unlock;
-
- dbg_upd("clean update marker for volume %d", vol_id);
-
- err = remove_marker(ubi);
- if (err)
- goto out_unlock;
-
- upd->vol_id = -1;
-
-out_unlock:
- mutex_unlock(&upd->mutex);
- return 0;
+ return err;
}
int ubi_upd_init_scan(struct ubi_info *ubi, struct ubi_scan_info *si)
{
int err;
- struct ubi_scan_volume *sv;
- struct ubi_vid_hdr *vid_hdr;
struct ubi_upd_info *upd;
const struct ubi_vtbl_vtr *vtr;
- const struct ubi_scan_leb *seb;
dbg_upd("initialize the update unit");
@@ -323,85 +282,11 @@ int ubi_upd_init_scan(struct ubi_info *ubi, struct ubi_scan_info *si)
}
mutex_init(&upd->mutex);
- upd->vol_id = -1;
-
- sv = ubi_scan_find_sv(si, UBI_UPDATE_VOL_ID);
- if (!sv) {
- dbg_upd("the update unit is initialized");
- return 0;
- }
-
-
- /*
- * The update marker was found - a volume update operation was
- * interrupted.
- */
-
- err = -EINVAL;
- if (sv->leb_count > 1) {
- /* There may be only one update marker */
- dbg_err("too many update markers %d", sv->leb_count);
- goto out_free_upd_buf;
- }
-
- seb = ubi_scan_find_seb(sv, 0);
- if (!seb) {
- dbg_err("bad update marker");
- goto out_free_upd_buf;
- }
-
- vid_hdr = ubi_zalloc_vid_hdr(ubi);
- if (!vid_hdr) {
- err = -ENOMEM;
- goto out_free_upd_buf;
- }
-
- err = ubi_io_read_vid_hdr(ubi, seb->pnum, vid_hdr, 1);
- if (unlikely(err < 0))
- goto out_vid_hdr;
- else if (unlikely(err > 0) && err != UBI_IO_BITFLIPS) {
- /*
- * Cannot read the update marker. But we read it earlier,
- * during scanning. No idea what happened. Don't erase it
- * anyway.
- */
- err = -EIO;
- goto out_vid_hdr;
- }
-
- memcpy(&upd->hdr_data, &vid_hdr->ivol_data[0],
- UBI_VID_HDR_IVOL_DATA_SIZE);
- upd->vol_id = ubi32_to_cpu(upd->hdr_data.vol_id);
- ubi_free_vid_hdr(ubi, vid_hdr);
-
- /* Check sanity */
- if (upd->vol_id < 0 || upd->vol_id >= ubi->acc->max_volumes) {
- ubi_err("bad volume ID %d in update marker",
- upd->vol_id);
- goto out_free_upd_buf;
- }
-
- ubi_warn("volume %d update was interrupted", upd->vol_id);
- vtr = ubi_vtbl_get_vtr(ubi, upd->vol_id);
- if (IS_ERR(vtr)) {
- /*
- * Update marker belongs to an non-existing volume. This may
- * happen if an unclean reboot happened during volume deletion.
- */
-
- err = remove_marker(ubi);
- if (err)
- goto out_free_upd_buf;
- upd->vol_id = -1;
- }
dbg_upd("the update unit is initialized");
+
return 0;
-out_vid_hdr:
- ubi_free_vid_hdr(ubi, vid_hdr);
-out_free_upd_buf:
- ubi_kfree(upd->upd_buf);
out_free_upd:
ubi_kfree(upd);
return err;
@@ -415,79 +300,35 @@ void ubi_upd_close(const struct ubi_info *ubi)
}
/**
- * put_marker - put update marker.
+ * ubi_wipe_out_volume - wipe out an UBI volume.
*
* @ubi: the UBI device description object
- * @vol_id: for which volume to put the update marker.
+ * @vol_id: ID of the volume to free
*
- * This function returns zero in case of success, and a negative error code in
- * case of failure.
+ * This function erases all the volume's eraseblocks. Returns zero in case of
+ * success, and a negative error code in case of failure.
*/
-static int put_marker(const struct ubi_info *ubi, int vol_id)
+static int ubi_wipe_out_volume(const struct ubi_info *ubi, int vol_id)
{
- int err;
- size_t written;
- struct ubi_upd_info *upd = ubi->upd;
-
- dbg_upd("put update marker for volume %d", vol_id);
- upd->hdr_data.vol_id = cpu_to_ubi32(vol_id);
- err = ubi_eba_write_leb(ubi, UBI_UPDATE_VOL_ID, 0, NULL, 0, 0,
- UBI_DATA_SHORTTERM, &written, &upd->hdr_data);
-
- return err;
-}
+ int i, err;
+ const struct ubi_vtbl_vtr *vtr;
-/**
- * remove_marker - remove update marker.
- *
- * @ubi: the UBI device description object
- *
- * This function returns zero in case of success, and a negative error code in
- * case of failure.
- */
-static int remove_marker(const struct ubi_info *ubi)
-{
- int err;
- struct ubi_upd_info *upd = ubi->upd;
+ ubi_assert(vol_id >= 0 && vol_id < ubi->acc->max_volumes);
- dbg_upd("remove update marker for volume %d", upd->vol_id);
+ vtr = ubi_vtbl_get_vtr(ubi, vol_id);
+ for (i = 0; i < vtr->reserved_pebs; i++) {
+ cond_resched();
- err = ubi_eba_erase_leb(ubi, UBI_UPDATE_VOL_ID, 0);
- if (err)
- return err;
+ err = ubi_eba_erase_leb(ubi, vol_id, i);
+ if (unlikely(err))
+ return err;
+ }
err = ubi_wl_erase_flush(ubi);
return err;
}
/**
- * finish_update - finish volume update.
- *
- * @ubi: the UBI device description object
- *
- * This function removes the clean marker from the media and finishes the
- * ongoing update operation. Returns zero in case of success and a negative
- * error code in case of failure.
- */
-static int finish_update(const struct ubi_info *ubi)
-{
- int err;
- struct ubi_upd_info *upd = ubi->upd;
-
- dbg_upd("finish volume %d update", upd->vol_id);
-
- upd->updating = 0;
-
- err = remove_marker(ubi);
- if (err)
- return err;
-
- ubi_vtbl_set_data_len(ubi, upd->vol_id, upd->upd_bytes);
- upd->vol_id = -1;
- return 0;
-}
-
-/**
* write_leb - write a portion of update data to a logical eraseblock.
*
* @ubi: the UBI device description object
@@ -539,7 +380,7 @@ static int write_leb(const struct ubi_info *ubi, int vol_id, int lnum,
len - l, vol_id, lnum);
err = ubi_eba_write_leb(ubi, vol_id, lnum, buf, 0, l,
- UBI_DATA_UNKNOWN, written, NULL);
+ UBI_DATA_UNKNOWN, written);
} else {
/*
* When writing to static volumes, and this is the last logical
diff --git a/drivers/mtd/ubi/upd.h b/drivers/mtd/ubi/upd.h
index ba05e10..69a9e5e 100644
--- a/drivers/mtd/ubi/upd.h
+++ b/drivers/mtd/ubi/upd.h
@@ -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 */
};
diff --git a/drivers/mtd/ubi/volmgmt.c b/drivers/mtd/ubi/volmgmt.c
index 8a9bcb1..bd1f709 100644
--- a/drivers/mtd/ubi/volmgmt.c
+++ b/drivers/mtd/ubi/volmgmt.c
@@ -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;
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 6b38b0d..6e69c4c 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -126,37 +126,83 @@ int ubi_vtbl_rsvol(const struct ubi_info *ubi, int vol_id, int reserved_pebs)
return err;
}
-int ubi_vtbl_set_data_len(const struct ubi_info *ubi, int vol_id,
- long long bytes)
+int ubi_vtbl_set_upd_marker(const struct ubi_info *ubi, int vol_id)
{
int err;
- struct ubi_vtbl_info *vtbl = ubi->vtbl;
- struct ubi_vtbl_vtr *vtr = &vtbl->vt[vol_id];
+ struct ubi_vtbl_vtr vtr;
+ const struct ubi_vtbl_info *vtbl = ubi->vtbl;
+
+ dbg_vtbl("set update marker for volume %d", vol_id);
+ /* Input arguments sanity check */
ubi_assert(vol_id >= 0 && vol_id < vtbl->vt_slots);
- ubi_assert(ubi->vtbl->vt[vol_id].reserved_pebs != 0);
+ ubi_assert(vtbl->vt[vol_id].reserved_pebs != 0);
ubi_assert(!ubi_is_ivol(vol_id));
- ubi_assert(bytes >= 0 &&
- bytes <= vtr->usable_leb_size * vtr->reserved_pebs);
- err = paranoid_check_vtr(ubi, vtr);
- if (err)
- return -EINVAL;
+ if (vtbl->vt[vol_id].upd_marker) {
+ dbg_vtbl("update marker is already set, do nothing");
+ return 0;
+ }
+
+ memcpy(&vtr, &vtbl->vt[vol_id], sizeof(struct ubi_vtbl_vtr));
+
+ vtr.name = strdup_len(vtbl->vt[vol_id].name,
+ vtbl->vt[vol_id].name_len);
+ if (!vtr.name)
+ return -ENOMEM;
+ vtr.upd_marker = 1;
- if (vtr->vol_type == UBI_DYNAMIC_VOLUME)
+ err = change_volume(ubi, vol_id, &vtr);
+ ubi_kfree(vtr.name);
+ return err;
+}
+
+int ubi_vtbl_clear_upd_marker(const struct ubi_info *ubi, int vol_id,
+ long long bytes)
+{
+ int err;
+ struct ubi_vtbl_vtr vtr;
+ const struct ubi_vtbl_info *vtbl = ubi->vtbl;
+
+ dbg_vtbl("clear update marker for volume %d", vol_id);
+
+ /* Input arguments sanity check */
+ ubi_assert(vol_id >= 0 && vol_id < vtbl->vt_slots);
+ ubi_assert(vtbl->vt[vol_id].reserved_pebs != 0);
+ ubi_assert(!ubi_is_ivol(vol_id));
+ ubi_assert(bytes >= 0 && bytes <= vtbl->vt[vol_id].usable_leb_size *
+ vtbl->vt[vol_id].reserved_pebs);
+
+ if (!vtbl->vt[vol_id].upd_marker) {
+ dbg_vtbl("update marker is already cleared, do nothing");
return 0;
+ }
- dbg_vtbl("set data length of static volume %d to %lld (was %lld)",
- vol_id, bytes, vtr->used_bytes);
- vtr->used_bytes = bytes;
- vtr->corrupted = 0;
- fill_ram_only_fields(ubi, vtr);
+ memcpy(&vtr, &vtbl->vt[vol_id], sizeof(struct ubi_vtbl_vtr));
- err = paranoid_check_vtr(ubi, vtr);
+ vtr.name = strdup_len(vtbl->vt[vol_id].name,
+ vtbl->vt[vol_id].name_len);
+ if (!vtr.name)
+ return -ENOMEM;
+ vtr.upd_marker = 0;
+
+ if (vtbl->vt[vol_id].vol_type == UBI_STATIC_VOLUME) {
+ dbg_vtbl("set data length of static volume %d to %lld",
+ vol_id, bytes);
+ vtr.used_bytes = bytes;
+ vtr.corrupted = 0;
+ fill_ram_only_fields(ubi, &vtr);
+ } else
+ ubi_assert(vtr.corrupted == 0);
+
+ err = paranoid_check_vtr(ubi, &vtbl->vt[vol_id]);
if (err)
- return -EINVAL;
+ return err;
- return 0;
+ err = change_volume(ubi, vol_id, &vtr);
+ ubi_kfree(vtr.name);
+
+ return err;
}
int ubi_vtbl_set_corrupted(const struct ubi_info *ubi, int vol_id)
@@ -173,6 +219,7 @@ int ubi_vtbl_set_corrupted(const struct ubi_info *ubi, int vol_id)
dbg_vtbl("mark static volume %d as corrupted", vol_id);
vtr->corrupted = 1;
}
+ /* TODO: should we have an asserd for dynamic volumes here? */
return 0;
}
@@ -211,8 +258,6 @@ int ubi_vtbl_get_compat(const struct ubi_info *ubi, int vol_id)
switch (vol_id) {
case UBI_LAYOUT_VOL_ID:
return UBI_LAYOUT_VOLUME_COMPAT;
- case UBI_UPDATE_VOL_ID:
- return UBI_UPDATE_VOLUME_COMPAT;
default:
BUG();
}
@@ -385,6 +430,8 @@ static int change_volume(const struct ubi_info *ubi,
if (!vol_tbl)
return -ENOMEM;
+ mutex_lock(&vtbl->mutex);
+
/* Generate the on-flash volume table contents */
for (i = 0; i < vtbl->vt_slots; i++) {
uint32_t crc;
@@ -395,7 +442,7 @@ static int change_volume(const struct ubi_info *ubi,
err = paranoid_check_vtr(ubi, tmp_vtr);
if (unlikely(err))
- goto out;
+ goto out_unlock;
if (unlikely(i == vol_id))
tmp_vtr = vtr;
@@ -409,6 +456,7 @@ static int change_volume(const struct ubi_info *ubi,
vol_tbl[i].reserved_pebs = cpu_to_ubi32(tmp_vtr->reserved_pebs);
vol_tbl[i].alignment = cpu_to_ubi32(tmp_vtr->alignment);
vol_tbl[i].data_pad = cpu_to_ubi32(tmp_vtr->data_pad);
+ vol_tbl[i].upd_marker = tmp_vtr->upd_marker;
if (tmp_vtr->vol_type == UBI_DYNAMIC_VOLUME)
vol_tbl[i].vol_type = UBI_VID_DYNAMIC;
else
@@ -423,9 +471,6 @@ static int change_volume(const struct ubi_info *ubi,
vol_tbl[i].crc = cpu_to_ubi32(crc);
}
-
- mutex_lock(&vtbl->mutex);
-
/* Update both volume table copies */
for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
size_t written;
@@ -442,7 +487,7 @@ static int change_volume(const struct ubi_info *ubi,
err = ubi_eba_write_leb(ubi, UBI_LAYOUT_VOL_ID, i, vol_tbl, 0,
vtbl->vt_size, UBI_DATA_LONGTERM,
- &written, NULL);
+ &written);
if (unlikely(err))
goto out_unlock;
}
@@ -469,7 +514,7 @@ static int change_volume(const struct ubi_info *ubi,
out_unlock:
mutex_unlock(&vtbl->mutex);
-out:
+
/*
* The volume table is probably in an inconsistent state now, so switch
* to read-only mode.
@@ -794,18 +839,6 @@ static void init_ivols(struct ubi_info *ubi)
vtr->used_ebs = vtr->reserved_pebs;
vtr->last_eb_bytes = vtr->reserved_pebs;
vtr->used_bytes = vtr->used_ebs * (io->leb_size - vtr->data_pad);
-
- /* The update volume */
- vtr = &vtbl->ivol_vtrs[1];
- vtr->reserved_pebs = UBI_UPDATE_VOLUME_EBS;
- vtr->alignment = 1;
- vtr->vol_type = UBI_DYNAMIC_VOLUME;
- vtr->name_len = sizeof(UBI_UPDATE_VOLUME_NAME) - 1;
- vtr->name = UBI_UPDATE_VOLUME_NAME;
- vtr->usable_leb_size = io->leb_size;
- vtr->used_ebs = vtr->reserved_pebs;
- vtr->last_eb_bytes = vtr->reserved_pebs;
- vtr->used_bytes = vtr->used_ebs * (io->leb_size - vtr->data_pad);
}
/**
@@ -954,6 +987,7 @@ static int vol_tbl_check(const struct ubi_info *ubi,
const struct ubi_vol_tbl_record *vol_tbl)
{
int i, reserved_pebs, alignment, data_pad, vol_type, name_len;
+ int upd_marker;
const char *name;
const struct ubi_vtbl_info *vtbl = ubi->vtbl;
const struct ubi_io_info *io = ubi->io;
@@ -967,6 +1001,7 @@ static int vol_tbl_check(const struct ubi_info *ubi,
reserved_pebs = ubi32_to_cpu(vol_tbl[i].reserved_pebs);
alignment = ubi32_to_cpu(vol_tbl[i].alignment);
data_pad = ubi32_to_cpu(vol_tbl[i].data_pad);
+ upd_marker = vol_tbl[i].upd_marker;
vol_type = vol_tbl[i].vol_type;
name_len = ubi16_to_cpu(vol_tbl[i].name_len);
name = &vol_tbl[i].name[0];
@@ -1028,6 +1063,11 @@ static int vol_tbl_check(const struct ubi_info *ubi,
goto bad;
}
+ if (unlikely(upd_marker != 0 && upd_marker != 1)) {
+ dbg_err("bad upd_marker");
+ goto bad;
+ }
+
if (unlikely(reserved_pebs > io->good_peb_count)) {
dbg_err("too large reserved_pebs");
goto bad;
@@ -1246,6 +1286,11 @@ static int paranoid_check_vtr(const struct ubi_info *ubi,
goto fail;
}
+ if (unlikely(vtr->upd_marker != 0 && vtr->upd_marker != 1)) {
+ ubi_err("zero upd_marker");
+ goto fail;
+ }
+
if (unlikely(vtr->reserved_pebs > io->good_peb_count)) {
ubi_err("too large reserved_pebs %d", vtr->reserved_pebs);
goto fail;
@@ -1274,7 +1319,7 @@ static int paranoid_check_vtr(const struct ubi_info *ubi,
goto fail;
}
- /* Check data-related fields */
+ /* Check RAM-only fields */
n = vtr->used_ebs * vtr->usable_leb_size;
if (vtr->vol_type == UBI_DYNAMIC_VOLUME) {
if (unlikely(vtr->corrupted != 0)) {
diff --git a/drivers/mtd/ubi/vtbl.h b/drivers/mtd/ubi/vtbl.h
index 331886d..df7480c 100644
--- a/drivers/mtd/ubi/vtbl.h
+++ b/drivers/mtd/ubi/vtbl.h
@@ -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;
}
/**
--git a/include/mtd/ubi-header.h b/include/mtd/ubi-header.h
index 73add4d..88f025e 100644
--- a/include/mtd/ubi-header.h
+++ b/include/mtd/ubi-header.h
@@ -53,7 +53,7 @@ enum {
};
/*
- * Molume type constants used in volume identifier headers.
+ * Volume type constants used in the volume identifier header.
*
* @UBI_VID_DYNAMIC: dynamic volume
* @UBI_VID_STATIC: static volume
@@ -97,8 +97,8 @@ typedef struct {
} __attribute__ ((packed)) ubi64_t;
/*
- * In this implementation UBI uses the big-endian format for on-flash integers.
- * The below are the corresponding endianess conversion macros.
+ * In this implementation of UBI uses the big-endian format for on-flash
+ * integers. The below are the corresponding conversion macros.
*/
#define cpu_to_ubi16(x) ((ubi16_t){__cpu_to_be16(x)})
#define ubi16_to_cpu(x) ((uint16_t)__be16_to_cpu((x).int16))
@@ -117,9 +117,6 @@ typedef struct {
#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(ubi32_t))
#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(ubi32_t))
-/* How much private data may internal volumes store in the VID header */
-#define UBI_VID_HDR_IVOL_DATA_SIZE 12
-
/**
* struct ubi_ec_hdr - UBI erase counter header.
*
@@ -128,8 +125,8 @@ typedef struct {
* UBI image (%UBI_VERSION)
* @padding1: reserved for future, zeroes
* @ec: the erase counter
- * @vid_hdr_offset: where the VID header begins
- * @data_offset: where the user data begins
+ * @vid_hdr_offset: where the VID header starts
+ * @data_offset: where the user data starts
* @padding2: reserved for future, zeroes
* @hdr_crc: the erase counter header CRC checksum
*
@@ -137,7 +134,7 @@ typedef struct {
* future usage. The unused fields are zeroed. The @version field is used to
* indicate the version of UBI implementation which is supposed to be able to
* work with this UBI image. If @version is greater then the current UBI
- * version, the image is rejecter. This may be useful in future if something
+ * version, the image is rejected. This may be useful in future if something
* is changed radically. This field is duplicated in the volume identifier
* header.
*
@@ -167,68 +164,68 @@ struct ubi_ec_hdr {
* means of copying an original physical eraseblock to ensure wear-leveling.
* @compat: compatibility of this volume (%UBI_COMPAT_DELETE,
* %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
- * @vol_id: volume ID
+ * @vol_id: ID of this volume
* @lnum: logical eraseblock number
* @leb_ver: eraseblock copy number
- * @data_size: how many bytes of data this eraseblock contains.
+ * @data_size: how many bytes of data this eraseblock contains
* @used_ebs: total number of used logical eraseblocks in this volume
* @data_pad: how many bytes at the end of this eraseblock are not used
- * @data_crc: CRC checksum of data containing in this eraseblock
+ * @data_crc: CRC checksum of the data stored in this eraseblock
* @padding1: reserved for future, zeroes
- * @ivol_data: private data of internal volumes
* @hdr_crc: volume identifier header CRC checksum
*
* The @leb_ver and the @copy_flag fields are used to distinguish between older
- * and newer copies of logical eraseblocks, as well as to guarantee robustness
- * to unclean reboots. As UBI erases logical eraseblocks asynchronously, it has
- * to distinguish between older and newer copies of eraseblocks. This is done
- * using the @version field. On the other hand, when UBI moves an eraseblock,
- * its version is also increased and the @copy_flag is set to 1. Additionally,
- * when moving eraseblocks, UBI calculates data CRC and stores it in the
- * @data_crc field, even for dynamic volumes.
+ * and newer copies of the logical eraseblock, as well as to guarantee
+ * robustness against unclean reboots. As UBI erases logical eraseblocks
+ * asynchronously, in background, it has to distinguish between older and newer
+ * copies of logical eraseblocks. This is done using the @version field. On the
+ * other hand, when UBI moves data of an eraseblock, its version is also
+ * increased and the @copy_flag is set to 1. Additionally, when moving data of
+ * eraseblocks, UBI calculates data CRC and stores it in the @data_crc field,
+ * even for dynamic volumes.
*
- * Thus, if there are 2 eraseblocks of the same volume and logical number, UBI
- * uses the following algorithm to pick one of them. It first picks the one
- * with larger version (say, A). If @copy_flag is not set, then A is picked. If
- * @copy_flag is set, UBI checks the CRC of the eraseblock (@data_crc). This is
- * needed to ensure that copying was finished. If the CRC is all right, A is
- * picked. If not, the older eraseblock is picked.
+ * Thus, if there are 2 physical eraseblocks belonging to the logical
+ * eraseblock (same volume ID and logical eraseblock number), UBI uses the
+ * following algorithm to pick one of them. It first picks the one with larger
+ * version (say, A). If @copy_flag is not set, then A is picked. If @copy_flag
+ * is set, UBI checks the CRC of data of this physical eraseblock (@data_crc).
+ * This is needed to ensure that the copying was finished. If the CRC is all
+ * right, A is picked. If not, the older physical eraseblock is picked.
*
- * Note, the @leb_ver field may overflow. Thus, if you have 2 versions A and B,
- * then A > B if abs(A-B) < 0x7FFFFFFF, and A < B otherwise.
+ * Note, the @leb_ver field may overflow. Thus, if you have 2 versions X and Y,
+ * then X > Y if abs(X-Y) < 0x7FFFFFFF, otherwise X < Y.
*
* There are 2 sorts of volumes in UBI: user volumes and internal volumes.
- * Internal volumes are not seen from outside and are used for different
- * internal UBI purposes. In this implementation there are only two internal
- * volumes: the layout volume and the update volume. Internal volumes are the
- * main mechanism of UBI extensions. For example, in future one may introduce a
- * journal internal volume.
+ * Internal volumes are not seen from outside and are used for various internal
+ * UBI purposes. In this implementation there is only one internal volume - the
+ * layout volume. Internal volumes are the main mechanism of UBI extensions.
+ * For example, in future one may introduce a journal internal volume. Internal
+ * volumes have their own reserved range of IDs.
*
- * The @compat field is only used for internal volumes and contains the degree
- * of their compatibility. This field is always zero for user volumes. This
- * field provides a mechanism to introduce UBI extensions and to be still
- * compatible with older UBI binaries. For example, if someone introduced an
- * journal internal volume in future, he would probably use %UBI_COMPAT_DELETE
- * compatibility. And in this case, older UBI binaries, which know nothing
- * about the journal volume, would just delete this and work perfectly fine.
- * This is somewhat similar to what Ext2fs does when it is fed by an Ext3fs
- * image - it just ignores the Ext3fs journal.
+ * The @compat field is only used for internal volumes and contains the "degree
+ * of their compatibility". It is always zero for user volumes. This field
+ * provides a mechanism to introduce UBI extensions and to be still compatible
+ * with older UBI binaries. For example, if someone introduced a journal in
+ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
+ * journal volume. And in this case, older UBI binaries, which know nothing
+ * about the journal volume, would just delete this volume and work perfectly
+ * fine. This is somewhat similar to what Ext2fs does when it is fed by an
+ * Ext3fs image - it just ignores the Ext3fs journal.
*
* The @data_crc field contains the CRC checksum of the contents of the logical
- * eraseblock if this is a static volume. In case of dynamic volumes, it does
+ * eraseblock if this is a static volume. In case of dynamic volumes, it does
* not contain the CRC checksum as a rule. The only exception is when the
- * logical eraseblock was moved by the wear-leveling unit, then the
- * wear-leveling unit calculates the eraseblocks' CRC and stores it at
- * @data_crc.
+ * data of the physical eraseblock was moved by the wear-leveling unit, then
+ * the wear-leveling unit calculates the data CRC and stores it in the
+ * @data_crc field. And of course, the @copy_flag is %in this case.
*
- * The @data_size field is always used for static volumes because we want to
- * know about how many bytes of data are stored in this eraseblock. For
- * dynamic eraseblocks, this field usually contains zero. The only exception is
- * when the logical eraseblock is moved to another physical eraseblock due to
+ * The @data_size field is used only for static volumes because UBI has to know
+ * how many bytes of data are stored in this eraseblock. For dynamic volumes,
+ * this field usually contains zero. The only exception is when the data of the
+ * physical eraseblock was moved to another physical eraseblock for
* wear-leveling reasons. In this case, UBI calculates CRC checksum of the
* contents and uses both @data_crc and @data_size fields. In this case, the
- * @data_size field contains the size of logical eraseblock of this volume
- * (which may vary owing to @alignment).
+ * @data_size field contains data size.
*
* The @used_ebs field is used only for static volumes and indicates how many
* eraseblocks the data of the volume takes. For dynamic volumes this field is
@@ -238,11 +235,6 @@ struct ubi_ec_hdr {
* parameter. So, effectively, the @data_pad field reduces the size of logical
* eraseblocks of this volume. This is very handy when one uses block-oriented
* software (say, cramfs) on top of the UBI volume.
- *
- * The @ivol_data contains private data of internal volumes. This might be very
- * handy to store data in the VID header, not in the eraseblock's contents. For
- * example it may make life of simple boot-loaders easier. The @ivol_data field
- * contains zeroes for user volumes.
*/
struct ubi_vid_hdr {
ubi32_t magic;
@@ -257,54 +249,31 @@ struct ubi_vid_hdr {
ubi32_t used_ebs;
ubi32_t data_pad;
ubi32_t data_crc;
- uint8_t padding1[12];
- uint8_t ivol_data[UBI_VID_HDR_IVOL_DATA_SIZE];
+ uint8_t padding1[24];
ubi32_t hdr_crc;
} __attribute__ ((packed));
-/**
- * struct ubi_vid_hdr_upd_vol - private data of the update internal volume
- * stored in volume identifier headers.
- *
- * @vol_id: volume ID of the volume under update
- * @padding: zeroes
- */
-struct ubi_vid_hdr_upd_vol {
- ubi32_t vol_id;
- uint8_t padding[UBI_VID_HDR_IVOL_DATA_SIZE-4];
-} __attribute__ ((packed));
-
/* Count of internal UBI volumes */
-#define UBI_INT_VOL_COUNT 2
+#define UBI_INT_VOL_COUNT 1
/*
- * Internal volume IDs start from this digit. There is a reserved room for 4096
- * internal volumes.
+ * IDs of internal volumes start from this digit. There is a reserved room for
+ * 4096 internal volumes.
*/
#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
/*
- * enum ubi_internal_volume_numbers - volume IDs of internal UBI volumes.
+ * IDs of internal UBI volumes.
*
- * %UBI_LAYOUT_VOL_ID: volume ID of the layout volume
- * %UBI_UPDATE_VOL_ID: volume ID of the update volume
+ * %UBI_LAYOUT_VOL_ID: layout volume ID
*/
enum {
UBI_LAYOUT_VOL_ID = UBI_INTERNAL_VOL_START,
- UBI_UPDATE_VOL_ID = UBI_INTERNAL_VOL_START + 1
};
-/* Number of logical eraseblocks reserved for internal volumes */
-#define UBI_LAYOUT_VOLUME_EBS 2
-#define UBI_UPDATE_VOLUME_EBS 1
-
-/* Names of internal volumes */
-#define UBI_LAYOUT_VOLUME_NAME "The layout volume"
-#define UBI_UPDATE_VOLUME_NAME "The update volume"
-
-/* Compatibility flags of internal volumes */
+#define UBI_LAYOUT_VOLUME_EBS 2
+#define UBI_LAYOUT_VOLUME_NAME "The layout volume"
#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
-#define UBI_UPDATE_VOLUME_COMPAT UBI_COMPAT_REJECT
/* The maximum number of volumes per one UBI device */
#define UBI_MAX_VOLUMES 128
@@ -312,10 +281,10 @@ enum {
/* The maximum volume name length */
#define UBI_VOL_NAME_MAX 127
-/* Size of volume table records */
+/* Size of the volume table record */
#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vol_tbl_record)
-/* Size of volume table records without the ending CRC */
+/* Size of the volume table record without the ending CRC */
#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(ubi32_t))
/**
@@ -323,10 +292,10 @@ enum {
*
* @reserved_pebs: how many physical eraseblocks are reserved for this volume
* @alignment: volume alignment
- * @data_pad: how many bytes are not used at the end of the eraseblocks to
+ * @data_pad: how many bytes are unused at the end of the each eraseblock to
* satisfy the requested alignment
* @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @padding1: reserved, zeroes
+ * @upd_marker: the update marker flag
* @name_len: the volume name length
* @name: the volume name
* @padding2: reserved, zeroes
@@ -338,9 +307,12 @@ enum {
*
* If the size of the logical eraseblock is large enough to fit
* %UBI_MAX_VOLUMES, the volume table contains %UBI_MAX_VOLUMES records.
- * Otherwise, it contains as much records as can be fit (i.e., size of logical
+ * Otherwise, it contains as many records as it can fit (i.e., size of logical
* eraseblock divided by sizeof(struct ubi_vol_tbl_record)).
*
+ * The @upd_marker flag is used to implement volume update. It is set to %1
+ * before update and set to %0 after the update.
+ *
* The @alignment field is specified when the volume is created and cannot be
* later changed. It may be useful, for example, when a block-oriented file
* system works on top of UBI. The @data_pad field is calculated using the
@@ -355,7 +327,7 @@ struct ubi_vol_tbl_record {
ubi32_t alignment;
ubi32_t data_pad;
uint8_t vol_type;
- uint8_t padding1;
+ uint8_t upd_marker;
ubi16_t name_len;
uint8_t name[UBI_VOL_NAME_MAX+1];
uint8_t padding2[24];
--
1.4.4.2
next prev parent reply other threads:[~2007-02-01 10:27 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-01 10:21 [RFC] [PATCH 0/1] [MTD] UBI: implement per-volume update Artem Bityutskiy
2007-02-01 10:21 ` Artem Bityutskiy [this message]
2007-02-01 13:10 ` [RFC] [PATCH 1/1] " Thomas Gleixner
2007-02-01 13:22 ` Artem Bityutskiy
2007-02-01 13:26 ` Artem Bityutskiy
2007-02-01 13:35 ` Frank Haverkamp
2007-02-01 13:32 ` [RFC] [PATCH 0/1] " Alexander Schmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070201102111.15629.24289.sendpatchset@localhost.localdomain \
--to=dedekind@infradead.org \
--cc=alexs@linux.vnet.ibm.com \
--cc=linux-mtd@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.