2 * JFFS2 -- Journalling Flash File System, Version 2.
4 * Copyright (C) 2001 Red Hat, Inc.
6 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
8 * The original JFFS, from which the design for JFFS2 was derived,
9 * was designed and implemented by Axis Communications AB.
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/
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.
21 * The Original Code is JFFS2 - Journalling Flash File System, version 2
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.
34 * $Id: build.c,v 1.16.2.3 2003/04/30 09:43:32 dwmw2 Exp $
38 #include <linux/kernel.h>
39 #include <linux/jffs2.h>
40 #include <linux/slab.h>
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 *);
46 static inline struct jffs2_inode_cache *
47 first_inode_chain(int *i, struct jffs2_sb_info *c)
49 for (; *i < INOCACHE_HASHSIZE; (*i)++) {
50 if (c->inocache_list[*i])
51 return c->inocache_list[*i];
56 static inline struct jffs2_inode_cache *
57 next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
59 /* More in this chain? */
63 return first_inode_chain(i, c);
66 #define for_each_inode(i, c, ic) \
67 for (i = 0, ic = first_inode_chain(&i, (c)); \
69 ic = next_inode(&i, ic, (c)))
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
76 int jffs2_build_filesystem(struct jffs2_sb_info *c)
80 struct jffs2_inode_cache *ic;
82 /* First, scan the medium and build all the inode caches with
83 lists of physical nodes */
85 c->flags |= JFFS2_SB_FLAG_MOUNTING;
86 ret = jffs2_scan_medium(c);
87 c->flags &= ~JFFS2_SB_FLAG_MOUNTING;
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);
99 D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret));
103 D1(printk(KERN_DEBUG "Pass 1 complete\n"));
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. */
111 D1(printk(KERN_DEBUG "Pass 2 (re)starting\n"));
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));
118 ret = jffs2_build_remove_unlinked_inode(c, ic);
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. */
125 } while(ret == -EAGAIN);
127 D1(printk(KERN_DEBUG "Pass 2 complete\n"));
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));
136 D1(printk(KERN_WARNING "Why no scan struct for ino #%u which has nlink %d?\n", ic->ino, ic->nlink));
143 scan->dents = fd->next;
144 jffs2_free_full_dirent(fd);
148 D1(printk(KERN_DEBUG "Pass 3 complete\n"));
153 int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
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;
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;
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));
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;
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));
176 jffs2_free_full_dnode(metadata->fn);
177 jffs2_free_tmp_dnode_info(metadata);
182 jffs2_add_full_dnode_to_fraglist (c, &fraglist, tn->fn);
183 jffs2_free_tmp_dnode_info(tn);
188 D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring new metadata at 0x%08x\n",
189 tn->fn->raw->flash_offset &~3));
191 jffs2_free_full_dnode(tn->fn);
192 jffs2_free_tmp_dnode_info(tn);
197 /* OK. Now clear up */
199 jffs2_free_full_dnode(metadata->fn);
200 jffs2_free_tmp_dnode_info(metadata);
205 struct jffs2_node_frag *frag;
207 fraglist = fraglist->next;
209 if (frag->node && !(--frag->node->frags)) {
210 jffs2_free_full_dnode(frag->node);
212 jffs2_free_node_frag(frag);
215 /* Now for each child, increase nlink */
216 for(fd=ic->scan->dents; fd; fd = fd->next) {
217 struct jffs2_inode_cache *child_ic;
221 child_ic = jffs2_get_ino_cache(c, fd->ino);
223 printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
224 fd->name, fd->ino, ic->ino);
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");
234 /* What do we do about it? */
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 */
242 int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
244 struct jffs2_raw_node_ref *raw;
245 struct jffs2_full_dirent *fd;
249 D1(printk(KERN_DEBUG "ino #%u was already removed\n", ic->ino));
253 D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino));
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);
260 if (ic->scan->dents) {
261 printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino);
263 while(ic->scan->dents) {
264 struct jffs2_inode_cache *child_ic;
266 fd = ic->scan->dents;
267 ic->scan->dents = fd->next;
269 D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n",
272 child_ic = jffs2_get_ino_cache(c, fd->ino);
274 printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino);
277 jffs2_free_full_dirent(fd);
284 // jffs2_del_ino_cache(c, ic);
285 // jffs2_free_inode_cache(ic);