From mboxrd@z Thu Jan 1 00:00:00 1970 From: Matthieu CASTET Subject: Re: [PATCH] UBI: allow atomic updates to sychronously erase old PEB Date: Thu, 29 Mar 2012 18:24:54 +0200 Message-ID: <4F748CD6.4080704@parrot.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: Artem Bityutskiy , "linux-fsdevel@vger.kernel.org" , "linux-mtd@lists.infradead.org" , "linux-kernel@vger.kernel.org" To: Joel Reardon Return-path: In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org Hi, what happen if there is a power cut between the atomic update and the e= rase ? Is the leb is deleted during the recovery ? Matthieu Joel Reardon a =E9crit : > 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 o= ld PEB will > be erase after the new PEB is written, but before the function return= s. It > will not go into a work queue. This is for security-relevant situatio= ns where, > for instance, the user needs assurance that sensitive information on = an > eraseblock is actually gone after the update. >=20 > The function schedule_erase always returns zero, because the actual e= rror > during erasure is not known at the time. Now, if it is immediate, the= n it has > the ability to return an error if that fails. This would mean some fu= nctions > 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 c= heck now > that this would be okay, or should the old PEB fail be ignored, or ha= ndled in > some other way. >=20 > Signed-off-by: Joel Reardon > --- > 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(-) >=20 > 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, str= uct ubi_volume *vol, > dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum); >=20 > vol->eba_tbl[lnum] =3D UBI_LEB_UNMAPPED; > - err =3D ubi_wl_put_peb(ubi, pnum, 0); > + err =3D ubi_wl_put_peb(ubi, pnum, 0, 0); >=20 > out_unlock: > leb_write_unlock(ubi, vol_id, lnum); > @@ -550,7 +550,7 @@ retry: > ubi_free_vid_hdr(ubi, vid_hdr); >=20 > vol->eba_tbl[lnum] =3D new_pnum; > - ubi_wl_put_peb(ubi, pnum, 1); > + ubi_wl_put_peb(ubi, pnum, 1, 0); >=20 > 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; >=20 > @@ -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 assum= e that if > * this physical eraseblock went bad, the erase code will han= dle that. > */ > - err =3D ubi_wl_put_peb(ubi, pnum, 1); > + err =3D 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; > } >=20 > - err =3D ubi_wl_put_peb(ubi, pnum, 1); > + err =3D 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 atomic= ally. @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_mu= tex. > */ > int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_vol= ume *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 =3D 0, vol_id =3D vol->vol_id; > struct ubi_vid_hdr *vid_hdr; > @@ -905,7 +907,7 @@ retry: > } >=20 > if (vol->eba_tbl[lnum] >=3D 0) { > - err =3D ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0); > + err =3D ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0, er= ase); > if (err) > goto out_leb_unlock; > } > @@ -930,7 +932,7 @@ write_error: > goto out_leb_unlock; > } >=20 > - err =3D ubi_wl_put_peb(ubi, pnum, 1); > + err =3D 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 atomic= ally. @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 voi= d *buf, > - int len, int dtype) > + int len, int dtype, int erase) > { > struct ubi_volume *vol =3D desc->vol; > struct ubi_device *ubi =3D vol->ubi; > @@ -524,8 +525,8 @@ int ubi_leb_change(struct ubi_volume_desc *desc, = int lnum, const void *buf, >=20 > if (len =3D=3D 0) > return 0; > - > - return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dt= ype); > + return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, > + len, dtype, erase); > } > EXPORT_SYMBOL_GPL(ubi_leb_change); >=20 > 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 dtyp= e, > int used_ebs); > int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_vol= ume *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); >=20 > /* 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, in= t 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 *s= i); > 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 =3D=3D 0) > return ubi_eba_atomic_leb_change(ubi, vol, req->lnum,= NULL, 0, > - req->dtype); > + req->dtype, 0); >=20 > vol->upd_bytes =3D req->bytes; > vol->upd_received =3D 0; > @@ -421,7 +421,8 @@ int ubi_more_leb_change_data(struct ubi_device *u= bi, struct ubi_volume *vol, > len - vol->upd_bytes); > len =3D ubi_calc_data_len(ubi, vol->upd_buf, len); > err =3D ubi_eba_atomic_leb_change(ubi, vol, vol->ch_l= num, > - vol->upd_buf, len, UB= I_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; > } >=20 > @@ -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 complet= ion > * > * This function returns zero in case of success and a %-ENOMEM in c= ase of > * failure. > */ > static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entr= y *e, > - int torture) > + int torture, int blocking) > { > struct ubi_work *wl_wrk; >=20 > @@ -649,7 +649,11 @@ static int schedule_erase(struct ubi_device *ubi= , struct ubi_wl_entry *e, > wl_wrk->e =3D e; > wl_wrk->torture =3D torture; >=20 > - schedule_ubi_work(ubi, wl_wrk); > + if (blocking) > + erase_worker(ubi, wl_wrk, 0); > + else > + schedule_ubi_work(ubi, wl_wrk); > + > return 0; > } >=20 > @@ -847,7 +851,7 @@ static int wear_leveling_worker(struct ubi_device= *ubi, struct ubi_work *wrk, > ubi->move_to_put =3D ubi->wl_scheduled =3D 0; > spin_unlock(&ubi->wl_lock); >=20 > - err =3D schedule_erase(ubi, e1, 0); > + err =3D 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 =3D schedule_erase(ubi, e2, 0); > + err =3D 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); >=20 > ubi_free_vid_hdr(ubi, vid_hdr); > - err =3D schedule_erase(ubi, e2, torture); > + err =3D 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; >=20 > /* Re-schedule the LEB for erasure */ > - err1 =3D schedule_erase(ubi, e, 0); > + err1 =3D schedule_erase(ubi, e, 0, 0); > if (err1) { > err =3D 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 erase= d > * > * This function is called to return physical eraseblock @pnum to th= e 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 ret= urns 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, in= t erase) > { > int err; > struct ubi_wl_entry *e; > @@ -1199,8 +1204,8 @@ retry: > } > } > spin_unlock(&ubi->wl_lock); > + err =3D schedule_erase(ubi, e, torture, erase); >=20 > - err =3D 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, st= ruct ubi_scan_info *si) > e->pnum =3D seb->pnum; > e->ec =3D seb->ec; > ubi->lookuptbl[e->pnum] =3D 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 lnu= m, const void *buf, > } >=20 > 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; >=20 > @@ -2705,7 +2705,7 @@ int dbg_leb_change(struct ubifs_info *c, int ln= um, const void *buf, > return -EROFS; > if (power_cut_emulated(c, lnum, 1)) > return -EROFS; > - err =3D ubi_leb_change(c->ubi, lnum, buf, len, dtype); > + err =3D 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_in= fo *c, struct list_head *head); > int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, i= nt 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); >=20 > 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 lnu= m, const void *buf, int offs, > } >=20 > int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf= , int len, > - int dtype) > + int dtype, int erase) > { > int err; >=20 > @@ -144,9 +144,9 @@ int ubifs_leb_change(struct ubifs_info *c, int ln= um, const void *buf, int len, > if (c->ro_error) > return -EROFS; > if (!dbg_is_tst_rcvry(c)) > - err =3D ubi_leb_change(c->ubi, lnum, buf, len, dtype)= ; > + err =3D ubi_leb_change(c->ubi, lnum, buf, len, dtype,= erase); > else > - err =3D dbg_leb_change(c, lnum, buf, len, dtype); > + err =3D dbg_leb_change(c, lnum, buf, len, dtype, eras= e); > 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 *b= uf, int *lnum, int *offs, > int sz =3D ALIGN(*offs, c->min_io_size), err; >=20 > ubifs_pad(c, buf + *offs, sz - *offs); > - err =3D ubifs_leb_change(c, *lnum, buf, sz, UBI_SHORT= TERM); > + err =3D ubifs_leb_change(c, *lnum, buf, sz, UBI_SHORT= TERM, 0); > if (err) > return err; > *lnum =3D ubifs_next_log_lnum(c, *lnum); > @@ -702,7 +702,8 @@ int ubifs_consolidate_log(struct ubifs_info *c) > int sz =3D ALIGN(offs, c->min_io_size); >=20 > ubifs_pad(c, buf + offs, sz - offs); > - err =3D ubifs_leb_change(c, write_lnum, buf, sz, UBI_= SHORTTERM); > + err =3D ubifs_leb_change(c, write_lnum, buf, > + sz, UBI_SHORTTERM, 0); > if (err) > goto out_free; > offs =3D 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, i= nt *main_lebs, int lpt_first, > set_ltab(c, lnum, c->leb_size - alen, alen - = len); > memset(p, 0xff, alen - len); > err =3D ubifs_leb_change(c, lnum++, buf, alen= , > - UBI_SHORTTERM); > + UBI_SHORTTERM, 0); > if (err) > goto out; > p =3D buf; > @@ -733,7 +733,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, i= nt *main_lebs, int lpt_first, > alen - len); > memset(p, 0xff, alen - len); > err =3D ubifs_leb_change(c, lnum++, b= uf, alen, > - UBI_SHORTTERM)= ; > + UBI_SHORTTERM,= 0); > if (err) > goto out; > p =3D buf; > @@ -781,7 +781,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, i= nt *main_lebs, int lpt_first, > set_ltab(c, lnum, c->leb_size - alen, alen - = len); > memset(p, 0xff, alen - len); > err =3D ubifs_leb_change(c, lnum++, buf, alen= , > - UBI_SHORTTERM); > + UBI_SHORTTERM, 0); > if (err) > goto out; > p =3D buf; > @@ -806,7 +806,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, i= nt *main_lebs, int lpt_first, > alen =3D ALIGN(len, c->min_io_size); > set_ltab(c, lnum, c->leb_size - alen, alen - len); > memset(p, 0xff, alen - len); > - err =3D ubifs_leb_change(c, lnum++, buf, alen, UBI_SH= ORTTERM); > + err =3D ubifs_leb_change(c, lnum++, buf, alen, UBI_SH= ORTTERM, 0); > if (err) > goto out; > p =3D buf; > @@ -826,7 +826,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, i= nt *main_lebs, int lpt_first, >=20 > /* Write remaining buffer */ > memset(p, 0xff, alen - len); > - err =3D ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM); > + err =3D ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM, 0= ); > if (err) > goto out; >=20 > 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 =3D ALIGN(len, c->min_io_size); > err =3D ubifs_leb_change(c, c->ohead_lnum, c->orph_bu= f, len, > - UBI_SHORTTERM); > + UBI_SHORTTERM, 0); > } else { > if (c->ohead_offs =3D=3D 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_in= fo *c, > mst->flags |=3D cpu_to_le32(UBIFS_MST_RCVRY); >=20 > ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1); > - err =3D ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM); > + err =3D ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM, 0); > if (err) > goto out; > - err =3D ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM)= ; > + err =3D 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 =3D 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 =3D ubifs_leb_read(c, lnum, sbuf, 0, offs, 1); > if (err) > return err; > - return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKN= OWN); > + return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKN= OWN, 0); > } >=20 > return 0; > @@ -1071,7 +1071,7 @@ static int clean_an_unclean_leb(struct ubifs_in= fo *c, > } >=20 > /* Write back the LEB atomically */ > - err =3D ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN); > + err =3D ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN, 0); > if (err) > return err; >=20 > @@ -1472,7 +1472,7 @@ static int fix_size_in_place(struct ubifs_info = *c, struct size_entry *e) > len -=3D 1; > len =3D ALIGN(len + 1, c->min_io_size); > /* Atomically write the fixed LEB back again */ > - err =3D ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN); > + err =3D 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, str= uct ubifs_sb_node *sup) > int len =3D ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); >=20 > ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1); > - return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len, UBI_LONGT= ERM); > + return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len, UBI_LONGT= ERM, 0); > } >=20 > /** > @@ -691,7 +691,7 @@ static int fixup_leb(struct ubifs_info *c, int ln= um, int len) > if (err) > return err; >=20 > - return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN); > + return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN, 0= ); > } >=20 > /** > 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 =3D 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, in= t 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 voi= d *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_d= esc *desc, int lnum, >=20 > /* > * This function is the same as the 'ubi_leb_change()' functions, bu= t 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); > } >=20 > #endif /* !__LINUX_UBI_H__ */ > -- > 1.7.5.4 >=20 >=20 > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ >=20