annotate packages/fs/jffs2/current/src/build.c @ 1118:18f99a0f0059

Merge with latest CVS from infradead.org
author gthomas
date Tue, 15 Jul 2003 20:45:32 +0000
parents a7947d436e85
children 121121d3d18f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
1 /*
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
2 * JFFS2 -- Journalling Flash File System, Version 2.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
3 *
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
4 * Copyright (C) 2001, 2002 Red Hat, Inc.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
5 *
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
6 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
7 *
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
8 * For licensing information, see the file 'LICENCE' in this directory.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
9 *
1118
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
10 * $Id: build.c,v 1.46 2003/04/29 17:12:26 gleixner Exp $
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
11 *
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
12 */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
13
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
14 #include <linux/kernel.h>
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
15 #include <linux/sched.h>
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
16 #include <linux/slab.h>
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
17 #include "nodelist.h"
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
18
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
19 int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
20 int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
21
1118
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
22 static inline struct jffs2_inode_cache *
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
23 first_inode_chain(int *i, struct jffs2_sb_info *c)
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
24 {
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
25 for (; *i < INOCACHE_HASHSIZE; (*i)++) {
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
26 if (c->inocache_list[*i])
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
27 return c->inocache_list[*i];
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
28 }
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
29 return NULL;
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
30 }
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
31
1118
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
32 static inline struct jffs2_inode_cache *
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
33 next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
34 {
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
35 /* More in this chain? */
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
36 if (ic->next)
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
37 return ic->next;
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
38 (*i)++;
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
39 return first_inode_chain(i, c);
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
40 }
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
41
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
42 #define for_each_inode(i, c, ic) \
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
43 for (i = 0, ic = first_inode_chain(&i, (c)); \
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
44 ic; \
18f99a0f0059 Merge with latest CVS from infradead.org
gthomas
parents: 570
diff changeset
45 ic = next_inode(&i, ic, (c)))
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
46
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
47 /* Scan plan:
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
48 - Scan physical nodes. Build map of inodes/dirents. Allocate inocaches as we go
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
49 - Scan directory tree from top down, setting nlink in inocaches
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
50 - Scan inocaches for inodes with nlink==0
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
51 */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
52 static int jffs2_build_filesystem(struct jffs2_sb_info *c)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
53 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
54 int ret;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
55 int i;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
56 struct jffs2_inode_cache *ic;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
57
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
58 /* First, scan the medium and build all the inode caches with
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
59 lists of physical nodes */
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
60
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
61 c->flags |= JFFS2_SB_FLAG_MOUNTING;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
62 ret = jffs2_scan_medium(c);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
63 c->flags &= ~JFFS2_SB_FLAG_MOUNTING;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
64
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
65 if (ret)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
66 return ret;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
67
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
68 D1(printk(KERN_DEBUG "Scanned flash completely\n"));
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
69 D1(jffs2_dump_block_lists(c));
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
70
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
71 /* Now scan the directory tree, increasing nlink according to every dirent found. */
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
72 for_each_inode(i, c, ic) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
73 D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
74 ret = jffs2_build_inode_pass1(c, ic);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
75 if (ret) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
76 D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
77 return ret;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
78 }
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
79 cond_resched();
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
80 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
81 D1(printk(KERN_DEBUG "Pass 1 complete\n"));
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
82 D1(jffs2_dump_block_lists(c));
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
83
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
84 /* Next, scan for inodes with nlink == 0 and remove them. If
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
85 they were directories, then decrement the nlink of their
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
86 children too, and repeat the scan. As that's going to be
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
87 a fairly uncommon occurrence, it's not so evil to do it this
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
88 way. Recursion bad. */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
89 do {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
90 D1(printk(KERN_DEBUG "Pass 2 (re)starting\n"));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
91 ret = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
92 for_each_inode(i, c, ic) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
93 D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
94 if (ic->nlink)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
95 continue;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
96
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
97 /* XXX: Can get high latency here. Move the cond_resched() from the end of the loop? */
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
98
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
99 ret = jffs2_build_remove_unlinked_inode(c, ic);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
100 if (ret)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
101 break;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
102 /* -EAGAIN means the inode's nlink was zero, so we deleted it,
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
103 and furthermore that it had children and their nlink has now
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
104 gone to zero too. So we have to restart the scan. */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
105 }
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
106 D1(jffs2_dump_block_lists(c));
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
107
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
108 cond_resched();
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
109
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
110 } while(ret == -EAGAIN);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
111
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
112 D1(printk(KERN_DEBUG "Pass 2 complete\n"));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
113
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
114 /* Finally, we can scan again and free the dirent nodes and scan_info structs */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
115 for_each_inode(i, c, ic) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
116 struct jffs2_full_dirent *fd;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
117 D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes));
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
118
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
119 while(ic->scan_dents) {
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
120 fd = ic->scan_dents;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
121 ic->scan_dents = fd->next;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
122 jffs2_free_full_dirent(fd);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
123 }
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
124 ic->scan_dents = NULL;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
125 cond_resched();
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
126 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
127 D1(printk(KERN_DEBUG "Pass 3 complete\n"));
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
128 D1(jffs2_dump_block_lists(c));
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
129
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
130 /* Rotate the lists by some number to ensure wear levelling */
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
131 jffs2_rotate_lists(c);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
132
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
133 return ret;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
134 }
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
135
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
136 int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
137 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
138 struct jffs2_full_dirent *fd;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
139
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
140 D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino));
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
141
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
142 if (ic->ino > c->highest_ino)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
143 c->highest_ino = ic->ino;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
144
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
145 /* For each child, increase nlink */
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
146 for(fd=ic->scan_dents; fd; fd = fd->next) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
147 struct jffs2_inode_cache *child_ic;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
148 if (!fd->ino)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
149 continue;
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
150
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
151 /* XXX: Can get high latency here with huge directories */
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
152
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
153 child_ic = jffs2_get_ino_cache(c, fd->ino);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
154 if (!child_ic) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
155 printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
156 fd->name, fd->ino, ic->ino);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
157 continue;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
158 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
159
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
160 if (child_ic->nlink++ && fd->type == DT_DIR) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
161 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);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
162 if (fd->ino == 1 && ic->ino == 1) {
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
163 printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n");
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
164 printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n");
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
165 }
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
166 /* What do we do about it? */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
167 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
168 D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
169 /* Can't free them. We might need them in pass 2 */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
170 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
171 return 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
172 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
173
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
174 int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
175 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
176 struct jffs2_raw_node_ref *raw;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
177 struct jffs2_full_dirent *fd;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
178 int ret = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
179
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
180 D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
181
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
182 for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) {
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
183 D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw)));
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
184 jffs2_mark_node_obsolete(c, raw);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
185 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
186
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
187 if (ic->scan_dents) {
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
188 int whinged = 0;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
189 D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino));
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
190
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
191 while(ic->scan_dents) {
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
192 struct jffs2_inode_cache *child_ic;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
193
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
194 fd = ic->scan_dents;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
195 ic->scan_dents = fd->next;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
196
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
197 if (!fd->ino) {
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
198 /* It's a deletion dirent. Ignore it */
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
199 D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name));
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
200 jffs2_free_full_dirent(fd);
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
201 continue;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
202 }
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
203 if (!whinged) {
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
204 whinged = 1;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
205 printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino);
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
206 }
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
207
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
208 D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n",
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
209 fd->name, fd->ino));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
210
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
211 child_ic = jffs2_get_ino_cache(c, fd->ino);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
212 if (!child_ic) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
213 printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
214 jffs2_free_full_dirent(fd);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
215 continue;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
216 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
217 jffs2_free_full_dirent(fd);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
218 child_ic->nlink--;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
219 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
220 ret = -EAGAIN;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
221 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
222
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
223 /*
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
224 We don't delete the inocache from the hash list and free it yet.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
225 The erase code will do that, when all the nodes are completely gone.
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
226 */
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
227
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
228 return ret;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
229 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
230
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
231 int jffs2_do_mount_fs(struct jffs2_sb_info *c)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
232 {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
233 int i;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
234
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
235 c->free_size = c->flash_size;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
236 c->nr_blocks = c->flash_size / c->sector_size;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
237 c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
238 if (!c->blocks)
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
239 return -ENOMEM;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
240 for (i=0; i<c->nr_blocks; i++) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
241 INIT_LIST_HEAD(&c->blocks[i].list);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
242 c->blocks[i].offset = i * c->sector_size;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
243 c->blocks[i].free_size = c->sector_size;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
244 c->blocks[i].dirty_size = 0;
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
245 c->blocks[i].wasted_size = 0;
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
246 c->blocks[i].unchecked_size = 0;
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
247 c->blocks[i].used_size = 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
248 c->blocks[i].first_node = NULL;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
249 c->blocks[i].last_node = NULL;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
250 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
251
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
252 init_MUTEX(&c->alloc_sem);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
253 init_MUTEX(&c->erase_free_sem);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
254 init_waitqueue_head(&c->erase_wait);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
255 init_waitqueue_head(&c->inocache_wq);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
256 spin_lock_init(&c->erase_completion_lock);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
257 spin_lock_init(&c->inocache_lock);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
258
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
259 INIT_LIST_HEAD(&c->clean_list);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
260 INIT_LIST_HEAD(&c->very_dirty_list);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
261 INIT_LIST_HEAD(&c->dirty_list);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
262 INIT_LIST_HEAD(&c->erasable_list);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
263 INIT_LIST_HEAD(&c->erasing_list);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
264 INIT_LIST_HEAD(&c->erase_pending_list);
570
a7947d436e85 Update to latest public JFFS2 sources
gthomas
parents: 208
diff changeset
265 INIT_LIST_HEAD(&c->erasable_pending_wbuf_list);
208
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
266 INIT_LIST_HEAD(&c->erase_complete_list);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
267 INIT_LIST_HEAD(&c->free_list);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
268 INIT_LIST_HEAD(&c->bad_list);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
269 INIT_LIST_HEAD(&c->bad_used_list);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
270 c->highest_ino = 1;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
271
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
272 if (jffs2_build_filesystem(c)) {
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
273 D1(printk(KERN_DEBUG "build_fs failed\n"));
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
274 jffs2_free_ino_caches(c);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
275 jffs2_free_raw_node_refs(c);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
276 kfree(c->blocks);
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
277 return -EIO;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
278 }
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
279 return 0;
e0c0827131d1 Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff changeset
280 }