All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2] Enable journal replay for UBIFS
Date: Tue, 20 Jan 2015 08:41:45 +0100	[thread overview]
Message-ID: <54BE06B9.1020405@denx.de> (raw)
In-Reply-To: <CANCpNEKcECqBGMRKgPOpBDgx2dpWvGnSBcYLL-FFUbNayJoT7A@mail.gmail.com>

Hello Anton,

Am 19.01.2015 14:48, schrieb Anton Habegger:
> During mount_ubifs the ubifs_replay_journal was disabled. This patch
> enables it again and fix some unrecoverable UBIFS volumes.
>
> The following patch enables the error handling for ubifs_replay_journal as well.
> Please see discussion "Unreadable UBIFS partition after power cuts".
>
>
> Signed-off-by: Anton Habegger <anton.habegger@delta-es.com>
> ---
>   fs/ubifs/Makefile |   2 +-
>   fs/ubifs/gc.c     | 987 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   fs/ubifs/replay.c |   8 +-
>   fs/ubifs/super.c  |   8 +-
>   fs/ubifs/tnc.c    |   7 +-
>   5 files changed, 997 insertions(+), 15 deletions(-)
>   create mode 100644 fs/ubifs/gc.c

Thanks!

> diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
> index 8c8c6ac..5efb349 100644
> --- a/fs/ubifs/Makefile
> +++ b/fs/ubifs/Makefile
> @@ -12,4 +12,4 @@
>   obj-y := ubifs.o io.o super.o sb.o master.o lpt.o
>   obj-y += lpt_commit.o scan.o lprops.o
>   obj-y += tnc.o tnc_misc.o debug.o crc16.o budget.o
> -obj-y += log.o orphan.o recovery.o replay.o
> +obj-y += log.o orphan.o recovery.o replay.o gc.o

Hmm.... do we really need this in u-boot? Ah, the most functions
are unneeded ... ok.

> diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
> new file mode 100644
> index 0000000..159ee67
> --- /dev/null
> +++ b/fs/ubifs/gc.c
> @@ -0,0 +1,987 @@
> +/*
> + * This file is part of UBIFS.
> + *
> + * Copyright (C) 2006-2008 Nokia Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 51
> + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + *
> + * Authors: Adrian Hunter
> + *          Artem Bityutskiy (???????? ?????)
> + */
> +
> +/*
> + * This file implements garbage collection. The procedure for garbage
> collection
> + * is different depending on whether a LEB as an index LEB (contains index
> + * nodes) or not. For non-index LEBs, garbage collection finds a LEB which
> + * contains a lot of dirty space (obsolete nodes), and copies the non-obsolete
> + * nodes to the journal, at which point the garbage-collected LEB is free to be
> + * reused. For index LEBs, garbage collection marks the non-obsolete
> index nodes
> + * dirty in the TNC, and after the next commit, the garbage-collected LEB is
> + * to be reused. Garbage collection will cause the number of dirty index nodes
> + * to grow, however sufficient space is reserved for the index to ensure the
> + * commit will never run out of space.
> + *
> + * Notes about dead watermark. At current UBIFS implementation we assume that
> + * LEBs which have less than @c->dead_wm bytes of free + dirty space are full
> + * and not worth garbage-collecting. The dead watermark is one min. I/O unit
> + * size, or min. UBIFS node size, depending on what is greater. Indeed, UBIFS
> + * Garbage Collector has to synchronize the GC head's write buffer before
> + * returning, so this is about wasting one min. I/O unit. However, UBIFS GC can
> + * actually reclaim even very small pieces of dirty space by garbage collecting
> + * enough dirty LEBs, but we do not bother doing this at this implementation.
> + *
> + * Notes about dark watermark. The results of GC work depends on how big are
> + * the UBIFS nodes GC deals with. Large nodes make GC waste more space. Indeed,
> + * if GC move data from LEB A to LEB B and nodes in LEB A are large, GC would
> + * have to waste large pieces of free space at the end of LEB B, because nodes
> + * from LEB A would not fit. And the worst situation is when all nodes are of
> + * maximum size. So dark watermark is the amount of free + dirty space in LEB
> + * which are guaranteed to be reclaimable. If LEB has less space, the GC might
> + * be unable to reclaim it. So, LEBs with free + dirty greater than dark
> + * watermark are "good" LEBs from GC's point of few. The other LEBs are not so
> + * good, and GC takes extra care when moving them.
> + */
> +#ifndef __UBOOT__
> +#include <linux/slab.h>
> +#include <linux/pagemap.h>
> +#include <linux/list_sort.h>
> +#endif
> +#include "ubifs.h"
> +
> +#ifndef __UBOOT__
> +/*
> + * GC may need to move more than one LEB to make progress. The below constants
> + * define "soft" and "hard" limits on the number of LEBs the garbage collector
> + * may move.
> + */
> +#define SOFT_LEBS_LIMIT 4
> +#define HARD_LEBS_LIMIT 32
> +
> +/**
> + * switch_gc_head - switch the garbage collection journal head.
> + * @c: UBIFS file-system description object
> + * @buf: buffer to write
> + * @len: length of the buffer to write
> + * @lnum: LEB number written is returned here
> + * @offs: offset written is returned here
> + *
> + * This function switch the GC head to the next LEB which is reserved in
> + * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required,
> + * and other negative error code in case of failures.
> + */
> +static int switch_gc_head(struct ubifs_info *c)
> +{
> + int err, gc_lnum = c->gc_lnum;
> + struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
> +
> + ubifs_assert(gc_lnum != -1);

Hmm.. something seems wrong with your mailer ... your patch is malformed.
Could you fix this please?

[...]
> diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
> index 7268b37..75b92ac 100644
> --- a/fs/ubifs/replay.c
> +++ b/fs/ubifs/replay.c
[...]
> @@ -1050,7 +1047,11 @@ int ubifs_replay_journal(struct ubifs_info *c)
>    * depend on it. This means we have to initialize it to make sure
>    * budgeting works properly.
>    */
> +#ifndef __UBOOT__
>    c->bi.uncommitted_idx = atomic_long_read(&c->dirty_zn_cnt);
> +#else
> + c->bi.uncommitted_idx = c->dirty_zn_cnt;
> +#endif

please introduce atomic_long_read() as mentioned to your other EMail.

>    c->bi.uncommitted_idx *= c->max_idx_node_sz;
>
>    ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
> @@ -1063,4 +1064,3 @@ out:
>    c->replaying = 0;
>    return err;
>   }
> -#endif
> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
> index 01d449a..10f8fff 100644
> --- a/fs/ubifs/super.c
> +++ b/fs/ubifs/super.c
> @@ -1049,7 +1049,6 @@ static void free_orphans(struct ubifs_info *c)
>    c->orph_buf = NULL;
>   }
>
> -#ifndef __UBOOT__
>   /**
>    * free_buds - free per-bud objects.
>    * @c: UBIFS file-system description object
> @@ -1061,7 +1060,6 @@ static void free_buds(struct ubifs_info *c)
>    rbtree_postorder_for_each_entry_safe(bud, n, &c->buds, rb)
>    kfree(bud);
>   }
> -#endif
>
>   /**
>    * check_volume_empty - check if the UBI volume is empty.
> @@ -1242,6 +1240,7 @@ static int ubifs_parse_options(struct ubifs_info
> *c, char *options,
>
>    return 0;
>   }
> +#endif
>
>   /**
>    * destroy_journal - destroy journal data structures.
> @@ -1272,7 +1271,6 @@ static void destroy_journal(struct ubifs_info *c)
>    ubifs_tnc_close(c);
>    free_buds(c);
>   }
> -#endif
>
>   /**
>    * bu_init - initialize bulk-read information.
> @@ -1502,11 +1500,9 @@ static int mount_ubifs(struct ubifs_info *c)
>    if (err)
>    goto out_lpt;
>
> -#ifndef __UBOOT__
>    err = ubifs_replay_journal(c);
>    if (err)
>    goto out_journal;
> -#endif
>
>    /* Calculate 'min_idx_lebs' after journal replay */
>    c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c);
> @@ -1678,10 +1674,8 @@ out_infos:
>    spin_unlock(&ubifs_infos_lock);
>   out_orphans:
>    free_orphans(c);
> -#ifndef __UBOOT__
>   out_journal:
>    destroy_journal(c);
> -#endif
>   out_lpt:
>    ubifs_lpt_free(c, 0);
>   out_master:
> diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
> index 95cae54..b6737db 100644
> --- a/fs/ubifs/tnc.c
> +++ b/fs/ubifs/tnc.c
> @@ -2827,7 +2827,6 @@ out_unlock:
>    return ERR_PTR(err);
>   }
>
> -#ifndef __UBOOT__
>   /**
>    * tnc_destroy_cnext - destroy left-over obsolete znodes from a failed commit.
>    * @c: UBIFS file-system description object
> @@ -2850,7 +2849,6 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
>    kfree(znode);
>    } while (cnext && cnext != c->cnext);
>   }
> -
>   /**
>    * ubifs_tnc_close - close TNC subsystem and free all related resources.
>    * @c: UBIFS file-system description object
> @@ -2859,17 +2857,20 @@ void ubifs_tnc_close(struct ubifs_info *c)
>   {
>    tnc_destroy_cnext(c);
>    if (c->zroot.znode) {
> +#ifndef __UBOOT__
>    long n;
> +#endif
>
>    ubifs_destroy_tnc_subtree(c->zroot.znode);
> +#ifndef __UBOOT__
>    n = atomic_long_read(&c->clean_zn_cnt);
>    atomic_long_sub(n, &ubifs_clean_zn_cnt);
> +#endif
>    }
>    kfree(c->gap_lebs);
>    kfree(c->ilebs);
>    destroy_old_idx(c);
>   }
> -#endif
>
>   /**
>    * left_znode - get the znode to the left.
>

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

      reply	other threads:[~2015-01-20  7:41 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-19 13:48 [U-Boot] [PATCH v2] Enable journal replay for UBIFS Anton Habegger
2015-01-20  7:41 ` Heiko Schocher [this message]

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=54BE06B9.1020405@denx.de \
    --to=hs@denx.de \
    --cc=u-boot@lists.denx.de \
    /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.