uboot/fs/ubifs/lpt_commit.c
<<
>>
Prefs
   1/*
   2 * This file is part of UBIFS.
   3 *
   4 * Copyright (C) 2006-2008 Nokia Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License version 2 as published by
   8 * the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along with
  16 * this program; if not, write to the Free Software Foundation, Inc., 51
  17 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18 *
  19 * Authors: Adrian Hunter
  20 *          Artem Bityutskiy (Битюцкий Артём)
  21 */
  22
  23/*
  24 * This file implements commit-related functionality of the LEB properties
  25 * subsystem.
  26 */
  27
  28#include "crc16.h"
  29#include "ubifs.h"
  30
  31/**
  32 * free_obsolete_cnodes - free obsolete cnodes for commit end.
  33 * @c: UBIFS file-system description object
  34 */
  35static void free_obsolete_cnodes(struct ubifs_info *c)
  36{
  37        struct ubifs_cnode *cnode, *cnext;
  38
  39        cnext = c->lpt_cnext;
  40        if (!cnext)
  41                return;
  42        do {
  43                cnode = cnext;
  44                cnext = cnode->cnext;
  45                if (test_bit(OBSOLETE_CNODE, &cnode->flags))
  46                        kfree(cnode);
  47                else
  48                        cnode->cnext = NULL;
  49        } while (cnext != c->lpt_cnext);
  50        c->lpt_cnext = NULL;
  51}
  52
  53/**
  54 * first_nnode - find the first nnode in memory.
  55 * @c: UBIFS file-system description object
  56 * @hght: height of tree where nnode found is returned here
  57 *
  58 * This function returns a pointer to the nnode found or %NULL if no nnode is
  59 * found. This function is a helper to 'ubifs_lpt_free()'.
  60 */
  61static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
  62{
  63        struct ubifs_nnode *nnode;
  64        int h, i, found;
  65
  66        nnode = c->nroot;
  67        *hght = 0;
  68        if (!nnode)
  69                return NULL;
  70        for (h = 1; h < c->lpt_hght; h++) {
  71                found = 0;
  72                for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
  73                        if (nnode->nbranch[i].nnode) {
  74                                found = 1;
  75                                nnode = nnode->nbranch[i].nnode;
  76                                *hght = h;
  77                                break;
  78                        }
  79                }
  80                if (!found)
  81                        break;
  82        }
  83        return nnode;
  84}
  85
  86/**
  87 * next_nnode - find the next nnode in memory.
  88 * @c: UBIFS file-system description object
  89 * @nnode: nnode from which to start.
  90 * @hght: height of tree where nnode is, is passed and returned here
  91 *
  92 * This function returns a pointer to the nnode found or %NULL if no nnode is
  93 * found. This function is a helper to 'ubifs_lpt_free()'.
  94 */
  95static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
  96                                      struct ubifs_nnode *nnode, int *hght)
  97{
  98        struct ubifs_nnode *parent;
  99        int iip, h, i, found;
 100
 101        parent = nnode->parent;
 102        if (!parent)
 103                return NULL;
 104        if (nnode->iip == UBIFS_LPT_FANOUT - 1) {
 105                *hght -= 1;
 106                return parent;
 107        }
 108        for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
 109                nnode = parent->nbranch[iip].nnode;
 110                if (nnode)
 111                        break;
 112        }
 113        if (!nnode) {
 114                *hght -= 1;
 115                return parent;
 116        }
 117        for (h = *hght + 1; h < c->lpt_hght; h++) {
 118                found = 0;
 119                for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
 120                        if (nnode->nbranch[i].nnode) {
 121                                found = 1;
 122                                nnode = nnode->nbranch[i].nnode;
 123                                *hght = h;
 124                                break;
 125                        }
 126                }
 127                if (!found)
 128                        break;
 129        }
 130        return nnode;
 131}
 132
 133/**
 134 * ubifs_lpt_free - free resources owned by the LPT.
 135 * @c: UBIFS file-system description object
 136 * @wr_only: free only resources used for writing
 137 */
 138void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
 139{
 140        struct ubifs_nnode *nnode;
 141        int i, hght;
 142
 143        /* Free write-only things first */
 144
 145        free_obsolete_cnodes(c); /* Leftover from a failed commit */
 146
 147        vfree(c->ltab_cmt);
 148        c->ltab_cmt = NULL;
 149        vfree(c->lpt_buf);
 150        c->lpt_buf = NULL;
 151        kfree(c->lsave);
 152        c->lsave = NULL;
 153
 154        if (wr_only)
 155                return;
 156
 157        /* Now free the rest */
 158
 159        nnode = first_nnode(c, &hght);
 160        while (nnode) {
 161                for (i = 0; i < UBIFS_LPT_FANOUT; i++)
 162                        kfree(nnode->nbranch[i].nnode);
 163                nnode = next_nnode(c, nnode, &hght);
 164        }
 165        for (i = 0; i < LPROPS_HEAP_CNT; i++)
 166                kfree(c->lpt_heap[i].arr);
 167        kfree(c->dirty_idx.arr);
 168        kfree(c->nroot);
 169        vfree(c->ltab);
 170        kfree(c->lpt_nod_buf);
 171}
 172