]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Jul 2009 02:14:48 +0000 (19:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Jul 2009 02:14:48 +0000 (19:14 -0700)
* 'linux-next' of git://git.infradead.org/ubifs-2.6:
  UBIFS: fix corruption dump
  UBIFS: clean up free space checking
  UBIFS: small amendments in the LEB scanning code
  UBIFS: dump a little more in case of corruptions
  MAINTAINERS: update ahunter's e-mail address
  UBIFS: allow more than one volume to be mounted
  UBIFS: fix assertion warning
  UBIFS: minor spelling and grammar fixes
  UBIFS: fix 64-bit divisions in debug print
  UBIFS: few spelling fixes
  UBIFS: set write-buffer timout to 3-5 seconds
  UBIFS: slightly optimize write-buffer timer usage
  UBIFS: improve debugging messaged
  UBIFS: fix integer overflow warning

MAINTAINERS
fs/ubifs/io.c
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/scan.c
fs/ubifs/super.c
fs/ubifs/ubifs.h

index 494059d60134ed3013c8dd70f1fe2b327f185fc6..9d1601ec13113037859a88c5174e5b475fa194fe 100644 (file)
@@ -5854,7 +5854,7 @@ UBI FILE SYSTEM (UBIFS)
 P:     Artem Bityutskiy
 M:     dedekind@infradead.org
 P:     Adrian Hunter
-M:     ext-adrian.hunter@nokia.com
+M:     adrian.hunter@nokia.com
 L:     linux-mtd@lists.infradead.org
 T:     git git://git.infradead.org/ubifs-2.6.git
 W:     http://www.linux-mtd.infradead.org/doc/ubifs.html
index bc5857199ec2a021c1f9f9838b11329461704b4f..762a7d6cec73de8433c58c6a6c691115e3c23e1c 100644 (file)
@@ -297,6 +297,7 @@ static enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer)
 {
        struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer);
 
+       dbg_io("jhead %d", wbuf->jhead);
        wbuf->need_sync = 1;
        wbuf->c->need_wbuf_sync = 1;
        ubifs_wake_up_bgt(wbuf->c);
@@ -311,8 +312,12 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
 {
        ubifs_assert(!hrtimer_active(&wbuf->timer));
 
-       if (!ktime_to_ns(wbuf->softlimit))
+       if (wbuf->no_timer)
                return;
+       dbg_io("set timer for jhead %d, %llu-%llu millisecs", wbuf->jhead,
+              div_u64(ktime_to_ns(wbuf->softlimit), USEC_PER_SEC),
+              div_u64(ktime_to_ns(wbuf->softlimit) + wbuf->delta,
+                      USEC_PER_SEC));
        hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta,
                               HRTIMER_MODE_REL);
 }
@@ -323,11 +328,8 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
  */
 static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
 {
-       /*
-        * If the syncer is waiting for the lock (from the background thread's
-        * context) and another task is changing write-buffer then the syncing
-        * should be canceled.
-        */
+       if (wbuf->no_timer)
+               return;
        wbuf->need_sync = 0;
        hrtimer_cancel(&wbuf->timer);
 }
@@ -349,8 +351,8 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
                /* Write-buffer is empty or not seeked */
                return 0;
 
-       dbg_io("LEB %d:%d, %d bytes",
-              wbuf->lnum, wbuf->offs, wbuf->used);
+       dbg_io("LEB %d:%d, %d bytes, jhead %d",
+              wbuf->lnum, wbuf->offs, wbuf->used, wbuf->jhead);
        ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
        ubifs_assert(!(wbuf->avail & 7));
        ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
@@ -390,7 +392,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
  * @offs: logical eraseblock offset to seek to
  * @dtype: data type
  *
- * This function targets the write buffer to logical eraseblock @lnum:@offs.
+ * This function targets the write-buffer to logical eraseblock @lnum:@offs.
  * The write-buffer is synchronized if it is not empty. Returns zero in case of
  * success and a negative error code in case of failure.
  */
@@ -399,7 +401,7 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
 {
        const struct ubifs_info *c = wbuf->c;
 
-       dbg_io("LEB %d:%d", lnum, offs);
+       dbg_io("LEB %d:%d, jhead %d", lnum, offs, wbuf->jhead);
        ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
        ubifs_assert(offs >= 0 && offs <= c->leb_size);
        ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
@@ -506,9 +508,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
        struct ubifs_info *c = wbuf->c;
        int err, written, n, aligned_len = ALIGN(len, 8), offs;
 
-       dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len,
-              dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum,
-              wbuf->offs + wbuf->used);
+       dbg_io("%d bytes (%s) to jhead %d wbuf at LEB %d:%d", len,
+              dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->jhead,
+              wbuf->lnum, wbuf->offs + wbuf->used);
        ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
        ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
        ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
@@ -533,8 +535,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
                memcpy(wbuf->buf + wbuf->used, buf, len);
 
                if (aligned_len == wbuf->avail) {
-                       dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum,
-                               wbuf->offs);
+                       dbg_io("flush jhead %d wbuf to LEB %d:%d",
+                              wbuf->jhead, wbuf->lnum, wbuf->offs);
                        err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
                                            wbuf->offs, c->min_io_size,
                                            wbuf->dtype);
@@ -562,7 +564,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
         * minimal I/O unit. We have to fill and flush write-buffer and switch
         * to the next min. I/O unit.
         */
-       dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs);
+       dbg_io("flush jhead %d wbuf to LEB %d:%d",
+              wbuf->jhead, wbuf->lnum, wbuf->offs);
        memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
        err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
                            c->min_io_size, wbuf->dtype);
@@ -695,7 +698,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
        int err, rlen, overlap;
        struct ubifs_ch *ch = buf;
 
-       dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
+       dbg_io("LEB %d:%d, %s, length %d, jhead %d", lnum, offs,
+              dbg_ntype(type), len, wbuf->jhead);
        ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
        ubifs_assert(!(offs & 7) && offs < c->leb_size);
        ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
@@ -819,13 +823,12 @@ out:
  * @c: UBIFS file-system description object
  * @wbuf: write-buffer to initialize
  *
- * This function initializes write buffer. Returns zero in case of success
+ * This function initializes write-buffer. Returns zero in case of success
  * %-ENOMEM in case of failure.
  */
 int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
 {
        size_t size;
-       ktime_t hardlimit;
 
        wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL);
        if (!wbuf->buf)
@@ -851,22 +854,16 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
 
        hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        wbuf->timer.function = wbuf_timer_callback_nolock;
-       /*
-        * Make write-buffer soft limit to be 20% of the hard limit. The
-        * write-buffer timer is allowed to expire any time between the soft
-        * and hard limits.
-        */
-       hardlimit = ktime_set(DEFAULT_WBUF_TIMEOUT_SECS, 0);
-       wbuf->delta = (DEFAULT_WBUF_TIMEOUT_SECS * NSEC_PER_SEC) * 2 / 10;
-       wbuf->softlimit = ktime_sub_ns(hardlimit, wbuf->delta);
-       hrtimer_set_expires_range_ns(&wbuf->timer,  wbuf->softlimit,
-                                    wbuf->delta);
+       wbuf->softlimit = ktime_set(WBUF_TIMEOUT_SOFTLIMIT, 0);
+       wbuf->delta = WBUF_TIMEOUT_HARDLIMIT - WBUF_TIMEOUT_SOFTLIMIT;
+       wbuf->delta *= 1000000000ULL;
+       ubifs_assert(wbuf->delta <= ULONG_MAX);
        return 0;
 }
 
 /**
  * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array.
- * @wbuf: the write-buffer whereto add
+ * @wbuf: the write-buffer where to add
  * @inum: the inode number
  *
  * This function adds an inode number to the inode array of the write-buffer.
index 805605250f128af9b6a978fa8c29c5c31660539a..e5f6cf8a115535e469a646e4806d9dcdbf19a490 100644 (file)
@@ -52,6 +52,25 @@ static int is_empty(void *buf, int len)
        return 1;
 }
 
+/**
+ * first_non_ff - find offset of the first non-0xff byte.
+ * @buf: buffer to search in
+ * @len: length of buffer
+ *
+ * This function returns offset of the first non-0xff byte in @buf or %-1 if
+ * the buffer contains only 0xff bytes.
+ */
+static int first_non_ff(void *buf, int len)
+{
+       uint8_t *p = buf;
+       int i;
+
+       for (i = 0; i < len; i++)
+               if (*p++ != 0xff)
+                       return i;
+       return -1;
+}
+
 /**
  * get_master_node - get the last valid master node allowing for corruption.
  * @c: UBIFS file-system description object
@@ -357,11 +376,7 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs)
        empty_offs = ALIGN(offs + 1, c->min_io_size);
        check_len = c->leb_size - empty_offs;
        p = buf + empty_offs - offs;
-
-       for (; check_len > 0; check_len--)
-               if (*p++ != 0xff)
-                       return 0;
-       return 1;
+       return is_empty(p, check_len);
 }
 
 /**
@@ -543,8 +558,8 @@ static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs)
  *
  * This function does a scan of a LEB, but caters for errors that might have
  * been caused by the unclean unmount from which we are attempting to recover.
- *
- * This function returns %0 on success and a negative error code on failure.
+ * Returns %0 in case of success, %-EUCLEAN if an unrecoverable corruption is
+ * found, and a negative error code in case of failure.
  */
 struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
                                         int offs, void *sbuf, int grouped)
@@ -643,7 +658,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
                        goto corrupted;
                default:
                        dbg_err("unknown");
-                       goto corrupted;
+                       err = -EINVAL;
+                       goto error;
                }
        }
 
@@ -652,8 +668,13 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
                        clean_buf(c, &buf, lnum, &offs, &len);
                        need_clean = 1;
                } else {
-                       ubifs_err("corrupt empty space at LEB %d:%d",
-                                 lnum, offs);
+                       int corruption = first_non_ff(buf, len);
+
+                       ubifs_err("corrupt empty space LEB %d:%d, corruption "
+                                 "starts at %d", lnum, offs, corruption);
+                       /* Make sure we dump interesting non-0xFF data */
+                       offs = corruption;
+                       buf += corruption;
                        goto corrupted;
                }
        }
@@ -813,7 +834,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 static int recover_head(const struct ubifs_info *c, int lnum, int offs,
                        void *sbuf)
 {
-       int len, err, need_clean = 0;
+       int len, err;
 
        if (c->min_io_size > 1)
                len = c->min_io_size;
@@ -827,19 +848,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
 
        /* Read at the head location and check it is empty flash */
        err = ubi_read(c->ubi, lnum, sbuf, offs, len);
-       if (err)
-               need_clean = 1;
-       else {
-               uint8_t *p = sbuf;
-
-               while (len--)
-                       if (*p++ != 0xff) {
-                               need_clean = 1;
-                               break;
-                       }
-       }
-
-       if (need_clean) {
+       if (err || !is_empty(sbuf, len)) {
                dbg_rcvry("cleaning head at %d:%d", lnum, offs);
                if (offs == 0)
                        return ubifs_leb_unmap(c, lnum);
index 11cc80125a49524cef118b97173ed7ff5fb94fd9..2970500f32dfbb76ca9b8d6ff39fd8ee08fada4a 100644 (file)
@@ -837,9 +837,10 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
 
        dbg_mnt("replay log LEB %d:%d", lnum, offs);
        sleb = ubifs_scan(c, lnum, offs, sbuf);
-       if (IS_ERR(sleb)) {
-               if (c->need_recovery)
-                       sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
+       if (IS_ERR(sleb) ) {
+               if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
+                       return PTR_ERR(sleb);
+               sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
                if (IS_ERR(sleb))
                        return PTR_ERR(sleb);
        }
@@ -957,7 +958,7 @@ out:
        return err;
 
 out_dump:
-       ubifs_err("log error detected while replying the log at LEB %d:%d",
+       ubifs_err("log error detected while replaying the log at LEB %d:%d",
                  lnum, offs + snod->offs);
        dbg_dump_node(c, snod->node);
        ubifs_scan_destroy(sleb);
index 0ed82479b44b4daca156a80107fee1b040ec10a7..892ebfee4fe538fe033596c5d42d13860d5fe82a 100644 (file)
@@ -238,12 +238,12 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
 {
        int len;
 
-       ubifs_err("corrupted data at LEB %d:%d", lnum, offs);
+       ubifs_err("corruption at LEB %d:%d", lnum, offs);
        if (dbg_failure_mode)
                return;
        len = c->leb_size - offs;
-       if (len > 4096)
-               len = 4096;
+       if (len > 8192)
+               len = 8192;
        dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
        print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
 }
@@ -256,7 +256,9 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
  * @sbuf: scan buffer (must be c->leb_size)
  *
  * This function scans LEB number @lnum and returns complete information about
- * its contents. Returns an error code in case of failure.
+ * its contents. Returns the scaned information in case of success and,
+ * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case
+ * of failure.
  */
 struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                                  int offs, void *sbuf)
@@ -279,7 +281,6 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                cond_resched();
 
                ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
-
                if (ret > 0) {
                        /* Padding bytes or a valid padding node */
                        offs += ret;
@@ -304,7 +305,8 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                        goto corrupted;
                default:
                        dbg_err("unknown");
-                       goto corrupted;
+                       err = -EINVAL;
+                       goto error;
                }
 
                err = ubifs_add_snod(c, sleb, buf, offs);
@@ -317,8 +319,10 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                len -= node_len;
        }
 
-       if (offs % c->min_io_size)
-               goto corrupted;
+       if (offs % c->min_io_size) {
+               ubifs_err("empty space starts at non-aligned offset %d", offs);
+               goto corrupted;;
+       }
 
        ubifs_end_scan(c, sleb, lnum, offs);
 
index 79fad43f3c57ecc71b9d6adaf8dfd5e650e6fa08..26d2e0d8046598ed579a400293dbebd38eefc7e3 100644 (file)
@@ -797,7 +797,7 @@ static int alloc_wbufs(struct ubifs_info *c)
         * does not need to be synchronized by timer.
         */
        c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
-       c->jheads[GCHD].wbuf.softlimit = ktime_set(0, 0);
+       c->jheads[GCHD].wbuf.no_timer = 1;
 
        return 0;
 }
@@ -986,7 +986,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
                switch (token) {
                /*
                 * %Opt_fast_unmount and %Opt_norm_unmount options are ignored.
-                * We accepte them in order to be backware-compatible. But this
+                * We accept them in order to be backward-compatible. But this
                 * should be removed at some point.
                 */
                case Opt_fast_unmount:
@@ -1287,6 +1287,9 @@ static int mount_ubifs(struct ubifs_info *c)
        if (err)
                goto out_journal;
 
+       /* Calculate 'min_idx_lebs' after journal replay */
+       c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
+
        err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
        if (err)
                goto out_orphans;
@@ -1754,10 +1757,8 @@ static void ubifs_put_super(struct super_block *sb)
 
                /* Synchronize write-buffers */
                if (c->jheads)
-                       for (i = 0; i < c->jhead_cnt; i++) {
+                       for (i = 0; i < c->jhead_cnt; i++)
                                ubifs_wbuf_sync(&c->jheads[i].wbuf);
-                               hrtimer_cancel(&c->jheads[i].wbuf.timer);
-                       }
 
                /*
                 * On fatal errors c->ro_media is set to 1, in which case we do
@@ -1975,7 +1976,8 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
        err  = bdi_init(&c->bdi);
        if (err)
                goto out_close;
-       err = bdi_register(&c->bdi, NULL, "ubifs");
+       err = bdi_register(&c->bdi, NULL, "ubifs_%d_%d",
+                          c->vi.ubi_num, c->vi.vol_id);
        if (err)
                goto out_bdi;
 
index 1bf01d8200667503cb0f0e310fafbc4304701721..a29349094422731766fa82a95201e0f14ad3c7fb 100644 (file)
@@ -95,8 +95,9 @@
  */
 #define BGT_NAME_PATTERN "ubifs_bgt%d_%d"
 
-/* Default write-buffer synchronization timeout in seconds */
-#define DEFAULT_WBUF_TIMEOUT_SECS 5
+/* Write-buffer synchronization timeout interval in seconds */
+#define WBUF_TIMEOUT_SOFTLIMIT 3
+#define WBUF_TIMEOUT_HARDLIMIT 5
 
 /* Maximum possible inode number (only 32-bit inodes are supported now) */
 #define MAX_INUM 0xFFFFFFFF
@@ -654,7 +655,8 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
  * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit
  *         and @softlimit + @delta)
  * @timer: write-buffer timer
- * @need_sync: it is set if its timer expired and needs sync
+ * @no_timer: non-zero if this write-buffer does not have a timer
+ * @need_sync: non-zero if the timer expired and the wbuf needs sync'ing
  * @next_ino: points to the next position of the following inode number
  * @inodes: stores the inode numbers of the nodes which are in wbuf
  *
@@ -683,7 +685,8 @@ struct ubifs_wbuf {
        ktime_t softlimit;
        unsigned long long delta;
        struct hrtimer timer;
-       int need_sync;
+       unsigned int no_timer:1;
+       unsigned int need_sync:1;
        int next_ino;
        ino_t *inodes;
 };