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 */ 35 static 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 */ 61 static 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 */ 95 static 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 */ 138 void 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