1 /*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7 *
8 * The original JFFS, from which the design for JFFS2 was derived,
9 * was designed and implemented by Axis Communications AB.
10 *
11 * The contents of this file are subject to the Red Hat eCos Public
12 * License Version 1.1 (the "Licence"); you may not use this file
13 * except in compliance with the Licence. You may obtain a copy of
14 * the Licence at http://www.redhat.com/
15 *
16 * Software distributed under the Licence is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
18 * See the Licence for the specific language governing rights and
19 * limitations under the Licence.
20 *
21 * The Original Code is JFFS2 - Journalling Flash File System, version 2
22 *
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU General Public License version 2 (the "GPL"), in
25 * which case the provisions of the GPL are applicable instead of the
26 * above. If you wish to allow the use of your version of this file
27 * only under the terms of the GPL and not to allow others to use your
28 * version of this file under the RHEPL, indicate your decision by
29 * deleting the provisions above and replace them with the notice and
30 * other provisions required by the GPL. If you do not delete the
31 * provisions above, a recipient may use your version of this file
32 * under either the RHEPL or the GPL.
33 *
34 * $Id: build.c,v 1.16.2.3 2003/04/30 09:43:32 dwmw2 Exp $
35 *
36 */
37
38 #include <linux/kernel.h>
39 #include <linux/jffs2.h>
40 #include <linux/slab.h>
41 #include "nodelist.h"
42
43 int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *);
44 int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *);
45
46 static inline struct jffs2_inode_cache *
first_inode_chain(int * i,struct jffs2_sb_info * c)47 first_inode_chain(int *i, struct jffs2_sb_info *c)
48 {
49 for (; *i < INOCACHE_HASHSIZE; (*i)++) {
50 if (c->inocache_list[*i])
51 return c->inocache_list[*i];
52 }
53 return NULL;
54 }
55
56 static inline struct jffs2_inode_cache *
next_inode(int * i,struct jffs2_inode_cache * ic,struct jffs2_sb_info * c)57 next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
58 {
59 /* More in this chain? */
60 if (ic->next)
61 return ic->next;
62 (*i)++;
63 return first_inode_chain(i, c);
64 }
65
66 #define for_each_inode(i, c, ic) \
67 for (i = 0, ic = first_inode_chain(&i, (c)); \
68 ic; \
69 ic = next_inode(&i, ic, (c)))
70
71 /* Scan plan:
72 - Scan physical nodes. Build map of inodes/dirents. Allocate inocaches as we go
73 - Scan directory tree from top down, setting nlink in inocaches
74 - Scan inocaches for inodes with nlink==0
75 */
jffs2_build_filesystem(struct jffs2_sb_info * c)76 int jffs2_build_filesystem(struct jffs2_sb_info *c)
77 {
78 int ret;
79 int i;
80 struct jffs2_inode_cache *ic;
81
82 /* First, scan the medium and build all the inode caches with
83 lists of physical nodes */
84
85 c->flags |= JFFS2_SB_FLAG_MOUNTING;
86 ret = jffs2_scan_medium(c);
87 c->flags &= ~JFFS2_SB_FLAG_MOUNTING;
88
89 if (ret)
90 return ret;
91
92 D1(printk(KERN_DEBUG "Scanned flash completely\n"));
93 /* Now build the data map for each inode, marking obsoleted nodes
94 as such, and also increase nlink of any children. */
95 for_each_inode(i, c, ic) {
96 D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino));
97 ret = jffs2_build_inode_pass1(c, ic);
98 if (ret) {
99 D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret));
100 return ret;
101 }
102 }
103 D1(printk(KERN_DEBUG "Pass 1 complete\n"));
104
105 /* Next, scan for inodes with nlink == 0 and remove them. If
106 they were directories, then decrement the nlink of their
107 children too, and repeat the scan. As that's going to be
108 a fairly uncommon occurrence, it's not so evil to do it this
109 way. Recursion bad. */
110 do {
111 D1(printk(KERN_DEBUG "Pass 2 (re)starting\n"));
112 ret = 0;
113 for_each_inode(i, c, ic) {
114 D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes));
115 if (ic->nlink)
116 continue;
117
118 ret = jffs2_build_remove_unlinked_inode(c, ic);
119 if (ret)
120 break;
121 /* -EAGAIN means the inode's nlink was zero, so we deleted it,
122 and furthermore that it had children and their nlink has now
123 gone to zero too. So we have to restart the scan. */
124 }
125 } while(ret == -EAGAIN);
126
127 D1(printk(KERN_DEBUG "Pass 2 complete\n"));
128
129 /* Finally, we can scan again and free the dirent nodes and scan_info structs */
130 for_each_inode(i, c, ic) {
131 struct jffs2_scan_info *scan = ic->scan;
132 struct jffs2_full_dirent *fd;
133 D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes));
134 if (!scan) {
135 if (ic->nlink) {
136 D1(printk(KERN_WARNING "Why no scan struct for ino #%u which has nlink %d?\n", ic->ino, ic->nlink));
137 }
138 continue;
139 }
140 ic->scan = NULL;
141 while(scan->dents) {
142 fd = scan->dents;
143 scan->dents = fd->next;
144 jffs2_free_full_dirent(fd);
145 }
146 kfree(scan);
147 }
148 D1(printk(KERN_DEBUG "Pass 3 complete\n"));
149
150 return ret;
151 }
152
jffs2_build_inode_pass1(struct jffs2_sb_info * c,struct jffs2_inode_cache * ic)153 int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
154 {
155 struct jffs2_tmp_dnode_info *tn;
156 struct jffs2_full_dirent *fd;
157 struct jffs2_node_frag *fraglist = NULL;
158 struct jffs2_tmp_dnode_info *metadata = NULL;
159
160 D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino));
161 if (ic->ino > c->highest_ino)
162 c->highest_ino = ic->ino;
163
164 if (!ic->scan->tmpnodes && ic->ino != 1) {
165 D1(printk(KERN_DEBUG "jffs2_build_inode: ino #%u has no data nodes!\n", ic->ino));
166 }
167 /* Build the list to make sure any obsolete nodes are marked as such */
168 while(ic->scan->tmpnodes) {
169 tn = ic->scan->tmpnodes;
170 ic->scan->tmpnodes = tn->next;
171
172 if (metadata && tn->version > metadata->version) {
173 D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring old metadata at 0x%08x\n",
174 metadata->fn->raw->flash_offset &~3));
175
176 jffs2_free_full_dnode(metadata->fn);
177 jffs2_free_tmp_dnode_info(metadata);
178 metadata = NULL;
179 }
180
181 if (tn->fn->size) {
182 jffs2_add_full_dnode_to_fraglist (c, &fraglist, tn->fn);
183 jffs2_free_tmp_dnode_info(tn);
184 } else {
185 if (!metadata) {
186 metadata = tn;
187 } else {
188 D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring new metadata at 0x%08x\n",
189 tn->fn->raw->flash_offset &~3));
190
191 jffs2_free_full_dnode(tn->fn);
192 jffs2_free_tmp_dnode_info(tn);
193 }
194 }
195 }
196
197 /* OK. Now clear up */
198 if (metadata) {
199 jffs2_free_full_dnode(metadata->fn);
200 jffs2_free_tmp_dnode_info(metadata);
201 }
202 metadata = NULL;
203
204 while (fraglist) {
205 struct jffs2_node_frag *frag;
206 frag = fraglist;
207 fraglist = fraglist->next;
208
209 if (frag->node && !(--frag->node->frags)) {
210 jffs2_free_full_dnode(frag->node);
211 }
212 jffs2_free_node_frag(frag);
213 }
214
215 /* Now for each child, increase nlink */
216 for(fd=ic->scan->dents; fd; fd = fd->next) {
217 struct jffs2_inode_cache *child_ic;
218 if (!fd->ino)
219 continue;
220
221 child_ic = jffs2_get_ino_cache(c, fd->ino);
222 if (!child_ic) {
223 printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
224 fd->name, fd->ino, ic->ino);
225 continue;
226 }
227
228 if (child_ic->nlink++ && fd->type == DT_DIR) {
229 printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino);
230 if (fd->ino == 1 && ic->ino == 1) {
231 printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n");
232 printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n");
233 }
234 /* What do we do about it? */
235 }
236 D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino));
237 /* Can't free them. We might need them in pass 2 */
238 }
239 return 0;
240 }
241
jffs2_build_remove_unlinked_inode(struct jffs2_sb_info * c,struct jffs2_inode_cache * ic)242 int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
243 {
244 struct jffs2_raw_node_ref *raw;
245 struct jffs2_full_dirent *fd;
246 int ret = 0;
247
248 if(!ic->scan) {
249 D1(printk(KERN_DEBUG "ino #%u was already removed\n", ic->ino));
250 return 0;
251 }
252
253 D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino));
254
255 for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) {
256 D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", raw->flash_offset&~3));
257 jffs2_mark_node_obsolete(c, raw);
258 }
259
260 if (ic->scan->dents) {
261 printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino);
262
263 while(ic->scan->dents) {
264 struct jffs2_inode_cache *child_ic;
265
266 fd = ic->scan->dents;
267 ic->scan->dents = fd->next;
268
269 D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n",
270 fd->name, fd->ino));
271
272 child_ic = jffs2_get_ino_cache(c, fd->ino);
273 if (!child_ic) {
274 printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino);
275 continue;
276 }
277 jffs2_free_full_dirent(fd);
278 child_ic->nlink--;
279 }
280 ret = -EAGAIN;
281 }
282 kfree(ic->scan);
283 ic->scan = NULL;
284 // jffs2_del_ino_cache(c, ic);
285 // jffs2_free_inode_cache(ic);
286 return ret;
287 }
288