Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / fs / ubifs / lpt_commit.c
diff --git a/qemu/roms/u-boot/fs/ubifs/lpt_commit.c b/qemu/roms/u-boot/fs/ubifs/lpt_commit.c
new file mode 100644 (file)
index 0000000..c0af818
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Adrian Hunter
+ *          Artem Bityutskiy (Битюцкий Артём)
+ */
+
+/*
+ * This file implements commit-related functionality of the LEB properties
+ * subsystem.
+ */
+
+#include "crc16.h"
+#include "ubifs.h"
+
+/**
+ * free_obsolete_cnodes - free obsolete cnodes for commit end.
+ * @c: UBIFS file-system description object
+ */
+static void free_obsolete_cnodes(struct ubifs_info *c)
+{
+       struct ubifs_cnode *cnode, *cnext;
+
+       cnext = c->lpt_cnext;
+       if (!cnext)
+               return;
+       do {
+               cnode = cnext;
+               cnext = cnode->cnext;
+               if (test_bit(OBSOLETE_CNODE, &cnode->flags))
+                       kfree(cnode);
+               else
+                       cnode->cnext = NULL;
+       } while (cnext != c->lpt_cnext);
+       c->lpt_cnext = NULL;
+}
+
+/**
+ * first_nnode - find the first nnode in memory.
+ * @c: UBIFS file-system description object
+ * @hght: height of tree where nnode found is returned here
+ *
+ * This function returns a pointer to the nnode found or %NULL if no nnode is
+ * found. This function is a helper to 'ubifs_lpt_free()'.
+ */
+static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
+{
+       struct ubifs_nnode *nnode;
+       int h, i, found;
+
+       nnode = c->nroot;
+       *hght = 0;
+       if (!nnode)
+               return NULL;
+       for (h = 1; h < c->lpt_hght; h++) {
+               found = 0;
+               for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+                       if (nnode->nbranch[i].nnode) {
+                               found = 1;
+                               nnode = nnode->nbranch[i].nnode;
+                               *hght = h;
+                               break;
+                       }
+               }
+               if (!found)
+                       break;
+       }
+       return nnode;
+}
+
+/**
+ * next_nnode - find the next nnode in memory.
+ * @c: UBIFS file-system description object
+ * @nnode: nnode from which to start.
+ * @hght: height of tree where nnode is, is passed and returned here
+ *
+ * This function returns a pointer to the nnode found or %NULL if no nnode is
+ * found. This function is a helper to 'ubifs_lpt_free()'.
+ */
+static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
+                                     struct ubifs_nnode *nnode, int *hght)
+{
+       struct ubifs_nnode *parent;
+       int iip, h, i, found;
+
+       parent = nnode->parent;
+       if (!parent)
+               return NULL;
+       if (nnode->iip == UBIFS_LPT_FANOUT - 1) {
+               *hght -= 1;
+               return parent;
+       }
+       for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
+               nnode = parent->nbranch[iip].nnode;
+               if (nnode)
+                       break;
+       }
+       if (!nnode) {
+               *hght -= 1;
+               return parent;
+       }
+       for (h = *hght + 1; h < c->lpt_hght; h++) {
+               found = 0;
+               for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+                       if (nnode->nbranch[i].nnode) {
+                               found = 1;
+                               nnode = nnode->nbranch[i].nnode;
+                               *hght = h;
+                               break;
+                       }
+               }
+               if (!found)
+                       break;
+       }
+       return nnode;
+}
+
+/**
+ * ubifs_lpt_free - free resources owned by the LPT.
+ * @c: UBIFS file-system description object
+ * @wr_only: free only resources used for writing
+ */
+void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
+{
+       struct ubifs_nnode *nnode;
+       int i, hght;
+
+       /* Free write-only things first */
+
+       free_obsolete_cnodes(c); /* Leftover from a failed commit */
+
+       vfree(c->ltab_cmt);
+       c->ltab_cmt = NULL;
+       vfree(c->lpt_buf);
+       c->lpt_buf = NULL;
+       kfree(c->lsave);
+       c->lsave = NULL;
+
+       if (wr_only)
+               return;
+
+       /* Now free the rest */
+
+       nnode = first_nnode(c, &hght);
+       while (nnode) {
+               for (i = 0; i < UBIFS_LPT_FANOUT; i++)
+                       kfree(nnode->nbranch[i].nnode);
+               nnode = next_nnode(c, nnode, &hght);
+       }
+       for (i = 0; i < LPROPS_HEAP_CNT; i++)
+               kfree(c->lpt_heap[i].arr);
+       kfree(c->dirty_idx.arr);
+       kfree(c->nroot);
+       vfree(c->ltab);
+       kfree(c->lpt_nod_buf);
+}