/* * 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); }