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