usb: gadget: udc: reduce indentation
[linux-2.6-block.git] / fs / ubifs / recovery.c
index 984e30e83c0b3eead78fdc61190026c78cd15d51..8526b7ec47077675fad73e1a74f48adeb250d212 100644 (file)
@@ -212,7 +212,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
        save_flags = mst->flags;
        mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
 
-       ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
+       err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ,
+                                     offsetof(struct ubifs_mst_node, hmac), 1);
+       if (err)
+               goto out;
        err = ubifs_leb_change(c, lnum, mst, sz);
        if (err)
                goto out;
@@ -264,9 +267,7 @@ int ubifs_recover_master_node(struct ubifs_info *c)
                        offs2 = (void *)mst2 - buf2;
                        if (offs1 == offs2) {
                                /* Same offset, so must be the same */
-                               if (memcmp((void *)mst1 + UBIFS_CH_SZ,
-                                          (void *)mst2 + UBIFS_CH_SZ,
-                                          UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
+                               if (ubifs_compare_master_node(c, mst1, mst2))
                                        goto out_err;
                                mst = mst1;
                        } else if (offs2 + sz == offs1) {
@@ -1461,16 +1462,82 @@ out:
        return err;
 }
 
+/**
+ * inode_fix_size - fix inode size
+ * @c: UBIFS file-system description object
+ * @e: inode size information for recovery
+ */
+static int inode_fix_size(struct ubifs_info *c, struct size_entry *e)
+{
+       struct inode *inode;
+       struct ubifs_inode *ui;
+       int err;
+
+       if (c->ro_mount)
+               ubifs_assert(c, !e->inode);
+
+       if (e->inode) {
+               /* Remounting rw, pick up inode we stored earlier */
+               inode = e->inode;
+       } else {
+               inode = ubifs_iget(c->vfs_sb, e->inum);
+               if (IS_ERR(inode))
+                       return PTR_ERR(inode);
+
+               if (inode->i_size >= e->d_size) {
+                       /*
+                        * The original inode in the index already has a size
+                        * big enough, nothing to do
+                        */
+                       iput(inode);
+                       return 0;
+               }
+
+               dbg_rcvry("ino %lu size %lld -> %lld",
+                         (unsigned long)e->inum,
+                         inode->i_size, e->d_size);
+
+               ui = ubifs_inode(inode);
+
+               inode->i_size = e->d_size;
+               ui->ui_size = e->d_size;
+               ui->synced_i_size = e->d_size;
+
+               e->inode = inode;
+       }
+
+       /*
+        * In readonly mode just keep the inode pinned in memory until we go
+        * readwrite. In readwrite mode write the inode to the journal with the
+        * fixed size.
+        */
+       if (c->ro_mount)
+               return 0;
+
+       err = ubifs_jnl_write_inode(c, inode);
+
+       iput(inode);
+
+       if (err)
+               return err;
+
+       rb_erase(&e->rb, &c->size_tree);
+       kfree(e);
+
+       return 0;
+}
+
 /**
  * ubifs_recover_size - recover inode size.
  * @c: UBIFS file-system description object
+ * @in_place: If true, do a in-place size fixup
  *
  * This function attempts to fix inode size discrepancies identified by the
  * 'ubifs_recover_size_accum()' function.
  *
  * This functions returns %0 on success and a negative error code on failure.
  */
-int ubifs_recover_size(struct ubifs_info *c)
+int ubifs_recover_size(struct ubifs_info *c, bool in_place)
 {
        struct rb_node *this = rb_first(&c->size_tree);
 
@@ -1479,6 +1546,9 @@ int ubifs_recover_size(struct ubifs_info *c)
                int err;
 
                e = rb_entry(this, struct size_entry, rb);
+
+               this = rb_next(this);
+
                if (!e->exists) {
                        union ubifs_key key;
 
@@ -1502,40 +1572,26 @@ int ubifs_recover_size(struct ubifs_info *c)
                }
 
                if (e->exists && e->i_size < e->d_size) {
-                       if (c->ro_mount) {
-                               /* Fix the inode size and pin it in memory */
-                               struct inode *inode;
-                               struct ubifs_inode *ui;
-
-                               ubifs_assert(c, !e->inode);
-
-                               inode = ubifs_iget(c->vfs_sb, e->inum);
-                               if (IS_ERR(inode))
-                                       return PTR_ERR(inode);
-
-                               ui = ubifs_inode(inode);
-                               if (inode->i_size < e->d_size) {
-                                       dbg_rcvry("ino %lu size %lld -> %lld",
-                                                 (unsigned long)e->inum,
-                                                 inode->i_size, e->d_size);
-                                       inode->i_size = e->d_size;
-                                       ui->ui_size = e->d_size;
-                                       ui->synced_i_size = e->d_size;
-                                       e->inode = inode;
-                                       this = rb_next(this);
-                                       continue;
-                               }
-                               iput(inode);
-                       } else {
-                               /* Fix the size in place */
+                       ubifs_assert(c, !(c->ro_mount && in_place));
+
+                       /*
+                        * We found data that is outside the found inode size,
+                        * fixup the inode size
+                        */
+
+                       if (in_place) {
                                err = fix_size_in_place(c, e);
                                if (err)
                                        return err;
                                iput(e->inode);
+                       } else {
+                               err = inode_fix_size(c, e);
+                               if (err)
+                                       return err;
+                               continue;
                        }
                }
 
-               this = rb_next(this);
                rb_erase(&e->rb, &c->size_tree);
                kfree(e);
        }