Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / fs / ubifs / gc.c
index d2680e0b4a36f38826f253d33c1b7d258b21bb2d..bf75fdc76fc357f7d8da299405fce8455a829e8d 100644 (file)
@@ -254,7 +254,8 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                             snod->type == UBIFS_DATA_NODE ||
                             snod->type == UBIFS_DENT_NODE ||
                             snod->type == UBIFS_XENT_NODE ||
-                            snod->type == UBIFS_TRUN_NODE);
+                            snod->type == UBIFS_TRUN_NODE ||
+                            snod->type == UBIFS_AUTH_NODE);
 
                if (snod->type != UBIFS_INO_NODE  &&
                    snod->type != UBIFS_DATA_NODE &&
@@ -364,12 +365,13 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
 
        /* Write nodes to their new location. Use the first-fit strategy */
        while (1) {
-               int avail;
+               int avail, moved = 0;
                struct ubifs_scan_node *snod, *tmp;
 
                /* Move data nodes */
                list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
-                       avail = c->leb_size - wbuf->offs - wbuf->used;
+                       avail = c->leb_size - wbuf->offs - wbuf->used -
+                                       ubifs_auth_node_sz(c);
                        if  (snod->len > avail)
                                /*
                                 * Do not skip data nodes in order to optimize
@@ -377,14 +379,21 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
                                 */
                                break;
 
+                       err = ubifs_shash_update(c, c->jheads[GCHD].log_hash,
+                                                snod->node, snod->len);
+                       if (err)
+                               goto out;
+
                        err = move_node(c, sleb, snod, wbuf);
                        if (err)
                                goto out;
+                       moved = 1;
                }
 
                /* Move non-data nodes */
                list_for_each_entry_safe(snod, tmp, &nondata, list) {
-                       avail = c->leb_size - wbuf->offs - wbuf->used;
+                       avail = c->leb_size - wbuf->offs - wbuf->used -
+                                       ubifs_auth_node_sz(c);
                        if (avail < min)
                                break;
 
@@ -402,9 +411,41 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
                                continue;
                        }
 
+                       err = ubifs_shash_update(c, c->jheads[GCHD].log_hash,
+                                                snod->node, snod->len);
+                       if (err)
+                               goto out;
+
                        err = move_node(c, sleb, snod, wbuf);
                        if (err)
                                goto out;
+                       moved = 1;
+               }
+
+               if (ubifs_authenticated(c) && moved) {
+                       struct ubifs_auth_node *auth;
+
+                       auth = kmalloc(ubifs_auth_node_sz(c), GFP_NOFS);
+                       if (!auth) {
+                               err = -ENOMEM;
+                               goto out;
+                       }
+
+                       err = ubifs_prepare_auth_node(c, auth,
+                                               c->jheads[GCHD].log_hash);
+                       if (err) {
+                               kfree(auth);
+                               goto out;
+                       }
+
+                       err = ubifs_wbuf_write_nolock(wbuf, auth,
+                                                     ubifs_auth_node_sz(c));
+                       if (err) {
+                               kfree(auth);
+                               goto out;
+                       }
+
+                       ubifs_add_dirt(c, wbuf->lnum, ubifs_auth_node_sz(c));
                }
 
                if (list_empty(&sleb->nodes) && list_empty(&nondata))