]>
Commit | Line | Data |
---|---|---|
9eefe2a2 SR |
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 | } |