UBI: implement per-volume update
Subsystems (2)
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.
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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
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 (Битюцкий Артём)
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 (Битюцкий Артём)
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
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_datafrom 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/