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