Re: [PATCH] UBI: allow atomic updates to sychronously erase old PEB

From: Matthieu CASTET
Date: Thu Mar 29 2012 - 12:25:02 EST


Hi,

what happen if there is a power cut between the atomic update and the erase ?
Is the leb is deleted during the recovery ?

Matthieu

Joel Reardon a écrit :
> This is a proposal for adding an immediate mode for atomic updates of LEBs in
> UBI. The idea is that, if the erase parameter is non-zero, then the old PEB will
> be erase after the new PEB is written, but before the function returns. It
> will not go into a work queue. This is for security-relevant situations where,
> for instance, the user needs assurance that sensitive information on an
> eraseblock is actually gone after the update.
>
> The function schedule_erase always returns zero, because the actual error
> during erasure is not known at the time. Now, if it is immediate, then it has
> the ability to return an error if that fails. This would mean some functions
> higher up (i.e., change_leb), will be able to return "old PEB is now bad"
> messages, indicating that the secure erasure has failed. I want to check now
> that this would be okay, or should the old PEB fail be ignored, or handled in
> some other way.
>
> Signed-off-by: Joel Reardon <reardonj@xxxxxxxxxxx>
> ---
> drivers/mtd/ubi/eba.c | 20 +++++++++++---------
> drivers/mtd/ubi/kapi.c | 7 ++++---
> drivers/mtd/ubi/ubi.h | 5 +++--
> drivers/mtd/ubi/upd.c | 5 +++--
> drivers/mtd/ubi/wl.c | 25 +++++++++++++++----------
> fs/ubifs/debug.c | 4 ++--
> fs/ubifs/debug.h | 2 +-
> fs/ubifs/io.c | 6 +++---
> fs/ubifs/log.c | 5 +++--
> fs/ubifs/lpt.c | 10 +++++-----
> fs/ubifs/orphan.c | 2 +-
> fs/ubifs/recovery.c | 12 ++++++------
> fs/ubifs/sb.c | 4 ++--
> fs/ubifs/tnc_commit.c | 2 +-
> fs/ubifs/ubifs.h | 2 +-
> include/linux/mtd/ubi.h | 6 +++---
> 16 files changed, 64 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
> index cd26da8..6e44cfe 100644
> --- a/drivers/mtd/ubi/eba.c
> +++ b/drivers/mtd/ubi/eba.c
> @@ -341,7 +341,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
> dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
>
> vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
> - err = ubi_wl_put_peb(ubi, pnum, 0);
> + err = ubi_wl_put_peb(ubi, pnum, 0, 0);
>
> out_unlock:
> leb_write_unlock(ubi, vol_id, lnum);
> @@ -550,7 +550,7 @@ retry:
> ubi_free_vid_hdr(ubi, vid_hdr);
>
> vol->eba_tbl[lnum] = new_pnum;
> - ubi_wl_put_peb(ubi, pnum, 1);
> + ubi_wl_put_peb(ubi, pnum, 1, 0);
>
> ubi_msg("data was successfully recovered");
> return 0;
> @@ -558,7 +558,7 @@ retry:
> out_unlock:
> mutex_unlock(&ubi->buf_mutex);
> out_put:
> - ubi_wl_put_peb(ubi, new_pnum, 1);
> + ubi_wl_put_peb(ubi, new_pnum, 1, 0);
> ubi_free_vid_hdr(ubi, vid_hdr);
> return err;
>
> @@ -568,7 +568,7 @@ write_error:
> * get another one.
> */
> ubi_warn("failed to write to PEB %d", new_pnum);
> - ubi_wl_put_peb(ubi, new_pnum, 1);
> + ubi_wl_put_peb(ubi, new_pnum, 1, 0);
> if (++tries > UBI_IO_RETRIES) {
> ubi_free_vid_hdr(ubi, vid_hdr);
> return err;
> @@ -687,7 +687,7 @@ write_error:
> * eraseblock, so just put it and request a new one. We assume that if
> * this physical eraseblock went bad, the erase code will handle that.
> */
> - err = ubi_wl_put_peb(ubi, pnum, 1);
> + err = ubi_wl_put_peb(ubi, pnum, 1, 0);
> if (err || ++tries > UBI_IO_RETRIES) {
> ubi_ro_mode(ubi);
> leb_write_unlock(ubi, vol_id, lnum);
> @@ -807,7 +807,7 @@ write_error:
> return err;
> }
>
> - err = ubi_wl_put_peb(ubi, pnum, 1);
> + err = ubi_wl_put_peb(ubi, pnum, 1, 0);
> if (err || ++tries > UBI_IO_RETRIES) {
> ubi_ro_mode(ubi);
> leb_write_unlock(ubi, vol_id, lnum);
> @@ -828,6 +828,7 @@ write_error:
> * @buf: data to write
> * @len: how many bytes to write
> * @dtype: data type
> + * @erase: if this physical eraseblock should be syncronously erased
> *
> * This function changes the contents of a logical eraseblock atomically. @buf
> * has to contain new logical eraseblock data, and @len - the length of the
> @@ -839,7 +840,8 @@ write_error:
> * LEB change may be done at a time. This is ensured by @ubi->alc_mutex.
> */
> int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
> - int lnum, const void *buf, int len, int dtype)
> + int lnum, const void *buf, int len, int dtype,
> + int erase)
> {
> int err, pnum, tries = 0, vol_id = vol->vol_id;
> struct ubi_vid_hdr *vid_hdr;
> @@ -905,7 +907,7 @@ retry:
> }
>
> if (vol->eba_tbl[lnum] >= 0) {
> - err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0);
> + err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0, erase);
> if (err)
> goto out_leb_unlock;
> }
> @@ -930,7 +932,7 @@ write_error:
> goto out_leb_unlock;
> }
>
> - err = ubi_wl_put_peb(ubi, pnum, 1);
> + err = ubi_wl_put_peb(ubi, pnum, 1, erase);
> if (err || ++tries > UBI_IO_RETRIES) {
> ubi_ro_mode(ubi);
> goto out_leb_unlock;
> diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
> index 9fdb353..7be2044 100644
> --- a/drivers/mtd/ubi/kapi.c
> +++ b/drivers/mtd/ubi/kapi.c
> @@ -487,6 +487,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
> * @buf: data to write
> * @len: how many bytes to write
> * @dtype: expected data type
> + * @erase: if non-zero then blocks until old block is erased
> *
> * This function changes the contents of a logical eraseblock atomically. @buf
> * has to contain new logical eraseblock data, and @len - the length of the
> @@ -497,7 +498,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
> * code in case of failure.
> */
> int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
> - int len, int dtype)
> + int len, int dtype, int erase)
> {
> struct ubi_volume *vol = desc->vol;
> struct ubi_device *ubi = vol->ubi;
> @@ -524,8 +525,8 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
>
> if (len == 0)
> return 0;
> -
> - return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype);
> + return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf,
> + len, dtype, erase);
> }
> EXPORT_SYMBOL_GPL(ubi_leb_change);
>
> diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
> index d51d75d..cbe9082 100644
> --- a/drivers/mtd/ubi/ubi.h
> +++ b/drivers/mtd/ubi/ubi.h
> @@ -532,14 +532,15 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
> int lnum, const void *buf, int len, int dtype,
> int used_ebs);
> int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
> - int lnum, const void *buf, int len, int dtype);
> + int lnum, const void *buf, int len, int dtype,
> + int erase);
> int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
> struct ubi_vid_hdr *vid_hdr);
> int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
>
> /* wl.c */
> int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
> -int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture);
> +int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture, int erase);
> int ubi_wl_flush(struct ubi_device *ubi);
> int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
> int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
> diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
> index 425bf5a..7584aed 100644
> --- a/drivers/mtd/ubi/upd.c
> +++ b/drivers/mtd/ubi/upd.c
> @@ -187,7 +187,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
> vol->vol_id, req->lnum, req->bytes);
> if (req->bytes == 0)
> return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0,
> - req->dtype);
> + req->dtype, 0);
>
> vol->upd_bytes = req->bytes;
> vol->upd_received = 0;
> @@ -421,7 +421,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
> len - vol->upd_bytes);
> len = ubi_calc_data_len(ubi, vol->upd_buf, len);
> err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
> - vol->upd_buf, len, UBI_UNKNOWN);
> + vol->upd_buf, len,
> + UBI_UNKNOWN, 0);
> if (err)
> return err;
> }
> diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
> index 0696e36..fa973f6 100644
> --- a/drivers/mtd/ubi/wl.c
> +++ b/drivers/mtd/ubi/wl.c
> @@ -469,7 +469,6 @@ retry:
> ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
> return err;
> }
> -
> return e->pnum;
> }
>
> @@ -629,12 +628,13 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
> * @ubi: UBI device description object
> * @e: the WL entry of the physical eraseblock to erase
> * @torture: if the physical eraseblock has to be tortured
> + * @blocking: schedule the work immediately and return after completion
> *
> * This function returns zero in case of success and a %-ENOMEM in case of
> * failure.
> */
> static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
> - int torture)
> + int torture, int blocking)
> {
> struct ubi_work *wl_wrk;
>
> @@ -649,7 +649,11 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
> wl_wrk->e = e;
> wl_wrk->torture = torture;
>
> - schedule_ubi_work(ubi, wl_wrk);
> + if (blocking)
> + erase_worker(ubi, wl_wrk, 0);
> + else
> + schedule_ubi_work(ubi, wl_wrk);
> +
> return 0;
> }
>
> @@ -847,7 +851,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
> ubi->move_to_put = ubi->wl_scheduled = 0;
> spin_unlock(&ubi->wl_lock);
>
> - err = schedule_erase(ubi, e1, 0);
> + err = schedule_erase(ubi, e1, 0, 0);
> if (err) {
> kmem_cache_free(ubi_wl_entry_slab, e1);
> if (e2)
> @@ -862,7 +866,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
> */
> dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase",
> e2->pnum, vol_id, lnum);
> - err = schedule_erase(ubi, e2, 0);
> + err = schedule_erase(ubi, e2, 0, 0);
> if (err) {
> kmem_cache_free(ubi_wl_entry_slab, e2);
> goto out_ro;
> @@ -901,7 +905,7 @@ out_not_moved:
> spin_unlock(&ubi->wl_lock);
>
> ubi_free_vid_hdr(ubi, vid_hdr);
> - err = schedule_erase(ubi, e2, torture);
> + err = schedule_erase(ubi, e2, torture, 0);
> if (err) {
> kmem_cache_free(ubi_wl_entry_slab, e2);
> goto out_ro;
> @@ -1058,7 +1062,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
> int err1;
>
> /* Re-schedule the LEB for erasure */
> - err1 = schedule_erase(ubi, e, 0);
> + err1 = schedule_erase(ubi, e, 0, 0);
> if (err1) {
> err = err1;
> goto out_ro;
> @@ -1128,13 +1132,14 @@ out_ro:
> * @ubi: UBI device description object
> * @pnum: physical eraseblock to return
> * @torture: if this physical eraseblock has to be tortured
> + * @erase: if this physical eraseblock should be synchronously erased
> *
> * This function is called to return physical eraseblock @pnum to the pool of
> * free physical eraseblocks. The @torture flag has to be set if an I/O error
> * occurred to this @pnum and it has to be tested. This function returns zero
> * in case of success, and a negative error code in case of failure.
> */
> -int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture)
> +int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture, int erase)
> {
> int err;
> struct ubi_wl_entry *e;
> @@ -1199,8 +1204,8 @@ retry:
> }
> }
> spin_unlock(&ubi->wl_lock);
> + err = schedule_erase(ubi, e, torture, erase);
>
> - err = schedule_erase(ubi, e, torture);
> if (err) {
> spin_lock(&ubi->wl_lock);
> wl_tree_add(e, &ubi->used);
> @@ -1465,7 +1470,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
> e->pnum = seb->pnum;
> e->ec = seb->ec;
> ubi->lookuptbl[e->pnum] = e;
> - if (schedule_erase(ubi, e, 0)) {
> + if (schedule_erase(ubi, e, 0, 0)) {
> kmem_cache_free(ubi_wl_entry_slab, e);
> goto out_free;
> }
> diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
> index 1934084..415a04f 100644
> --- a/fs/ubifs/debug.c
> +++ b/fs/ubifs/debug.c
> @@ -2697,7 +2697,7 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
> }
>
> int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
> - int len, int dtype)
> + int len, int dtype, int erase)
> {
> int err;
>
> @@ -2705,7 +2705,7 @@ int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
> return -EROFS;
> if (power_cut_emulated(c, lnum, 1))
> return -EROFS;
> - err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
> + err = ubi_leb_change(c->ubi, lnum, buf, len, dtype, erase);
> if (err)
> return err;
> if (power_cut_emulated(c, lnum, 1))
> diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
> index 9f71765..64950a7 100644
> --- a/fs/ubifs/debug.h
> +++ b/fs/ubifs/debug.h
> @@ -309,7 +309,7 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
> int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
> int len, int dtype);
> int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
> - int dtype);
> + int dtype, int erase);
> int dbg_leb_unmap(struct ubifs_info *c, int lnum);
> int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype);
>
> diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
> index 9228950..9ea6741 100644
> --- a/fs/ubifs/io.c
> +++ b/fs/ubifs/io.c
> @@ -136,7 +136,7 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
> }
>
> int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
> - int dtype)
> + int dtype, int erase)
> {
> int err;
>
> @@ -144,9 +144,9 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
> if (c->ro_error)
> return -EROFS;
> if (!dbg_is_tst_rcvry(c))
> - err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
> + err = ubi_leb_change(c->ubi, lnum, buf, len, dtype, erase);
> else
> - err = dbg_leb_change(c, lnum, buf, len, dtype);
> + err = dbg_leb_change(c, lnum, buf, len, dtype, erase);
> if (err) {
> ubifs_err("changing %d bytes in LEB %d failed, error %d",
> len, lnum, err);
> diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
> index f9fd068..a3d4660 100644
> --- a/fs/ubifs/log.c
> +++ b/fs/ubifs/log.c
> @@ -623,7 +623,7 @@ static int add_node(struct ubifs_info *c, void *buf, int *lnum, int *offs,
> int sz = ALIGN(*offs, c->min_io_size), err;
>
> ubifs_pad(c, buf + *offs, sz - *offs);
> - err = ubifs_leb_change(c, *lnum, buf, sz, UBI_SHORTTERM);
> + err = ubifs_leb_change(c, *lnum, buf, sz, UBI_SHORTTERM, 0);
> if (err)
> return err;
> *lnum = ubifs_next_log_lnum(c, *lnum);
> @@ -702,7 +702,8 @@ int ubifs_consolidate_log(struct ubifs_info *c)
> int sz = ALIGN(offs, c->min_io_size);
>
> ubifs_pad(c, buf + offs, sz - offs);
> - err = ubifs_leb_change(c, write_lnum, buf, sz, UBI_SHORTTERM);
> + err = ubifs_leb_change(c, write_lnum, buf,
> + sz, UBI_SHORTTERM, 0);
> if (err)
> goto out_free;
> offs = ALIGN(offs, c->min_io_size);
> diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
> index 66d59d0..c974211 100644
> --- a/fs/ubifs/lpt.c
> +++ b/fs/ubifs/lpt.c
> @@ -702,7 +702,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
> set_ltab(c, lnum, c->leb_size - alen, alen - len);
> memset(p, 0xff, alen - len);
> err = ubifs_leb_change(c, lnum++, buf, alen,
> - UBI_SHORTTERM);
> + UBI_SHORTTERM, 0);
> if (err)
> goto out;
> p = buf;
> @@ -733,7 +733,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
> alen - len);
> memset(p, 0xff, alen - len);
> err = ubifs_leb_change(c, lnum++, buf, alen,
> - UBI_SHORTTERM);
> + UBI_SHORTTERM, 0);
> if (err)
> goto out;
> p = buf;
> @@ -781,7 +781,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
> set_ltab(c, lnum, c->leb_size - alen, alen - len);
> memset(p, 0xff, alen - len);
> err = ubifs_leb_change(c, lnum++, buf, alen,
> - UBI_SHORTTERM);
> + UBI_SHORTTERM, 0);
> if (err)
> goto out;
> p = buf;
> @@ -806,7 +806,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
> alen = ALIGN(len, c->min_io_size);
> set_ltab(c, lnum, c->leb_size - alen, alen - len);
> memset(p, 0xff, alen - len);
> - err = ubifs_leb_change(c, lnum++, buf, alen, UBI_SHORTTERM);
> + err = ubifs_leb_change(c, lnum++, buf, alen, UBI_SHORTTERM, 0);
> if (err)
> goto out;
> p = buf;
> @@ -826,7 +826,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
>
> /* Write remaining buffer */
> memset(p, 0xff, alen - len);
> - err = ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM);
> + err = ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM, 0);
> if (err)
> goto out;
>
> diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
> index c542c73..a0ec4ed 100644
> --- a/fs/ubifs/orphan.c
> +++ b/fs/ubifs/orphan.c
> @@ -249,7 +249,7 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
> ubifs_prepare_node(c, c->orph_buf, len, 1);
> len = ALIGN(len, c->min_io_size);
> err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len,
> - UBI_SHORTTERM);
> + UBI_SHORTTERM, 0);
> } else {
> if (c->ohead_offs == 0) {
> /* Ensure LEB has been unmapped */
> diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
> index 2a935b3..0531112 100644
> --- a/fs/ubifs/recovery.c
> +++ b/fs/ubifs/recovery.c
> @@ -213,10 +213,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
> mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
>
> ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
> - err = ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM);
> + err = ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM, 0);
> if (err)
> goto out;
> - err = ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM);
> + err = ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM, 0);
> if (err)
> goto out;
> out:
> @@ -556,7 +556,7 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
> }
> }
> err = ubifs_leb_change(c, lnum, sleb->buf, len,
> - UBI_UNKNOWN);
> + UBI_UNKNOWN, 0);
> if (err)
> return err;
> }
> @@ -941,7 +941,7 @@ static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
> err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
> if (err)
> return err;
> - return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKNOWN);
> + return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKNOWN, 0);
> }
>
> return 0;
> @@ -1071,7 +1071,7 @@ static int clean_an_unclean_leb(struct ubifs_info *c,
> }
>
> /* Write back the LEB atomically */
> - err = ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN);
> + err = ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN, 0);
> if (err)
> return err;
>
> @@ -1472,7 +1472,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
> len -= 1;
> len = ALIGN(len + 1, c->min_io_size);
> /* Atomically write the fixed LEB back again */
> - err = ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
> + err = ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN, 0);
> if (err)
> goto out;
> dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
> diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
> index 771f7fb..e38d72e 100644
> --- a/fs/ubifs/sb.c
> +++ b/fs/ubifs/sb.c
> @@ -518,7 +518,7 @@ int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
> int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
>
> ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);
> - return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len, UBI_LONGTERM);
> + return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len, UBI_LONGTERM, 0);
> }
>
> /**
> @@ -691,7 +691,7 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
> if (err)
> return err;
>
> - return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
> + return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN, 0);
> }
>
> /**
> diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
> index 4c15f07..485a283 100644
> --- a/fs/ubifs/tnc_commit.c
> +++ b/fs/ubifs/tnc_commit.c
> @@ -323,7 +323,7 @@ static int layout_leb_in_gaps(struct ubifs_info *c, int *p)
> if (err)
> return err;
> err = ubifs_leb_change(c, lnum, c->ileb_buf, c->ileb_len,
> - UBI_SHORTTERM);
> + UBI_SHORTTERM, 1);
> if (err)
> return err;
> dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written);
> diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
> index 0cc1180..d7a2827 100644
> --- a/fs/ubifs/ubifs.h
> +++ b/fs/ubifs/ubifs.h
> @@ -1470,7 +1470,7 @@ int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
> int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
> int len, int dtype);
> int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
> - int dtype);
> + int dtype, int erase);
> int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
> int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype);
> int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
> diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
> index db4836b..2387c8a 100644
> --- a/include/linux/mtd/ubi.h
> +++ b/include/linux/mtd/ubi.h
> @@ -210,7 +210,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
> int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
> int offset, int len, int dtype);
> int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
> - int len, int dtype);
> + int len, int dtype, int erase);
> int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum);
> int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
> int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
> @@ -239,12 +239,12 @@ static inline int ubi_write(struct ubi_volume_desc *desc, int lnum,
>
> /*
> * This function is the same as the 'ubi_leb_change()' functions, but it does
> - * not have the data type argument.
> + * not have the data type argument or the immediate erase argument.
> */
> static inline int ubi_change(struct ubi_volume_desc *desc, int lnum,
> const void *buf, int len)
> {
> - return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
> + return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN, 0);
> }
>
> #endif /* !__LINUX_UBI_H__ */
> --
> 1.7.5.4
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/