xref: /OK3568_Linux_fs/kernel/fs/jffs2/build.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * JFFS2 -- Journalling Flash File System, Version 2.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright © 2001-2007 Red Hat, Inc.
5*4882a593Smuzhiyun  * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Created by David Woodhouse <dwmw2@infradead.org>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * For licensing information, see the file 'LICENCE' in this directory.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/kernel.h>
16*4882a593Smuzhiyun #include <linux/sched.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun #include <linux/vmalloc.h>
19*4882a593Smuzhiyun #include <linux/mtd/mtd.h>
20*4882a593Smuzhiyun #include <linux/mm.h> /* kvfree() */
21*4882a593Smuzhiyun #include "nodelist.h"
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *,
24*4882a593Smuzhiyun 		struct jffs2_inode_cache *, struct jffs2_full_dirent **);
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun static inline struct jffs2_inode_cache *
first_inode_chain(int * i,struct jffs2_sb_info * c)27*4882a593Smuzhiyun first_inode_chain(int *i, struct jffs2_sb_info *c)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	for (; *i < c->inocache_hashsize; (*i)++) {
30*4882a593Smuzhiyun 		if (c->inocache_list[*i])
31*4882a593Smuzhiyun 			return c->inocache_list[*i];
32*4882a593Smuzhiyun 	}
33*4882a593Smuzhiyun 	return NULL;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static inline struct jffs2_inode_cache *
next_inode(int * i,struct jffs2_inode_cache * ic,struct jffs2_sb_info * c)37*4882a593Smuzhiyun next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	/* More in this chain? */
40*4882a593Smuzhiyun 	if (ic->next)
41*4882a593Smuzhiyun 		return ic->next;
42*4882a593Smuzhiyun 	(*i)++;
43*4882a593Smuzhiyun 	return first_inode_chain(i, c);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define for_each_inode(i, c, ic)			\
47*4882a593Smuzhiyun 	for (i = 0, ic = first_inode_chain(&i, (c));	\
48*4882a593Smuzhiyun 	     ic;					\
49*4882a593Smuzhiyun 	     ic = next_inode(&i, ic, (c)))
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 
jffs2_build_inode_pass1(struct jffs2_sb_info * c,struct jffs2_inode_cache * ic,int * dir_hardlinks)52*4882a593Smuzhiyun static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
53*4882a593Smuzhiyun 				    struct jffs2_inode_cache *ic,
54*4882a593Smuzhiyun 				    int *dir_hardlinks)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	struct jffs2_full_dirent *fd;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	dbg_fsbuild("building directory inode #%u\n", ic->ino);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	/* For each child, increase nlink */
61*4882a593Smuzhiyun 	for(fd = ic->scan_dents; fd; fd = fd->next) {
62*4882a593Smuzhiyun 		struct jffs2_inode_cache *child_ic;
63*4882a593Smuzhiyun 		if (!fd->ino)
64*4882a593Smuzhiyun 			continue;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 		/* we can get high latency here with huge directories */
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 		child_ic = jffs2_get_ino_cache(c, fd->ino);
69*4882a593Smuzhiyun 		if (!child_ic) {
70*4882a593Smuzhiyun 			dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
71*4882a593Smuzhiyun 				  fd->name, fd->ino, ic->ino);
72*4882a593Smuzhiyun 			jffs2_mark_node_obsolete(c, fd->raw);
73*4882a593Smuzhiyun 			/* Clear the ic/raw union so it doesn't cause problems later. */
74*4882a593Smuzhiyun 			fd->ic = NULL;
75*4882a593Smuzhiyun 			continue;
76*4882a593Smuzhiyun 		}
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 		/* From this point, fd->raw is no longer used so we can set fd->ic */
79*4882a593Smuzhiyun 		fd->ic = child_ic;
80*4882a593Smuzhiyun 		child_ic->pino_nlink++;
81*4882a593Smuzhiyun 		/* If we appear (at this stage) to have hard-linked directories,
82*4882a593Smuzhiyun 		 * set a flag to trigger a scan later */
83*4882a593Smuzhiyun 		if (fd->type == DT_DIR) {
84*4882a593Smuzhiyun 			child_ic->flags |= INO_FLAGS_IS_DIR;
85*4882a593Smuzhiyun 			if (child_ic->pino_nlink > 1)
86*4882a593Smuzhiyun 				*dir_hardlinks = 1;
87*4882a593Smuzhiyun 		}
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 		dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
90*4882a593Smuzhiyun 		/* Can't free scan_dents so far. We might need them in pass 2 */
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /* Scan plan:
95*4882a593Smuzhiyun  - Scan physical nodes. Build map of inodes/dirents. Allocate inocaches as we go
96*4882a593Smuzhiyun  - Scan directory tree from top down, setting nlink in inocaches
97*4882a593Smuzhiyun  - Scan inocaches for inodes with nlink==0
98*4882a593Smuzhiyun */
jffs2_build_filesystem(struct jffs2_sb_info * c)99*4882a593Smuzhiyun static int jffs2_build_filesystem(struct jffs2_sb_info *c)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	int ret, i, dir_hardlinks = 0;
102*4882a593Smuzhiyun 	struct jffs2_inode_cache *ic;
103*4882a593Smuzhiyun 	struct jffs2_full_dirent *fd;
104*4882a593Smuzhiyun 	struct jffs2_full_dirent *dead_fds = NULL;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	dbg_fsbuild("build FS data structures\n");
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	/* First, scan the medium and build all the inode caches with
109*4882a593Smuzhiyun 	   lists of physical nodes */
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	c->flags |= JFFS2_SB_FLAG_SCANNING;
112*4882a593Smuzhiyun 	ret = jffs2_scan_medium(c);
113*4882a593Smuzhiyun 	c->flags &= ~JFFS2_SB_FLAG_SCANNING;
114*4882a593Smuzhiyun 	if (ret)
115*4882a593Smuzhiyun 		goto exit;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	dbg_fsbuild("scanned flash completely\n");
118*4882a593Smuzhiyun 	jffs2_dbg_dump_block_lists_nolock(c);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	dbg_fsbuild("pass 1 starting\n");
121*4882a593Smuzhiyun 	c->flags |= JFFS2_SB_FLAG_BUILDING;
122*4882a593Smuzhiyun 	/* Now scan the directory tree, increasing nlink according to every dirent found. */
123*4882a593Smuzhiyun 	for_each_inode(i, c, ic) {
124*4882a593Smuzhiyun 		if (ic->scan_dents) {
125*4882a593Smuzhiyun 			jffs2_build_inode_pass1(c, ic, &dir_hardlinks);
126*4882a593Smuzhiyun 			cond_resched();
127*4882a593Smuzhiyun 		}
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	dbg_fsbuild("pass 1 complete\n");
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	/* Next, scan for inodes with nlink == 0 and remove them. If
133*4882a593Smuzhiyun 	   they were directories, then decrement the nlink of their
134*4882a593Smuzhiyun 	   children too, and repeat the scan. As that's going to be
135*4882a593Smuzhiyun 	   a fairly uncommon occurrence, it's not so evil to do it this
136*4882a593Smuzhiyun 	   way. Recursion bad. */
137*4882a593Smuzhiyun 	dbg_fsbuild("pass 2 starting\n");
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	for_each_inode(i, c, ic) {
140*4882a593Smuzhiyun 		if (ic->pino_nlink)
141*4882a593Smuzhiyun 			continue;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 		jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
144*4882a593Smuzhiyun 		cond_resched();
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	dbg_fsbuild("pass 2a starting\n");
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	while (dead_fds) {
150*4882a593Smuzhiyun 		fd = dead_fds;
151*4882a593Smuzhiyun 		dead_fds = fd->next;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		ic = jffs2_get_ino_cache(c, fd->ino);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 		if (ic)
156*4882a593Smuzhiyun 			jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
157*4882a593Smuzhiyun 		jffs2_free_full_dirent(fd);
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	dbg_fsbuild("pass 2a complete\n");
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	if (dir_hardlinks) {
163*4882a593Smuzhiyun 		/* If we detected directory hardlinks earlier, *hopefully*
164*4882a593Smuzhiyun 		 * they are gone now because some of the links were from
165*4882a593Smuzhiyun 		 * dead directories which still had some old dirents lying
166*4882a593Smuzhiyun 		 * around and not yet garbage-collected, but which have
167*4882a593Smuzhiyun 		 * been discarded above. So clear the pino_nlink field
168*4882a593Smuzhiyun 		 * in each directory, so that the final scan below can
169*4882a593Smuzhiyun 		 * print appropriate warnings. */
170*4882a593Smuzhiyun 		for_each_inode(i, c, ic) {
171*4882a593Smuzhiyun 			if (ic->flags & INO_FLAGS_IS_DIR)
172*4882a593Smuzhiyun 				ic->pino_nlink = 0;
173*4882a593Smuzhiyun 		}
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 	dbg_fsbuild("freeing temporary data structures\n");
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	/* Finally, we can scan again and free the dirent structs */
178*4882a593Smuzhiyun 	for_each_inode(i, c, ic) {
179*4882a593Smuzhiyun 		while(ic->scan_dents) {
180*4882a593Smuzhiyun 			fd = ic->scan_dents;
181*4882a593Smuzhiyun 			ic->scan_dents = fd->next;
182*4882a593Smuzhiyun 			/* We do use the pino_nlink field to count nlink of
183*4882a593Smuzhiyun 			 * directories during fs build, so set it to the
184*4882a593Smuzhiyun 			 * parent ino# now. Now that there's hopefully only
185*4882a593Smuzhiyun 			 * one. */
186*4882a593Smuzhiyun 			if (fd->type == DT_DIR) {
187*4882a593Smuzhiyun 				if (!fd->ic) {
188*4882a593Smuzhiyun 					/* We'll have complained about it and marked the coresponding
189*4882a593Smuzhiyun 					   raw node obsolete already. Just skip it. */
190*4882a593Smuzhiyun 					continue;
191*4882a593Smuzhiyun 				}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 				/* We *have* to have set this in jffs2_build_inode_pass1() */
194*4882a593Smuzhiyun 				BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR));
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 				/* We clear ic->pino_nlink ∀ directories' ic *only* if dir_hardlinks
197*4882a593Smuzhiyun 				 * is set. Otherwise, we know this should never trigger anyway, so
198*4882a593Smuzhiyun 				 * we don't do the check. And ic->pino_nlink still contains the nlink
199*4882a593Smuzhiyun 				 * value (which is 1). */
200*4882a593Smuzhiyun 				if (dir_hardlinks && fd->ic->pino_nlink) {
201*4882a593Smuzhiyun 					JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n",
202*4882a593Smuzhiyun 						    fd->name, fd->ino, ic->ino, fd->ic->pino_nlink);
203*4882a593Smuzhiyun 					/* Should we unlink it from its previous parent? */
204*4882a593Smuzhiyun 				}
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 				/* For directories, ic->pino_nlink holds that parent inode # */
207*4882a593Smuzhiyun 				fd->ic->pino_nlink = ic->ino;
208*4882a593Smuzhiyun 			}
209*4882a593Smuzhiyun 			jffs2_free_full_dirent(fd);
210*4882a593Smuzhiyun 		}
211*4882a593Smuzhiyun 		ic->scan_dents = NULL;
212*4882a593Smuzhiyun 		cond_resched();
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun 	jffs2_build_xattr_subsystem(c);
215*4882a593Smuzhiyun 	c->flags &= ~JFFS2_SB_FLAG_BUILDING;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	dbg_fsbuild("FS build complete\n");
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	/* Rotate the lists by some number to ensure wear levelling */
220*4882a593Smuzhiyun 	jffs2_rotate_lists(c);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	ret = 0;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun exit:
225*4882a593Smuzhiyun 	if (ret) {
226*4882a593Smuzhiyun 		for_each_inode(i, c, ic) {
227*4882a593Smuzhiyun 			while(ic->scan_dents) {
228*4882a593Smuzhiyun 				fd = ic->scan_dents;
229*4882a593Smuzhiyun 				ic->scan_dents = fd->next;
230*4882a593Smuzhiyun 				jffs2_free_full_dirent(fd);
231*4882a593Smuzhiyun 			}
232*4882a593Smuzhiyun 		}
233*4882a593Smuzhiyun 		jffs2_clear_xattr_subsystem(c);
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	return ret;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
jffs2_build_remove_unlinked_inode(struct jffs2_sb_info * c,struct jffs2_inode_cache * ic,struct jffs2_full_dirent ** dead_fds)239*4882a593Smuzhiyun static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c,
240*4882a593Smuzhiyun 					struct jffs2_inode_cache *ic,
241*4882a593Smuzhiyun 					struct jffs2_full_dirent **dead_fds)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	struct jffs2_raw_node_ref *raw;
244*4882a593Smuzhiyun 	struct jffs2_full_dirent *fd;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	dbg_fsbuild("removing ino #%u with nlink == zero.\n", ic->ino);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	raw = ic->nodes;
249*4882a593Smuzhiyun 	while (raw != (void *)ic) {
250*4882a593Smuzhiyun 		struct jffs2_raw_node_ref *next = raw->next_in_ino;
251*4882a593Smuzhiyun 		dbg_fsbuild("obsoleting node at 0x%08x\n", ref_offset(raw));
252*4882a593Smuzhiyun 		jffs2_mark_node_obsolete(c, raw);
253*4882a593Smuzhiyun 		raw = next;
254*4882a593Smuzhiyun 	}
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (ic->scan_dents) {
257*4882a593Smuzhiyun 		int whinged = 0;
258*4882a593Smuzhiyun 		dbg_fsbuild("inode #%u was a directory which may have children...\n", ic->ino);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 		while(ic->scan_dents) {
261*4882a593Smuzhiyun 			struct jffs2_inode_cache *child_ic;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 			fd = ic->scan_dents;
264*4882a593Smuzhiyun 			ic->scan_dents = fd->next;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 			if (!fd->ino) {
267*4882a593Smuzhiyun 				/* It's a deletion dirent. Ignore it */
268*4882a593Smuzhiyun 				dbg_fsbuild("child \"%s\" is a deletion dirent, skipping...\n", fd->name);
269*4882a593Smuzhiyun 				jffs2_free_full_dirent(fd);
270*4882a593Smuzhiyun 				continue;
271*4882a593Smuzhiyun 			}
272*4882a593Smuzhiyun 			if (!whinged)
273*4882a593Smuzhiyun 				whinged = 1;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 			dbg_fsbuild("removing child \"%s\", ino #%u\n", fd->name, fd->ino);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 			child_ic = jffs2_get_ino_cache(c, fd->ino);
278*4882a593Smuzhiyun 			if (!child_ic) {
279*4882a593Smuzhiyun 				dbg_fsbuild("cannot remove child \"%s\", ino #%u, because it doesn't exist\n",
280*4882a593Smuzhiyun 						fd->name, fd->ino);
281*4882a593Smuzhiyun 				jffs2_free_full_dirent(fd);
282*4882a593Smuzhiyun 				continue;
283*4882a593Smuzhiyun 			}
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 			/* Reduce nlink of the child. If it's now zero, stick it on the
286*4882a593Smuzhiyun 			   dead_fds list to be cleaned up later. Else just free the fd */
287*4882a593Smuzhiyun 			child_ic->pino_nlink--;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 			if (!child_ic->pino_nlink) {
290*4882a593Smuzhiyun 				dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
291*4882a593Smuzhiyun 					  fd->ino, fd->name);
292*4882a593Smuzhiyun 				fd->next = *dead_fds;
293*4882a593Smuzhiyun 				*dead_fds = fd;
294*4882a593Smuzhiyun 			} else {
295*4882a593Smuzhiyun 				dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
296*4882a593Smuzhiyun 					  fd->ino, fd->name, child_ic->pino_nlink);
297*4882a593Smuzhiyun 				jffs2_free_full_dirent(fd);
298*4882a593Smuzhiyun 			}
299*4882a593Smuzhiyun 		}
300*4882a593Smuzhiyun 	}
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	/*
303*4882a593Smuzhiyun 	   We don't delete the inocache from the hash list and free it yet.
304*4882a593Smuzhiyun 	   The erase code will do that, when all the nodes are completely gone.
305*4882a593Smuzhiyun 	*/
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
jffs2_calc_trigger_levels(struct jffs2_sb_info * c)308*4882a593Smuzhiyun static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	uint32_t size;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	/* Deletion should almost _always_ be allowed. We're fairly
313*4882a593Smuzhiyun 	   buggered once we stop allowing people to delete stuff
314*4882a593Smuzhiyun 	   because there's not enough free space... */
315*4882a593Smuzhiyun 	c->resv_blocks_deletion = 2;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	/* Be conservative about how much space we need before we allow writes.
318*4882a593Smuzhiyun 	   On top of that which is required for deletia, require an extra 2%
319*4882a593Smuzhiyun 	   of the medium to be available, for overhead caused by nodes being
320*4882a593Smuzhiyun 	   split across blocks, etc. */
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	size = c->flash_size / 50; /* 2% of flash size */
323*4882a593Smuzhiyun 	size += c->nr_blocks * 100; /* And 100 bytes per eraseblock */
324*4882a593Smuzhiyun 	size += c->sector_size - 1; /* ... and round up */
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	c->resv_blocks_write = c->resv_blocks_deletion + (size / c->sector_size);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	/* When do we let the GC thread run in the background */
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	c->resv_blocks_gctrigger = c->resv_blocks_write + 1;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	/* When do we allow garbage collection to merge nodes to make
333*4882a593Smuzhiyun 	   long-term progress at the expense of short-term space exhaustion? */
334*4882a593Smuzhiyun 	c->resv_blocks_gcmerge = c->resv_blocks_deletion + 1;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	/* When do we allow garbage collection to eat from bad blocks rather
337*4882a593Smuzhiyun 	   than actually making progress? */
338*4882a593Smuzhiyun 	c->resv_blocks_gcbad = 0;//c->resv_blocks_deletion + 2;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/* What number of 'very dirty' eraseblocks do we allow before we
341*4882a593Smuzhiyun 	   trigger the GC thread even if we don't _need_ the space. When we
342*4882a593Smuzhiyun 	   can't mark nodes obsolete on the medium, the old dirty nodes cause
343*4882a593Smuzhiyun 	   performance problems because we have to inspect and discard them. */
344*4882a593Smuzhiyun 	c->vdirty_blocks_gctrigger = c->resv_blocks_gctrigger;
345*4882a593Smuzhiyun 	if (jffs2_can_mark_obsolete(c))
346*4882a593Smuzhiyun 		c->vdirty_blocks_gctrigger *= 10;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	/* If there's less than this amount of dirty space, don't bother
349*4882a593Smuzhiyun 	   trying to GC to make more space. It'll be a fruitless task */
350*4882a593Smuzhiyun 	c->nospc_dirty_size = c->sector_size + (c->flash_size / 100);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	dbg_fsbuild("trigger levels (size %d KiB, block size %d KiB, %d blocks)\n",
353*4882a593Smuzhiyun 		    c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks);
354*4882a593Smuzhiyun 	dbg_fsbuild("Blocks required to allow deletion:    %d (%d KiB)\n",
355*4882a593Smuzhiyun 		  c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024);
356*4882a593Smuzhiyun 	dbg_fsbuild("Blocks required to allow writes:      %d (%d KiB)\n",
357*4882a593Smuzhiyun 		  c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024);
358*4882a593Smuzhiyun 	dbg_fsbuild("Blocks required to quiesce GC thread: %d (%d KiB)\n",
359*4882a593Smuzhiyun 		  c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024);
360*4882a593Smuzhiyun 	dbg_fsbuild("Blocks required to allow GC merges:   %d (%d KiB)\n",
361*4882a593Smuzhiyun 		  c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024);
362*4882a593Smuzhiyun 	dbg_fsbuild("Blocks required to GC bad blocks:     %d (%d KiB)\n",
363*4882a593Smuzhiyun 		  c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024);
364*4882a593Smuzhiyun 	dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n",
365*4882a593Smuzhiyun 		  c->nospc_dirty_size);
366*4882a593Smuzhiyun 	dbg_fsbuild("Very dirty blocks before GC triggered: %d\n",
367*4882a593Smuzhiyun 		  c->vdirty_blocks_gctrigger);
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
jffs2_do_mount_fs(struct jffs2_sb_info * c)370*4882a593Smuzhiyun int jffs2_do_mount_fs(struct jffs2_sb_info *c)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	int ret;
373*4882a593Smuzhiyun 	int i;
374*4882a593Smuzhiyun 	int size;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	c->free_size = c->flash_size;
377*4882a593Smuzhiyun 	c->nr_blocks = c->flash_size / c->sector_size;
378*4882a593Smuzhiyun 	size = sizeof(struct jffs2_eraseblock) * c->nr_blocks;
379*4882a593Smuzhiyun #ifndef __ECOS
380*4882a593Smuzhiyun 	if (jffs2_blocks_use_vmalloc(c))
381*4882a593Smuzhiyun 		c->blocks = vzalloc(size);
382*4882a593Smuzhiyun 	else
383*4882a593Smuzhiyun #endif
384*4882a593Smuzhiyun 		c->blocks = kzalloc(size, GFP_KERNEL);
385*4882a593Smuzhiyun 	if (!c->blocks)
386*4882a593Smuzhiyun 		return -ENOMEM;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	for (i=0; i<c->nr_blocks; i++) {
389*4882a593Smuzhiyun 		INIT_LIST_HEAD(&c->blocks[i].list);
390*4882a593Smuzhiyun 		c->blocks[i].offset = i * c->sector_size;
391*4882a593Smuzhiyun 		c->blocks[i].free_size = c->sector_size;
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->clean_list);
395*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->very_dirty_list);
396*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->dirty_list);
397*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->erasable_list);
398*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->erasing_list);
399*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->erase_checking_list);
400*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->erase_pending_list);
401*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->erasable_pending_wbuf_list);
402*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->erase_complete_list);
403*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->free_list);
404*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->bad_list);
405*4882a593Smuzhiyun 	INIT_LIST_HEAD(&c->bad_used_list);
406*4882a593Smuzhiyun 	c->highest_ino = 1;
407*4882a593Smuzhiyun 	c->summary = NULL;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	ret = jffs2_sum_init(c);
410*4882a593Smuzhiyun 	if (ret)
411*4882a593Smuzhiyun 		goto out_free;
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	if (jffs2_build_filesystem(c)) {
414*4882a593Smuzhiyun 		dbg_fsbuild("build_fs failed\n");
415*4882a593Smuzhiyun 		jffs2_free_ino_caches(c);
416*4882a593Smuzhiyun 		jffs2_free_raw_node_refs(c);
417*4882a593Smuzhiyun 		ret = -EIO;
418*4882a593Smuzhiyun 		goto out_sum_exit;
419*4882a593Smuzhiyun 	}
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	jffs2_calc_trigger_levels(c);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return 0;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun  out_sum_exit:
426*4882a593Smuzhiyun 	jffs2_sum_exit(c);
427*4882a593Smuzhiyun  out_free:
428*4882a593Smuzhiyun 	kvfree(c->blocks);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	return ret;
431*4882a593Smuzhiyun }
432