xref: /rk3399_rockchip-uboot/fs/ubifs/lpt_commit.c (revision 9eefe2a2b37a838558e3d213a9f5519503d0c180)
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