ubifs: Fix journal replay wrt. xattr nodes
[pandora-kernel.git] / fs / ubifs / tnc.c
index 91b4213..f996cb5 100644 (file)
 #include <linux/slab.h>
 #include "ubifs.h"
 
+static int try_read_node(const struct ubifs_info *c, void *buf, int type,
+                        int len, int lnum, int offs);
+static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
+                             struct ubifs_zbranch *zbr, void *node);
+
 /*
  * Returned codes of 'matches_name()' and 'fallible_matches_name()' functions.
  * @NAME_LESS: name corresponding to the first argument is less than second
@@ -223,7 +228,7 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
        __set_bit(DIRTY_ZNODE, &zn->flags);
        __clear_bit(COW_ZNODE, &zn->flags);
 
-       ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+       ubifs_assert(!ubifs_zn_obsolete(znode));
        __set_bit(OBSOLETE_ZNODE, &znode->flags);
 
        if (znode->level != 0) {
@@ -271,7 +276,7 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
        struct ubifs_znode *zn;
        int err;
 
-       if (!test_bit(COW_ZNODE, &znode->flags)) {
+       if (!ubifs_zn_cow(znode)) {
                /* znode is not being committed */
                if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) {
                        atomic_long_inc(&c->dirty_zn_cnt);
@@ -420,7 +425,19 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr,
                return 0;
        }
 
-       err = ubifs_tnc_read_node(c, zbr, node);
+       if (c->replaying) {
+               err = fallible_read_node(c, &zbr->key, zbr, node);
+               /*
+                * When the node was not found, return -ENOENT, 0 otherwise.
+                * Negative return codes stay as-is.
+                */
+               if (err == 0)
+                       err = -ENOENT;
+               else if (err == 1)
+                       err = 0;
+       } else {
+               err = ubifs_tnc_read_node(c, zbr, node);
+       }
        if (err)
                return err;
 
@@ -462,7 +479,7 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
 
        dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
 
-       err = ubi_read(c->ubi, lnum, buf, offs, len);
+       err = ubifs_leb_read(c, lnum, buf, offs, len, 1);
        if (err) {
                ubifs_err("cannot read node type %d from LEB %d:%d, error %d",
                          type, lnum, offs, err);
@@ -1666,7 +1683,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
        if (!overlap) {
                /* We may safely unlock the write-buffer and read the data */
                spin_unlock(&wbuf->lock);
-               return ubi_read(c->ubi, lnum, buf, offs, len);
+               return ubifs_leb_read(c, lnum, buf, offs, len, 0);
        }
 
        /* Don't read under wbuf */
@@ -1680,7 +1697,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
 
        if (rlen > 0)
                /* Read everything that goes before write-buffer */
-               return ubi_read(c->ubi, lnum, buf, offs, rlen);
+               return ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
 
        return 0;
 }
@@ -1767,7 +1784,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)
        if (wbuf)
                err = read_wbuf(wbuf, bu->buf, len, lnum, offs);
        else
-               err = ubi_read(c->ubi, lnum, bu->buf, offs, len);
+               err = ubifs_leb_read(c, lnum, bu->buf, offs, len, 0);
 
        /* Check for a race with GC */
        if (maybe_leb_gced(c, lnum, bu->gc_seq))
@@ -2423,7 +2440,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
         */
 
        do {
-               ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+               ubifs_assert(!ubifs_zn_obsolete(znode));
                ubifs_assert(ubifs_zn_dirty(znode));
 
                zp = znode->parent;
@@ -2479,9 +2496,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
                        c->zroot.offs = zbr->offs;
                        c->zroot.len = zbr->len;
                        c->zroot.znode = znode;
-                       ubifs_assert(!test_bit(OBSOLETE_ZNODE,
-                                    &zp->flags));
-                       ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags));
+                       ubifs_assert(!ubifs_zn_obsolete(zp));
+                       ubifs_assert(ubifs_zn_dirty(zp));
                        atomic_long_dec(&c->dirty_zn_cnt);
 
                        if (zp->cnext) {
@@ -2786,7 +2802,11 @@ struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,
        if (nm->name) {
                if (err) {
                        /* Handle collisions */
-                       err = resolve_collision(c, key, &znode, &n, nm);
+                       if (c->replaying)
+                               err = fallible_resolve_collision(c, key, &znode, &n,
+                                                        nm, 0);
+                       else
+                               err = resolve_collision(c, key, &znode, &n, nm);
                        dbg_tnc("rc returned %d, znode %p, n %d",
                                err, znode, n);
                        if (unlikely(err < 0))
@@ -2865,7 +2885,7 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
                struct ubifs_znode *znode = cnext;
 
                cnext = cnext->cnext;
-               if (test_bit(OBSOLETE_ZNODE, &znode->flags))
+               if (ubifs_zn_obsolete(znode))
                        kfree(znode);
        } while (cnext && cnext != c->cnext);
 }
@@ -3301,7 +3321,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 
        if (!S_ISREG(inode->i_mode))
                return 0;
-       if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+       if (!dbg_is_chk_gen(c))
                return 0;
 
        block = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
@@ -3337,9 +3357,10 @@ out_dump:
        ubifs_err("inode %lu has size %lld, but there are data at offset %lld "
                  "(data key %s)", (unsigned long)inode->i_ino, size,
                  ((loff_t)block) << UBIFS_BLOCK_SHIFT, DBGKEY(key));
+       mutex_unlock(&c->tnc_mutex);
        dbg_dump_inode(c, inode);
        dbg_dump_stack();
-       err = -EINVAL;
+       return -EINVAL;
 
 out_unlock:
        mutex_unlock(&c->tnc_mutex);