Merge branch 'stable/bug.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / fs / ubifs / io.c
index 3be645e..9228950 100644 (file)
@@ -86,8 +86,125 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
                c->no_chk_data_crc = 0;
                c->vfs_sb->s_flags |= MS_RDONLY;
                ubifs_warn("switched to read-only mode, error %d", err);
+               dump_stack();
+       }
+}
+
+/*
+ * Below are simple wrappers over UBI I/O functions which include some
+ * additional checks and UBIFS debugging stuff. See corresponding UBI function
+ * for more information.
+ */
+
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+                  int len, int even_ebadmsg)
+{
+       int err;
+
+       err = ubi_read(c->ubi, lnum, buf, offs, len);
+       /*
+        * In case of %-EBADMSG print the error message only if the
+        * @even_ebadmsg is true.
+        */
+       if (err && (err != -EBADMSG || even_ebadmsg)) {
+               ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
+                         len, lnum, offs, err);
+               dbg_dump_stack();
+       }
+       return err;
+}
+
+int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+                   int len, int dtype)
+{
+       int err;
+
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
+               return -EROFS;
+       if (!dbg_is_tst_rcvry(c))
+               err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
+       else
+               err = dbg_leb_write(c, lnum, buf, offs, len, dtype);
+       if (err) {
+               ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
+                         len, lnum, offs, err);
+               ubifs_ro_mode(c, err);
+               dbg_dump_stack();
+       }
+       return err;
+}
+
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
+                    int dtype)
+{
+       int err;
+
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
+               return -EROFS;
+       if (!dbg_is_tst_rcvry(c))
+               err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
+       else
+               err = dbg_leb_change(c, lnum, buf, len, dtype);
+       if (err) {
+               ubifs_err("changing %d bytes in LEB %d failed, error %d",
+                         len, lnum, err);
+               ubifs_ro_mode(c, err);
+               dbg_dump_stack();
+       }
+       return err;
+}
+
+int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
+{
+       int err;
+
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
+               return -EROFS;
+       if (!dbg_is_tst_rcvry(c))
+               err = ubi_leb_unmap(c->ubi, lnum);
+       else
+               err = dbg_leb_unmap(c, lnum);
+       if (err) {
+               ubifs_err("unmap LEB %d failed, error %d", lnum, err);
+               ubifs_ro_mode(c, err);
+               dbg_dump_stack();
+       }
+       return err;
+}
+
+int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
+{
+       int err;
+
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
+               return -EROFS;
+       if (!dbg_is_tst_rcvry(c))
+               err = ubi_leb_map(c->ubi, lnum, dtype);
+       else
+               err = dbg_leb_map(c, lnum, dtype);
+       if (err) {
+               ubifs_err("mapping LEB %d failed, error %d", lnum, err);
+               ubifs_ro_mode(c, err);
+               dbg_dump_stack();
+       }
+       return err;
+}
+
+int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
+{
+       int err;
+
+       err = ubi_is_mapped(c->ubi, lnum);
+       if (err < 0) {
+               ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
+                         lnum, err);
                dbg_dump_stack();
        }
+       return err;
 }
 
 /**
@@ -406,14 +523,10 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
        dirt = sync_len - wbuf->used;
        if (dirt)
                ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
-       err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-                           sync_len, wbuf->dtype);
-       if (err) {
-               ubifs_err("cannot write %d bytes to LEB %d:%d",
-                         sync_len, wbuf->lnum, wbuf->offs);
-               dbg_dump_stack();
+       err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len,
+                             wbuf->dtype);
+       if (err)
                return err;
-       }
 
        spin_lock(&wbuf->lock);
        wbuf->offs += sync_len;
@@ -605,9 +718,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
                if (aligned_len == wbuf->avail) {
                        dbg_io("flush jhead %s wbuf to LEB %d:%d",
                               dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
-                       err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
-                                           wbuf->offs, wbuf->size,
-                                           wbuf->dtype);
+                       err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
+                                             wbuf->offs, wbuf->size,
+                                             wbuf->dtype);
                        if (err)
                                goto out;
 
@@ -642,8 +755,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
                dbg_io("flush jhead %s wbuf to LEB %d:%d",
                       dbg_jhead(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,
-                                   wbuf->size, wbuf->dtype);
+               err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
+                                     wbuf->size, wbuf->dtype);
                if (err)
                        goto out;
 
@@ -661,8 +774,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
                 */
                dbg_io("write %d bytes to LEB %d:%d",
                       wbuf->size, wbuf->lnum, wbuf->offs);
-               err = ubi_leb_write(c->ubi, wbuf->lnum, buf, wbuf->offs,
-                                   wbuf->size, wbuf->dtype);
+               err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
+                                     wbuf->size, wbuf->dtype);
                if (err)
                        goto out;
 
@@ -683,8 +796,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
                n <<= c->max_write_shift;
                dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
                       wbuf->offs);
-               err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written,
-                                   wbuf->offs, n, wbuf->dtype);
+               err = ubifs_leb_write(c, wbuf->lnum, buf + written,
+                                     wbuf->offs, n, wbuf->dtype);
                if (err)
                        goto out;
                wbuf->offs += n;
@@ -766,13 +879,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
                return -EROFS;
 
        ubifs_prepare_node(c, buf, len, 1);
-       err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype);
-       if (err) {
-               ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
-                         buf_len, lnum, offs, err);
+       err = ubifs_leb_write(c, lnum, buf, offs, buf_len, dtype);
+       if (err)
                dbg_dump_node(c, buf);
-               dbg_dump_stack();
-       }
 
        return err;
 }
@@ -824,13 +933,9 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
 
        if (rlen > 0) {
                /* Read everything that goes before write-buffer */
-               err = ubi_read(c->ubi, lnum, buf, offs, rlen);
-               if (err && err != -EBADMSG) {
-                       ubifs_err("failed to read node %d from LEB %d:%d, "
-                                 "error %d", type, lnum, offs, err);
-                       dbg_dump_stack();
+               err = ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
+               if (err && err != -EBADMSG)
                        return err;
-               }
        }
 
        if (type != ch->node_type) {
@@ -885,12 +990,9 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
        ubifs_assert(!(offs & 7) && offs < c->leb_size);
        ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
 
-       err = ubi_read(c->ubi, lnum, buf, offs, len);
-       if (err && err != -EBADMSG) {
-               ubifs_err("cannot read node %d from LEB %d:%d, error %d",
-                         type, lnum, offs, err);
+       err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
+       if (err && err != -EBADMSG)
                return err;
-       }
 
        if (type != ch->node_type) {
                ubifs_err("bad node type (%d but expected %d)",