[lkml]   [2011]   [May]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    Subject[patch 13/38] UBIFS: do not free write-buffers when in R/O mode
    2.6.38-stable review patch.  If anyone has any objections, please let us know.


    From: Artem Bityutskiy <>

    commit b50b9f408502a2ea90459ae36ba8cdc9cc005cfe upstream.

    Currently UBIFS has a small optimization - it frees write-buffers when it is
    re-mounted from R/W mode to R/O mode. Of course, when it is mounted R/O, it
    does not allocate write-buffers as well.

    This optimization is nice but it leads to subtle problems and complications
    in recovery, which I can reproduce using the integck test. The symptoms are
    that after a power cut the file-system cannot be mounted if we first mount
    it R/O, and then re-mount R/W - 'ubifs_rcvry_gc_commit()' prints:

    UBIFS error (pid 34456): could not find an empty LEB

    Analysis of the problem.

    When mounting R/W, the reply process sets journal heads to buds [1], but
    when mounting R/O - it does not do this, because the write-buffers are not
    allocated. So 'ubifs_rcvry_gc_commit()' works completely differently for the
    same file-system but for the following 2 cases:

    1. mounting R/W after a power cut and recover
    2. mounting R/O after a power cut, re-mounting R/W and run deferred recovery

    In the former case, we have journal heads seeked to the a bud, in the latter
    case, they are non-seeked (wbuf->lnum == -1). So in the latter case we do not
    try to recover the GC LEB by garbage-collecting to the GC head, but we just
    try to find an empty LEB, and there may be no empty LEBs, so we just fail.
    On the other hand, in the former case (mount R/W), we are able to make a GC LEB
    (@c->gc_lnum) by garbage-collecting.

    Thus, let's remove this small nice optimization and always allocate
    write-buffers. This should not make too big difference - we have only 3
    of them, each of max. write unit size, which is usually 2KiB. So this is
    about 6KiB of RAM for the typical case, and only when mounted R/O.

    [1]: Note, currently the replay process is setting (seeking) the journal heads
    to _some_ buds, not necessarily to the buds which had been the journal heads
    before the power cut happened. This will be fixed separately.

    Signed-off-by: Artem Bityutskiy <>
    Signed-off-by: Greg Kroah-Hartman <>

    fs/ubifs/log.c | 20 --------------------
    fs/ubifs/super.c | 15 ++++-----------
    2 files changed, 4 insertions(+), 31 deletions(-)

    --- a/fs/ubifs/log.c
    +++ b/fs/ubifs/log.c
    @@ -175,26 +175,6 @@ void ubifs_add_bud(struct ubifs_info *c,

    - * ubifs_create_buds_lists - create journal head buds lists for remount rw.
    - * @c: UBIFS file-system description object
    - */
    -void ubifs_create_buds_lists(struct ubifs_info *c)
    - struct rb_node *p;
    - spin_lock(&c->buds_lock);
    - p = rb_first(&c->buds);
    - while (p) {
    - struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb);
    - struct ubifs_jhead *jhead = &c->jheads[bud->jhead];
    - list_add_tail(&bud->list, &jhead->buds_list);
    - p = rb_next(p);
    - }
    - spin_unlock(&c->buds_lock);
    * ubifs_add_bud_to_log - add a new bud to the log.
    * @c: UBIFS file-system description object
    * @jhead: journal head the bud belongs to
    --- a/fs/ubifs/super.c
    +++ b/fs/ubifs/super.c
    @@ -1235,12 +1235,12 @@ static int mount_ubifs(struct ubifs_info
    goto out_free;

    + err = alloc_wbufs(c);
    + if (err)
    + goto out_cbuf;
    sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
    if (!c->ro_mount) {
    - err = alloc_wbufs(c);
    - if (err)
    - goto out_cbuf;
    /* Create background thread */
    c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
    if (IS_ERR(c->bgt)) {
    @@ -1603,12 +1603,6 @@ static int ubifs_remount_rw(struct ubifs
    if (err)
    goto out;

    - err = alloc_wbufs(c);
    - if (err)
    - goto out;
    - ubifs_create_buds_lists(c);
    /* Create background thread */
    c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
    if (IS_ERR(c->bgt)) {
    @@ -1717,7 +1711,6 @@ static void ubifs_remount_ro(struct ubif
    if (err)
    ubifs_ro_mode(c, err);

    - free_wbufs(c);
    c->orph_buf = NULL;

     \ /
      Last update: 2011-05-06 02:21    [W:0.024 / U:0.856 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site