• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2011 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  * Acknowledgements:
9  * Luc van OostenRyck for numerous patches.
10  * Nick Bane for numerous patches.
11  * Nick Bane for 2.5/2.6 integration.
12  * Andras Toth for mknod rdev issue.
13  * Michael Fischer for finding the problem with inode inconsistency.
14  * Some code bodily lifted from JFFS
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License version 2 as
18  * published by the Free Software Foundation.
19  */
20 
21 /*
22  *
23  * This is the file system front-end to YAFFS that hooks it up to
24  * the VFS.
25  *
26  * Special notes:
27  * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with
28  *         this superblock
29  * >> 2.6: sb->s_fs_info  points to the struct yaffs_dev associated with this
30  *         superblock
31  * >> inode->u.generic_ip points to the associated struct yaffs_obj.
32  */
33 
34 /*
35  * There are two variants of the VFS glue code. This variant should compile
36  * for any version of Linux.
37  */
38 #include <linux/version.h>
39 
40 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
41 #define YAFFS_COMPILE_BACKGROUND
42 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23))
43 #define YAFFS_COMPILE_FREEZER
44 #endif
45 #endif
46 
47 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
48 #define YAFFS_COMPILE_EXPORTFS
49 #endif
50 
51 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
52 #define YAFFS_USE_SETATTR_COPY
53 #define YAFFS_USE_TRUNCATE_SETSIZE
54 #endif
55 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
56 #define YAFFS_HAS_EVICT_INODE
57 #endif
58 
59 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
60 #define YAFFS_NEW_FOLLOW_LINK 1
61 #else
62 #define YAFFS_NEW_FOLLOW_LINK 0
63 #endif
64 
65 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
66 #define YAFFS_HAS_WRITE_SUPER
67 #endif
68 
69 
70 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
71 #include <linux/config.h>
72 #endif
73 
74 #include <linux/kernel.h>
75 #include <linux/module.h>
76 #include <linux/slab.h>
77 #include <linux/init.h>
78 #include <linux/fs.h>
79 #include <linux/proc_fs.h>
80 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
81 #include <linux/smp_lock.h>
82 #endif
83 #include <linux/pagemap.h>
84 #include <linux/mtd/mtd.h>
85 #include <linux/interrupt.h>
86 #include <linux/string.h>
87 #include <linux/ctype.h>
88 
89 #if (YAFFS_NEW_FOLLOW_LINK == 1)
90 #include <linux/namei.h>
91 #endif
92 
93 #ifdef YAFFS_COMPILE_EXPORTFS
94 #include <linux/exportfs.h>
95 #endif
96 
97 #ifdef YAFFS_COMPILE_BACKGROUND
98 #include <linux/kthread.h>
99 #include <linux/delay.h>
100 #endif
101 #ifdef YAFFS_COMPILE_FREEZER
102 #include <linux/freezer.h>
103 #endif
104 
105 #include <asm/div64.h>
106 
107 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
108 
109 #include <linux/statfs.h>
110 
111 #define UnlockPage(p) unlock_page(p)
112 #define Page_Uptodate(page)	test_bit(PG_uptodate, &(page)->flags)
113 
114 /* FIXME: use sb->s_id instead ? */
115 #define yaffs_devname(sb, buf)	bdevname(sb->s_bdev, buf)
116 
117 #else
118 
119 #include <linux/locks.h>
120 #define	BDEVNAME_SIZE		0
121 #define	yaffs_devname(sb, buf)	kdevname(sb->s_dev)
122 
123 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
124 /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
125 #define __user
126 #endif
127 
128 #endif
129 
130 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
131 #define YPROC_ROOT  (&proc_root)
132 #else
133 #define YPROC_ROOT  NULL
134 #endif
135 
136 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
137 #define Y_INIT_TIMER(a)	init_timer(a)
138 #else
139 #define Y_INIT_TIMER(a)	init_timer_on_stack(a)
140 #endif
141 
142 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
143 #define YAFFS_USE_WRITE_BEGIN_END 1
144 #else
145 #define YAFFS_USE_WRITE_BEGIN_END 0
146 #endif
147 
148 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
149 #define YAFFS_SUPER_HAS_DIRTY
150 #endif
151 
152 
153 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
154 #define set_nlink(inode, count)  do { (inode)->i_nlink = (count); } while(0)
155 #endif
156 
157 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
YCALCBLOCKS(uint64_t partition_size,uint32_t block_size)158 static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
159 {
160 	uint64_t result = partition_size;
161 	do_div(result, block_size);
162 	return (uint32_t) result;
163 }
164 #else
165 #define YCALCBLOCKS(s, b) ((s)/(b))
166 #endif
167 
168 #include <linux/uaccess.h>
169 #include <linux/mtd/mtd.h>
170 
171 #include "yportenv.h"
172 #include "yaffs_trace.h"
173 #include "yaffs_guts.h"
174 #include "yaffs_attribs.h"
175 
176 #include "yaffs_linux.h"
177 
178 #include "yaffs_mtdif.h"
179 
180 unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS;
181 unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
182 unsigned int yaffs_auto_checkpoint = 1;
183 unsigned int yaffs_gc_control = 1;
184 unsigned int yaffs_bg_enable = 1;
185 unsigned int yaffs_auto_select = 1;
186 /* Module Parameters */
187 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
188 module_param(yaffs_trace_mask, uint, 0644);
189 module_param(yaffs_wr_attempts, uint, 0644);
190 module_param(yaffs_auto_checkpoint, uint, 0644);
191 module_param(yaffs_gc_control, uint, 0644);
192 module_param(yaffs_bg_enable, uint, 0644);
193 #else
194 MODULE_PARM(yaffs_trace_mask, "i");
195 MODULE_PARM(yaffs_wr_attempts, "i");
196 MODULE_PARM(yaffs_auto_checkpoint, "i");
197 MODULE_PARM(yaffs_gc_control, "i");
198 #endif
199 
200 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
201 /* use iget and read_inode */
202 #define Y_IGET(sb, inum) iget((sb), (inum))
203 
204 #else
205 /* Call local equivalent */
206 #define YAFFS_USE_OWN_IGET
207 #define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
208 
209 #endif
210 
211 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
212 #define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private)
213 #else
214 #define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
215 #endif
216 
217 #define yaffs_inode_to_obj(iptr) \
218 	((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
219 #define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode)
220 
221 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
222 #define yaffs_super_to_dev(sb)	((struct yaffs_dev *)sb->s_fs_info)
223 #else
224 #define yaffs_super_to_dev(sb)	((struct yaffs_dev *)sb->u.generic_sbp)
225 #endif
226 
227 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
228 #define Y_CLEAR_INODE(i) clear_inode(i)
229 #else
230 #define Y_CLEAR_INODE(i) end_writeback(i)
231 #endif
232 
233 
234 #define update_dir_time(dir) do {\
235 			(dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
236 		} while (0)
237 
238 static void yaffs_fill_inode_from_obj(struct inode *inode,
239 				      struct yaffs_obj *obj);
240 
241 
yaffs_gross_lock(struct yaffs_dev * dev)242 static void yaffs_gross_lock(struct yaffs_dev *dev)
243 {
244 	yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locking %p", current);
245 	mutex_lock(&(yaffs_dev_to_lc(dev)->gross_lock));
246 	yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locked %p", current);
247 }
248 
yaffs_gross_unlock(struct yaffs_dev * dev)249 static void yaffs_gross_unlock(struct yaffs_dev *dev)
250 {
251 	yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current);
252 	mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock));
253 }
254 
255 
yaffs_readpage_nolock(struct file * f,struct page * pg)256 static int yaffs_readpage_nolock(struct file *f, struct page *pg)
257 {
258 	/* Lifted from jffs2 */
259 
260 	struct yaffs_obj *obj;
261 	unsigned char *pg_buf;
262 	int ret;
263 	loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
264 	struct yaffs_dev *dev;
265 
266 	yaffs_trace(YAFFS_TRACE_OS,
267 		"yaffs_readpage_nolock at %lld, size %08x",
268 		(long long)pos,
269 		(unsigned)PAGE_CACHE_SIZE);
270 
271 	obj = yaffs_dentry_to_obj(f->f_dentry);
272 
273 	dev = obj->my_dev;
274 
275 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
276 	BUG_ON(!PageLocked(pg));
277 #else
278 	if (!PageLocked(pg))
279 		PAGE_BUG(pg);
280 #endif
281 
282 	pg_buf = kmap(pg);
283 	/* FIXME: Can kmap fail? */
284 
285 	yaffs_gross_lock(dev);
286 
287 	ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE);
288 
289 	yaffs_gross_unlock(dev);
290 
291 	if (ret >= 0)
292 		ret = 0;
293 
294 	if (ret) {
295 		ClearPageUptodate(pg);
296 		SetPageError(pg);
297 	} else {
298 		SetPageUptodate(pg);
299 		ClearPageError(pg);
300 	}
301 
302 	flush_dcache_page(pg);
303 	kunmap(pg);
304 
305 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done");
306 	return ret;
307 }
308 
yaffs_readpage_unlock(struct file * f,struct page * pg)309 static int yaffs_readpage_unlock(struct file *f, struct page *pg)
310 {
311 	int ret = yaffs_readpage_nolock(f, pg);
312 	UnlockPage(pg);
313 	return ret;
314 }
315 
yaffs_readpage(struct file * f,struct page * pg)316 static int yaffs_readpage(struct file *f, struct page *pg)
317 {
318 	int ret;
319 
320 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage");
321 	ret = yaffs_readpage_unlock(f, pg);
322 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done");
323 	return ret;
324 }
325 
326 
yaffs_set_super_dirty_val(struct yaffs_dev * dev,int val)327 static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
328 {
329 	struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
330 
331 	if (lc)
332 		lc->dirty = val;
333 
334 # ifdef YAFFS_SUPER_HAS_DIRTY
335 	{
336 		struct super_block *sb = lc->super;
337 
338 		if (sb)
339 			sb->s_dirt = val;
340 	}
341 #endif
342 
343 }
344 
yaffs_set_super_dirty(struct yaffs_dev * dev)345 static void yaffs_set_super_dirty(struct yaffs_dev *dev)
346 {
347 	yaffs_set_super_dirty_val(dev, 1);
348 }
349 
yaffs_clear_super_dirty(struct yaffs_dev * dev)350 static void yaffs_clear_super_dirty(struct yaffs_dev *dev)
351 {
352 	yaffs_set_super_dirty_val(dev, 0);
353 }
354 
yaffs_check_super_dirty(struct yaffs_dev * dev)355 static int yaffs_check_super_dirty(struct yaffs_dev *dev)
356 {
357 	struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
358 
359 	if (lc && lc->dirty)
360 		return 1;
361 
362 # ifdef YAFFS_SUPER_HAS_DIRTY
363 	{
364 		struct super_block *sb = lc->super;
365 
366 		if (sb && sb->s_dirt)
367 			return 1;
368 	}
369 #endif
370 	return 0;
371 
372 }
373 
374 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
yaffs_writepage(struct page * page,struct writeback_control * wbc)375 static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
376 #else
377 static int yaffs_writepage(struct page *page)
378 #endif
379 {
380 	struct yaffs_dev *dev;
381 	struct address_space *mapping = page->mapping;
382 	struct inode *inode;
383 	unsigned long end_index;
384 	char *buffer;
385 	struct yaffs_obj *obj;
386 	int n_written = 0;
387 	unsigned n_bytes;
388 	loff_t i_size;
389 
390 	if (!mapping)
391 		BUG();
392 	inode = mapping->host;
393 	if (!inode)
394 		BUG();
395 	i_size = i_size_read(inode);
396 
397 	end_index = i_size >> PAGE_CACHE_SHIFT;
398 
399 	if (page->index < end_index)
400 		n_bytes = PAGE_CACHE_SIZE;
401 	else {
402 		n_bytes = i_size & (PAGE_CACHE_SIZE - 1);
403 
404 		if (page->index > end_index || !n_bytes) {
405 			yaffs_trace(YAFFS_TRACE_OS,
406 				"yaffs_writepage at %lld, inode size = %lld!!",
407 				((loff_t)page->index) << PAGE_CACHE_SHIFT,
408 				inode->i_size);
409 			yaffs_trace(YAFFS_TRACE_OS,
410 				"                -> don't care!!");
411 
412 			zero_user_segment(page, 0, PAGE_CACHE_SIZE);
413 			set_page_writeback(page);
414 			unlock_page(page);
415 			end_page_writeback(page);
416 			return 0;
417 		}
418 	}
419 
420 	if (n_bytes != PAGE_CACHE_SIZE)
421 		zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE);
422 
423 	get_page(page);
424 
425 	buffer = kmap(page);
426 
427 	obj = yaffs_inode_to_obj(inode);
428 	dev = obj->my_dev;
429 	yaffs_gross_lock(dev);
430 
431 	yaffs_trace(YAFFS_TRACE_OS,
432 		"yaffs_writepage at %lld, size %08x",
433 		((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes);
434 	yaffs_trace(YAFFS_TRACE_OS,
435 		"writepag0: obj = %lld, ino = %lld",
436 		obj->variant.file_variant.file_size, inode->i_size);
437 
438 	n_written = yaffs_wr_file(obj, buffer,
439 				  ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0);
440 
441 	yaffs_set_super_dirty(dev);
442 
443 	yaffs_trace(YAFFS_TRACE_OS,
444 		"writepag1: obj = %lld, ino = %lld",
445 		obj->variant.file_variant.file_size, inode->i_size);
446 
447 	yaffs_gross_unlock(dev);
448 
449 	kunmap(page);
450 	set_page_writeback(page);
451 	unlock_page(page);
452 	end_page_writeback(page);
453 	put_page(page);
454 
455 	return (n_written == n_bytes) ? 0 : -ENOSPC;
456 }
457 
458 /* Space holding and freeing is done to ensure we have space available for write_begin/end */
459 /* For now we just assume few parallel writes and check against a small number. */
460 /* Todo: need to do this with a counter to handle parallel reads better */
461 
yaffs_hold_space(struct file * f)462 static ssize_t yaffs_hold_space(struct file *f)
463 {
464 	struct yaffs_obj *obj;
465 	struct yaffs_dev *dev;
466 
467 	int n_free_chunks;
468 
469 	obj = yaffs_dentry_to_obj(f->f_dentry);
470 
471 	dev = obj->my_dev;
472 
473 	yaffs_gross_lock(dev);
474 
475 	n_free_chunks = yaffs_get_n_free_chunks(dev);
476 
477 	yaffs_gross_unlock(dev);
478 
479 	return (n_free_chunks > 20) ? 1 : 0;
480 }
481 
yaffs_release_space(struct file * f)482 static void yaffs_release_space(struct file *f)
483 {
484 	struct yaffs_obj *obj;
485 	struct yaffs_dev *dev;
486 
487 	obj = yaffs_dentry_to_obj(f->f_dentry);
488 
489 	dev = obj->my_dev;
490 
491 	yaffs_gross_lock(dev);
492 
493 	yaffs_gross_unlock(dev);
494 }
495 
496 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
yaffs_write_begin(struct file * filp,struct address_space * mapping,loff_t pos,unsigned len,unsigned flags,struct page ** pagep,void ** fsdata)497 static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
498 			     loff_t pos, unsigned len, unsigned flags,
499 			     struct page **pagep, void **fsdata)
500 {
501 	struct page *pg = NULL;
502 	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
503 
504 	int ret = 0;
505 	int space_held = 0;
506 
507 	/* Get a page */
508 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
509 	pg = grab_cache_page_write_begin(mapping, index, flags);
510 #else
511 	pg = __grab_cache_page(mapping, index);
512 #endif
513 
514 	*pagep = pg;
515 	if (!pg) {
516 		ret = -ENOMEM;
517 		goto out;
518 	}
519 	yaffs_trace(YAFFS_TRACE_OS,
520 		"start yaffs_write_begin index %d(%x) uptodate %d",
521 		(int)index, (int)index, Page_Uptodate(pg) ? 1 : 0);
522 
523 	/* Get fs space */
524 	space_held = yaffs_hold_space(filp);
525 
526 	if (!space_held) {
527 		ret = -ENOSPC;
528 		goto out;
529 	}
530 
531 	/* Update page if required */
532 
533 	if (!Page_Uptodate(pg))
534 		ret = yaffs_readpage_nolock(filp, pg);
535 
536 	if (ret)
537 		goto out;
538 
539 	/* Happy path return */
540 	yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok");
541 
542 	return 0;
543 
544 out:
545 	yaffs_trace(YAFFS_TRACE_OS,
546 		"end yaffs_write_begin fail returning %d", ret);
547 	if (space_held)
548 		yaffs_release_space(filp);
549 	if (pg) {
550 		unlock_page(pg);
551 		page_cache_release(pg);
552 	}
553 	return ret;
554 }
555 
556 #else
557 
yaffs_prepare_write(struct file * f,struct page * pg,unsigned offset,unsigned to)558 static int yaffs_prepare_write(struct file *f, struct page *pg,
559 			       unsigned offset, unsigned to)
560 {
561 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write");
562 
563 	if (!Page_Uptodate(pg))
564 		return yaffs_readpage_nolock(f, pg);
565 	return 0;
566 }
567 #endif
568 
569 
yaffs_file_write(struct file * f,const char * buf,size_t n,loff_t * pos)570 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
571 				loff_t * pos)
572 {
573 	struct yaffs_obj *obj;
574 	int n_written;
575 	loff_t ipos;
576 	struct inode *inode;
577 	struct yaffs_dev *dev;
578 
579 	obj = yaffs_dentry_to_obj(f->f_dentry);
580 
581 	if (!obj) {
582 		yaffs_trace(YAFFS_TRACE_OS,
583 			"yaffs_file_write: hey obj is null!");
584                 return -EINVAL;
585         }
586 
587 	dev = obj->my_dev;
588 
589 	yaffs_gross_lock(dev);
590 
591 	inode = f->f_dentry->d_inode;
592 
593 	if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
594 		ipos = inode->i_size;
595 	else
596 		ipos = *pos;
597 
598 	yaffs_trace(YAFFS_TRACE_OS,
599 		"yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
600 		(unsigned)n, (unsigned)n, obj->obj_id, ipos);
601 
602 	n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
603 
604 	yaffs_set_super_dirty(dev);
605 
606 	yaffs_trace(YAFFS_TRACE_OS,
607 		"yaffs_file_write: %d(%x) bytes written",
608 		(unsigned)n, (unsigned)n);
609 
610 	if (n_written > 0) {
611 		ipos += n_written;
612 		*pos = ipos;
613 		if (ipos > inode->i_size) {
614 			inode->i_size = ipos;
615 			inode->i_blocks = (ipos + 511) >> 9;
616 
617 			yaffs_trace(YAFFS_TRACE_OS,
618 				"yaffs_file_write size updated to %lld bytes, %d blocks",
619 				ipos, (int)(inode->i_blocks));
620 		}
621 
622 	}
623 	yaffs_gross_unlock(dev);
624 	return (n_written == 0) && (n > 0) ? -ENOSPC : n_written;
625 }
626 
627 
628 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
yaffs_write_end(struct file * filp,struct address_space * mapping,loff_t pos,unsigned len,unsigned copied,struct page * pg,void * fsdadata)629 static int yaffs_write_end(struct file *filp, struct address_space *mapping,
630 			   loff_t pos, unsigned len, unsigned copied,
631 			   struct page *pg, void *fsdadata)
632 {
633 	int ret = 0;
634 	void *addr, *kva;
635 	uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
636 
637 	kva = kmap(pg);
638 	addr = kva + offset_into_page;
639 
640 	yaffs_trace(YAFFS_TRACE_OS,
641 		"yaffs_write_end addr %p pos %lld n_bytes %d",
642 		addr, pos, copied);
643 
644 	ret = yaffs_file_write(filp, addr, copied, &pos);
645 
646 	if (ret != copied) {
647 		yaffs_trace(YAFFS_TRACE_OS,
648 			"yaffs_write_end not same size ret %d  copied %d",
649 			ret, copied);
650 		SetPageError(pg);
651 	}
652 
653 	kunmap(pg);
654 
655 	yaffs_release_space(filp);
656 	unlock_page(pg);
657 	page_cache_release(pg);
658 	return ret;
659 }
660 #else
661 
yaffs_commit_write(struct file * f,struct page * pg,unsigned offset,unsigned to)662 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
663 			      unsigned to)
664 {
665 	void *addr, *kva;
666 
667 	loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
668 	int n_bytes = to - offset;
669 	int n_written;
670 
671 	kva = kmap(pg);
672 	addr = kva + offset;
673 
674 	yaffs_trace(YAFFS_TRACE_OS,
675 		"yaffs_commit_write addr %p pos %lld n_bytes %d",
676 		addr, pos, n_bytes);
677 
678 	n_written = yaffs_file_write(f, addr, n_bytes, &pos);
679 
680 	if (n_written != n_bytes) {
681 		yaffs_trace(YAFFS_TRACE_OS,
682 			"yaffs_commit_write not same size n_written %d  n_bytes %d",
683 			n_written, n_bytes);
684 		SetPageError(pg);
685 	}
686 	kunmap(pg);
687 
688 	yaffs_trace(YAFFS_TRACE_OS,
689 		"yaffs_commit_write returning %d",
690 		n_written == n_bytes ? 0 : n_written);
691 
692 	return n_written == n_bytes ? 0 : n_written;
693 }
694 #endif
695 
696 static struct address_space_operations yaffs_file_address_operations = {
697 	.readpage = yaffs_readpage,
698 	.writepage = yaffs_writepage,
699 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
700 	.write_begin = yaffs_write_begin,
701 	.write_end = yaffs_write_end,
702 #else
703 	.prepare_write = yaffs_prepare_write,
704 	.commit_write = yaffs_commit_write,
705 #endif
706 };
707 
708 
709 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
yaffs_file_flush(struct file * file,fl_owner_t id)710 static int yaffs_file_flush(struct file *file, fl_owner_t id)
711 #else
712 static int yaffs_file_flush(struct file *file)
713 #endif
714 {
715 	struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
716 
717 	struct yaffs_dev *dev = obj->my_dev;
718 
719 	yaffs_trace(YAFFS_TRACE_OS,
720 		"yaffs_file_flush object %d (%s)",
721 		obj->obj_id,
722 		obj->dirty ? "dirty" : "clean");
723 
724 	yaffs_gross_lock(dev);
725 
726 	yaffs_flush_file(obj, 1, 0);
727 
728 	yaffs_gross_unlock(dev);
729 
730 	return 0;
731 }
732 
733 
734 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
yaffs_sync_object(struct file * file,loff_t start,loff_t end,int datasync)735 static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync)
736 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
737 static int yaffs_sync_object(struct file *file, int datasync)
738 #else
739 static int yaffs_sync_object(struct file *file, struct dentry *dentry,
740 			     int datasync)
741 #endif
742 {
743 	struct yaffs_obj *obj;
744 	struct yaffs_dev *dev;
745 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
746 	struct dentry *dentry = file->f_path.dentry;
747 #endif
748 
749 	obj = yaffs_dentry_to_obj(dentry);
750 
751 	dev = obj->my_dev;
752 
753 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
754 		"yaffs_sync_object");
755 	yaffs_gross_lock(dev);
756 	yaffs_flush_file(obj, 1, datasync);
757 	yaffs_gross_unlock(dev);
758 	return 0;
759 }
760 
761 
762 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
763 static const struct file_operations yaffs_file_operations = {
764 	.read = do_sync_read,
765 	.write = do_sync_write,
766 	.aio_read = generic_file_aio_read,
767 	.aio_write = generic_file_aio_write,
768 	.mmap = generic_file_mmap,
769 	.flush = yaffs_file_flush,
770 	.fsync = yaffs_sync_object,
771 	.splice_read = generic_file_splice_read,
772 	.splice_write = generic_file_splice_write,
773 	.llseek = generic_file_llseek,
774 };
775 
776 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
777 
778 static const struct file_operations yaffs_file_operations = {
779 	.read = do_sync_read,
780 	.write = do_sync_write,
781 	.aio_read = generic_file_aio_read,
782 	.aio_write = generic_file_aio_write,
783 	.mmap = generic_file_mmap,
784 	.flush = yaffs_file_flush,
785 	.fsync = yaffs_sync_object,
786 	.sendfile = generic_file_sendfile,
787 };
788 
789 #else
790 
791 static const struct file_operations yaffs_file_operations = {
792 	.read = generic_file_read,
793 	.write = generic_file_write,
794 	.mmap = generic_file_mmap,
795 	.flush = yaffs_file_flush,
796 	.fsync = yaffs_sync_object,
797 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
798 	.sendfile = generic_file_sendfile,
799 #endif
800 };
801 #endif
802 
803 
804 
805 
806 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
zero_user_segment(struct page * page,unsigned start,unsigned end)807 static void zero_user_segment(struct page *page, unsigned start, unsigned end)
808 {
809 	void *kaddr = kmap_atomic(page, KM_USER0);
810 	memset(kaddr + start, 0, end - start);
811 	kunmap_atomic(kaddr, KM_USER0);
812 	flush_dcache_page(page);
813 }
814 #endif
815 
816 
yaffs_vfs_setsize(struct inode * inode,loff_t newsize)817 static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
818 {
819 #ifdef YAFFS_USE_TRUNCATE_SETSIZE
820 	truncate_setsize(inode, newsize);
821 	return 0;
822 #else
823 	truncate_inode_pages(&inode->i_data, newsize);
824 	return 0;
825 #endif
826 
827 }
828 
829 
yaffs_vfs_setattr(struct inode * inode,struct iattr * attr)830 static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
831 {
832 #ifdef YAFFS_USE_SETATTR_COPY
833 	setattr_copy(inode, attr);
834 	return 0;
835 #else
836 	return inode_setattr(inode, attr);
837 #endif
838 
839 }
840 
yaffs_setattr(struct dentry * dentry,struct iattr * attr)841 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
842 {
843 	struct inode *inode = dentry->d_inode;
844 	int error = 0;
845 	struct yaffs_dev *dev;
846 
847 	yaffs_trace(YAFFS_TRACE_OS,
848 		"yaffs_setattr of object %d",
849 		yaffs_inode_to_obj(inode)->obj_id);
850 #if 0
851 	/* Fail if a requested resize >= 2GB */
852 	if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
853 		error = -EINVAL;
854 #endif
855 
856 	if (error == 0)
857 		error = inode_change_ok(inode, attr);
858 	if (error == 0) {
859 		int result;
860 		if (!error) {
861 			error = yaffs_vfs_setattr(inode, attr);
862 			yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called");
863 			if (attr->ia_valid & ATTR_SIZE) {
864 				yaffs_vfs_setsize(inode, attr->ia_size);
865 				inode->i_blocks = (inode->i_size + 511) >> 9;
866 			}
867 		}
868 		dev = yaffs_inode_to_obj(inode)->my_dev;
869 		if (attr->ia_valid & ATTR_SIZE) {
870 			yaffs_trace(YAFFS_TRACE_OS,
871 				"resize to %d(%x)",
872 				(int)(attr->ia_size),
873 				(int)(attr->ia_size));
874 		}
875 		yaffs_gross_lock(dev);
876 		result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr);
877 		if (result == YAFFS_OK) {
878 			error = 0;
879 		} else {
880 			error = -EPERM;
881 		}
882 		yaffs_gross_unlock(dev);
883 
884 	}
885 
886 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error);
887 
888 	return error;
889 }
890 
yaffs_setxattr(struct dentry * dentry,const char * name,const void * value,size_t size,int flags)891 static int yaffs_setxattr(struct dentry *dentry, const char *name,
892 		   const void *value, size_t size, int flags)
893 {
894 	struct inode *inode = dentry->d_inode;
895 	int error = 0;
896 	struct yaffs_dev *dev;
897 	struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
898 
899 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id);
900 
901 	if (error == 0) {
902 		int result;
903 		dev = obj->my_dev;
904 		yaffs_gross_lock(dev);
905 		result = yaffs_set_xattrib(obj, name, value, size, flags);
906 		if (result == YAFFS_OK)
907 			error = 0;
908 		else if (result < 0)
909 			error = result;
910 		yaffs_gross_unlock(dev);
911 
912 	}
913 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error);
914 
915 	return error;
916 }
917 
yaffs_getxattr(struct dentry * dentry,const char * name,void * buff,size_t size)918 static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name,
919 			void *buff, size_t size)
920 {
921 	struct inode *inode = dentry->d_inode;
922 	int error = 0;
923 	struct yaffs_dev *dev;
924 	struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
925 
926 	yaffs_trace(YAFFS_TRACE_OS,
927 		"yaffs_getxattr \"%s\" from object %d",
928 		name, obj->obj_id);
929 
930 	if (error == 0) {
931 		dev = obj->my_dev;
932 		yaffs_gross_lock(dev);
933 		error = yaffs_get_xattrib(obj, name, buff, size);
934 		yaffs_gross_unlock(dev);
935 
936 	}
937 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error);
938 
939 	return error;
940 }
941 
yaffs_removexattr(struct dentry * dentry,const char * name)942 static int yaffs_removexattr(struct dentry *dentry, const char *name)
943 {
944 	struct inode *inode = dentry->d_inode;
945 	int error = 0;
946 	struct yaffs_dev *dev;
947 	struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
948 
949 	yaffs_trace(YAFFS_TRACE_OS,
950 		"yaffs_removexattr of object %d", obj->obj_id);
951 
952 	if (error == 0) {
953 		int result;
954 		dev = obj->my_dev;
955 		yaffs_gross_lock(dev);
956 		result = yaffs_remove_xattrib(obj, name);
957 		if (result == YAFFS_OK)
958 			error = 0;
959 		else if (result < 0)
960 			error = result;
961 		yaffs_gross_unlock(dev);
962 
963 	}
964 	yaffs_trace(YAFFS_TRACE_OS,
965 		"yaffs_removexattr done returning %d", error);
966 
967 	return error;
968 }
969 
yaffs_listxattr(struct dentry * dentry,char * buff,size_t size)970 static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size)
971 {
972 	struct inode *inode = dentry->d_inode;
973 	int error = 0;
974 	struct yaffs_dev *dev;
975 	struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
976 
977 	yaffs_trace(YAFFS_TRACE_OS,
978 		"yaffs_listxattr of object %d", obj->obj_id);
979 
980 	if (error == 0) {
981 		dev = obj->my_dev;
982 		yaffs_gross_lock(dev);
983 		error = yaffs_list_xattrib(obj, buff, size);
984 		yaffs_gross_unlock(dev);
985 
986 	}
987 	yaffs_trace(YAFFS_TRACE_OS,
988 		"yaffs_listxattr done returning %d", error);
989 
990 	return error;
991 }
992 
993 
994 static const struct inode_operations yaffs_file_inode_operations = {
995 	.setattr = yaffs_setattr,
996 	.setxattr = yaffs_setxattr,
997 	.getxattr = yaffs_getxattr,
998 	.listxattr = yaffs_listxattr,
999 	.removexattr = yaffs_removexattr,
1000 };
1001 
1002 
yaffs_readlink(struct dentry * dentry,char __user * buffer,int buflen)1003 static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
1004 			  int buflen)
1005 {
1006 	unsigned char *alias;
1007 	int ret;
1008 
1009 	struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
1010 
1011 	yaffs_gross_lock(dev);
1012 
1013 	alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
1014 
1015 	yaffs_gross_unlock(dev);
1016 
1017 	if (!alias)
1018 		return -ENOMEM;
1019 
1020 	ret = vfs_readlink(dentry, buffer, buflen, alias);
1021 	kfree(alias);
1022 	return ret;
1023 }
1024 
1025 #if (YAFFS_NEW_FOLLOW_LINK == 1)
yaffs_follow_link(struct dentry * dentry,struct nameidata * nd)1026 static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
1027 {
1028 	void *ret;
1029 #else
1030 static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
1031 {
1032 	int ret
1033 #endif
1034 	unsigned char *alias;
1035 	int ret_int = 0;
1036 	struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
1037 
1038 	yaffs_gross_lock(dev);
1039 
1040 	alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
1041 	yaffs_gross_unlock(dev);
1042 
1043 	if (!alias) {
1044 		ret_int = -ENOMEM;
1045 		goto out;
1046 	}
1047 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1048 	nd_set_link(nd, alias);
1049 	ret = alias;
1050 out:
1051 	if (ret_int)
1052 		ret = ERR_PTR(ret_int);
1053 	return ret;
1054 #else
1055 	ret = vfs_follow_link(nd, alias);
1056 	kfree(alias);
1057 out:
1058 	if (ret_int)
1059 		ret = ret_int;
1060 	return ret;
1061 #endif
1062 }
1063 
1064 
1065 #ifdef YAFFS_HAS_PUT_INODE
1066 
1067 /* For now put inode is just for debugging
1068  * Put inode is called when the inode **structure** is put.
1069  */
1070 static void yaffs_put_inode(struct inode *inode)
1071 {
1072 	yaffs_trace(YAFFS_TRACE_OS,
1073 		"yaffs_put_inode: ino %d, count %d"),
1074 		(int)inode->i_ino, atomic_read(&inode->i_count);
1075 
1076 }
1077 #endif
1078 
1079 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1080 void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias)
1081 {
1082 	kfree(alias);
1083 }
1084 #endif
1085 
1086 static const struct inode_operations yaffs_symlink_inode_operations = {
1087 	.readlink = yaffs_readlink,
1088 	.follow_link = yaffs_follow_link,
1089 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1090 	.put_link = yaffs_put_link,
1091 #endif
1092 	.setattr = yaffs_setattr,
1093 	.setxattr = yaffs_setxattr,
1094 	.getxattr = yaffs_getxattr,
1095 	.listxattr = yaffs_listxattr,
1096 	.removexattr = yaffs_removexattr,
1097 };
1098 
1099 #ifdef YAFFS_USE_OWN_IGET
1100 
1101 static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
1102 {
1103 	struct inode *inode;
1104 	struct yaffs_obj *obj;
1105 	struct yaffs_dev *dev = yaffs_super_to_dev(sb);
1106 
1107 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino);
1108 
1109 	inode = iget_locked(sb, ino);
1110 	if (!inode)
1111 		return ERR_PTR(-ENOMEM);
1112 	if (!(inode->i_state & I_NEW))
1113 		return inode;
1114 
1115 	/* NB This is called as a side effect of other functions, but
1116 	 * we had to release the lock to prevent deadlocks, so
1117 	 * need to lock again.
1118 	 */
1119 
1120 	yaffs_gross_lock(dev);
1121 
1122 	obj = yaffs_find_by_number(dev, inode->i_ino);
1123 
1124 	yaffs_fill_inode_from_obj(inode, obj);
1125 
1126 	yaffs_gross_unlock(dev);
1127 
1128 	unlock_new_inode(inode);
1129 	return inode;
1130 }
1131 
1132 #else
1133 
1134 static void yaffs_read_inode(struct inode *inode)
1135 {
1136 	/* NB This is called as a side effect of other functions, but
1137 	 * we had to release the lock to prevent deadlocks, so
1138 	 * need to lock again.
1139 	 */
1140 
1141 	struct yaffs_obj *obj;
1142 	struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb);
1143 
1144 	yaffs_trace(YAFFS_TRACE_OS,
1145 		"yaffs_read_inode for %d", (int)inode->i_ino);
1146 
1147 	if (current != yaffs_dev_to_lc(dev)->readdir_process)
1148 		yaffs_gross_lock(dev);
1149 
1150 	obj = yaffs_find_by_number(dev, inode->i_ino);
1151 
1152 	yaffs_fill_inode_from_obj(inode, obj);
1153 
1154 	if (current != yaffs_dev_to_lc(dev)->readdir_process)
1155 		yaffs_gross_unlock(dev);
1156 }
1157 
1158 #endif
1159 
1160 
1161 
1162 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
1163 			      struct yaffs_obj *obj)
1164 {
1165 	struct inode *inode;
1166 
1167 	if (!sb) {
1168 		yaffs_trace(YAFFS_TRACE_OS,
1169 			"yaffs_get_inode for NULL super_block!!");
1170 		return NULL;
1171 
1172 	}
1173 
1174 	if (!obj) {
1175 		yaffs_trace(YAFFS_TRACE_OS,
1176 			"yaffs_get_inode for NULL object!!");
1177 		return NULL;
1178 
1179 	}
1180 
1181 	yaffs_trace(YAFFS_TRACE_OS,
1182 		"yaffs_get_inode for object %d", obj->obj_id);
1183 
1184 	inode = Y_IGET(sb, obj->obj_id);
1185 	if (IS_ERR(inode))
1186 		return NULL;
1187 
1188 	/* NB Side effect: iget calls back to yaffs_read_inode(). */
1189 	/* iget also increments the inode's i_count */
1190 	/* NB You can't be holding gross_lock or deadlock will happen! */
1191 
1192 	return inode;
1193 }
1194 
1195 
1196 
1197 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
1198 #define YCRED(x) x
1199 #else
1200 #define YCRED(x) (x->cred)
1201 #endif
1202 
1203 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1204 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
1205 		       dev_t rdev)
1206 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1207 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
1208 		       dev_t rdev)
1209 #else
1210 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
1211 		       int rdev)
1212 #endif
1213 {
1214 	struct inode *inode;
1215 
1216 	struct yaffs_obj *obj = NULL;
1217 	struct yaffs_dev *dev;
1218 
1219 	struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
1220 
1221 	int error = -ENOSPC;
1222 	uid_t uid = YCRED(current)->fsuid;
1223 	gid_t gid =
1224 	    (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
1225 
1226 	if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
1227 		mode |= S_ISGID;
1228 
1229 	if (parent) {
1230 		yaffs_trace(YAFFS_TRACE_OS,
1231 			"yaffs_mknod: parent object %d type %d",
1232 			parent->obj_id, parent->variant_type);
1233 	} else {
1234 		yaffs_trace(YAFFS_TRACE_OS,
1235 			"yaffs_mknod: could not get parent object");
1236 		return -EPERM;
1237 	}
1238 
1239 	yaffs_trace(YAFFS_TRACE_OS,
1240 		"yaffs_mknod: making oject for %s, mode %x dev %x",
1241 		dentry->d_name.name, mode, rdev);
1242 
1243 	dev = parent->my_dev;
1244 
1245 	yaffs_gross_lock(dev);
1246 
1247 	switch (mode & S_IFMT) {
1248 	default:
1249 		/* Special (socket, fifo, device...) */
1250 		yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making special");
1251 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1252 		obj =
1253 		    yaffs_create_special(parent, dentry->d_name.name, mode, uid,
1254 					 gid, old_encode_dev(rdev));
1255 #else
1256 		obj =
1257 		    yaffs_create_special(parent, dentry->d_name.name, mode, uid,
1258 					 gid, rdev);
1259 #endif
1260 		break;
1261 	case S_IFREG:		/* file          */
1262 		yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making file");
1263 		obj = yaffs_create_file(parent, dentry->d_name.name, mode, uid,
1264 					gid);
1265 		break;
1266 	case S_IFDIR:		/* directory */
1267 		yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making directory");
1268 		obj = yaffs_create_dir(parent, dentry->d_name.name, mode,
1269 				       uid, gid);
1270 		break;
1271 	case S_IFLNK:		/* symlink */
1272 		yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink");
1273 		obj = NULL;	/* Do we ever get here? */
1274 		break;
1275 	}
1276 
1277 	/* Can not call yaffs_get_inode() with gross lock held */
1278 	yaffs_gross_unlock(dev);
1279 
1280 	if (obj) {
1281 		inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
1282 		d_instantiate(dentry, inode);
1283 		update_dir_time(dir);
1284 		yaffs_trace(YAFFS_TRACE_OS,
1285 			"yaffs_mknod created object %d count = %d",
1286 			obj->obj_id, atomic_read(&inode->i_count));
1287 		error = 0;
1288 		yaffs_fill_inode_from_obj(dir, parent);
1289 	} else {
1290 		yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object");
1291 		error = -ENOMEM;
1292 	}
1293 
1294 	return error;
1295 }
1296 
1297 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1298 static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1299 #else
1300 static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1301 #endif
1302 {
1303 	int ret_val;
1304 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir");
1305 	ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
1306 	return ret_val;
1307 }
1308 
1309 
1310 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1311 static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1312 			bool dummy)
1313 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1314 static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1315 			struct nameidata *n)
1316 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1317 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
1318 			struct nameidata *n)
1319 #else
1320 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
1321 #endif
1322 {
1323 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_create");
1324 	return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
1325 }
1326 
1327 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1328 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
1329 				   unsigned int dummy)
1330 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1331 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
1332 				   struct nameidata *n)
1333 #else
1334 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
1335 #endif
1336 {
1337 	struct yaffs_obj *obj;
1338 	struct inode *inode = NULL;	/* NCB 2.5/2.6 needs NULL here */
1339 
1340 	struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev;
1341 
1342 	if (current != yaffs_dev_to_lc(dev)->readdir_process)
1343 		yaffs_gross_lock(dev);
1344 
1345 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s",
1346 		yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name);
1347 
1348 	obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name);
1349 
1350 	obj = yaffs_get_equivalent_obj(obj);	/* in case it was a hardlink */
1351 
1352 	/* Can't hold gross lock when calling yaffs_get_inode() */
1353 	if (current != yaffs_dev_to_lc(dev)->readdir_process)
1354 		yaffs_gross_unlock(dev);
1355 
1356 	if (obj) {
1357 		yaffs_trace(YAFFS_TRACE_OS,
1358 			"yaffs_lookup found %d", obj->obj_id);
1359 
1360 		inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
1361 	} else {
1362 		yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found");
1363 
1364 	}
1365 
1366 /* added NCB for 2.5/6 compatability - forces add even if inode is
1367  * NULL which creates dentry hash */
1368 	d_add(dentry, inode);
1369 
1370 	return NULL;
1371 }
1372 
1373 /*
1374  * Create a link...
1375  */
1376 static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
1377 		      struct dentry *dentry)
1378 {
1379 	struct inode *inode = old_dentry->d_inode;
1380 	struct yaffs_obj *obj = NULL;
1381 	struct yaffs_obj *link = NULL;
1382 	struct yaffs_dev *dev;
1383 
1384 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_link");
1385 
1386 	obj = yaffs_inode_to_obj(inode);
1387 	dev = obj->my_dev;
1388 
1389 	yaffs_gross_lock(dev);
1390 
1391 	if (!S_ISDIR(inode->i_mode))	/* Don't link directories */
1392 		link =
1393 		    yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name,
1394 				   obj);
1395 
1396 	if (link) {
1397 		set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj));
1398 		d_instantiate(dentry, old_dentry->d_inode);
1399 		atomic_inc(&old_dentry->d_inode->i_count);
1400 		yaffs_trace(YAFFS_TRACE_OS,
1401 			"yaffs_link link count %d i_count %d",
1402 			old_dentry->d_inode->i_nlink,
1403 			atomic_read(&old_dentry->d_inode->i_count));
1404 	}
1405 
1406 	yaffs_gross_unlock(dev);
1407 
1408 	if (link) {
1409 		update_dir_time(dir);
1410 		return 0;
1411 	}
1412 
1413 	return -EPERM;
1414 }
1415 
1416 static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
1417 			 const char *symname)
1418 {
1419 	struct yaffs_obj *obj;
1420 	struct yaffs_dev *dev;
1421 	uid_t uid = YCRED(current)->fsuid;
1422 	gid_t gid =
1423 	    (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
1424 
1425 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
1426 
1427 	if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) >
1428 				YAFFS_MAX_NAME_LENGTH)
1429 		return -ENAMETOOLONG;
1430 
1431 	if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) >
1432 				YAFFS_MAX_ALIAS_LENGTH)
1433 		return -ENAMETOOLONG;
1434 
1435 	dev = yaffs_inode_to_obj(dir)->my_dev;
1436 	yaffs_gross_lock(dev);
1437 	obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name,
1438 				   S_IFLNK | S_IRWXUGO, uid, gid, symname);
1439 	yaffs_gross_unlock(dev);
1440 
1441 	if (obj) {
1442 		struct inode *inode;
1443 
1444 		inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
1445 		d_instantiate(dentry, inode);
1446 		update_dir_time(dir);
1447 		yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
1448 		return 0;
1449 	} else {
1450 		yaffs_trace(YAFFS_TRACE_OS, "symlink not created");
1451 	}
1452 
1453 	return -ENOMEM;
1454 }
1455 
1456 /*
1457  * The VFS layer already does all the dentry stuff for rename.
1458  *
1459  * NB: POSIX says you can rename an object over an old object of the same name
1460  */
1461 static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
1462 			struct inode *new_dir, struct dentry *new_dentry)
1463 {
1464 	struct yaffs_dev *dev;
1465 	int ret_val = YAFFS_FAIL;
1466 	struct yaffs_obj *target;
1467 
1468 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename");
1469 	dev = yaffs_inode_to_obj(old_dir)->my_dev;
1470 
1471 	yaffs_gross_lock(dev);
1472 
1473 	/* Check if the target is an existing directory that is not empty. */
1474 	target = yaffs_find_by_name(yaffs_inode_to_obj(new_dir),
1475 				    new_dentry->d_name.name);
1476 
1477 	if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
1478 	    !list_empty(&target->variant.dir_variant.children)) {
1479 
1480 		yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir");
1481 
1482 		ret_val = YAFFS_FAIL;
1483 	} else {
1484 		/* Now does unlinking internally using shadowing mechanism */
1485 		yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj");
1486 
1487 		ret_val = yaffs_rename_obj(yaffs_inode_to_obj(old_dir),
1488 					   old_dentry->d_name.name,
1489 					   yaffs_inode_to_obj(new_dir),
1490 					   new_dentry->d_name.name);
1491 	}
1492 	yaffs_gross_unlock(dev);
1493 
1494 	if (ret_val == YAFFS_OK) {
1495 		if (target)
1496 			inode_dec_link_count(new_dentry->d_inode);
1497 
1498 		update_dir_time(old_dir);
1499 		if (old_dir != new_dir)
1500 			update_dir_time(new_dir);
1501 		return 0;
1502 	} else {
1503 		return -ENOTEMPTY;
1504 	}
1505 }
1506 
1507 
1508 
1509 
1510 static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
1511 {
1512 	int ret_val;
1513 
1514 	struct yaffs_dev *dev;
1515 	struct yaffs_obj *obj;
1516 
1517 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_unlink %d:%s",
1518 		(int)(dir->i_ino), dentry->d_name.name);
1519 	obj = yaffs_inode_to_obj(dir);
1520 	dev = obj->my_dev;
1521 
1522 	yaffs_gross_lock(dev);
1523 
1524 	ret_val = yaffs_unlinker(obj, dentry->d_name.name);
1525 
1526 	if (ret_val == YAFFS_OK) {
1527 		inode_dec_link_count(dentry->d_inode);
1528 		dir->i_version++;
1529 		yaffs_gross_unlock(dev);
1530 		update_dir_time(dir);
1531 		return 0;
1532 	}
1533 	yaffs_gross_unlock(dev);
1534 	return -ENOTEMPTY;
1535 }
1536 
1537 
1538 
1539 static const struct inode_operations yaffs_dir_inode_operations = {
1540 	.create = yaffs_create,
1541 	.lookup = yaffs_lookup,
1542 	.link = yaffs_link,
1543 	.unlink = yaffs_unlink,
1544 	.symlink = yaffs_symlink,
1545 	.mkdir = yaffs_mkdir,
1546 	.rmdir = yaffs_unlink,
1547 	.mknod = yaffs_mknod,
1548 	.rename = yaffs_rename,
1549 	.setattr = yaffs_setattr,
1550 	.setxattr = yaffs_setxattr,
1551 	.getxattr = yaffs_getxattr,
1552 	.listxattr = yaffs_listxattr,
1553 	.removexattr = yaffs_removexattr,
1554 };
1555 
1556 /*-----------------------------------------------------------------*/
1557 /* Directory search context allows us to unlock access to yaffs during
1558  * filldir without causing problems with the directory being modified.
1559  * This is similar to the tried and tested mechanism used in yaffs direct.
1560  *
1561  * A search context iterates along a doubly linked list of siblings in the
1562  * directory. If the iterating object is deleted then this would corrupt
1563  * the list iteration, likely causing a crash. The search context avoids
1564  * this by using the remove_obj_fn to move the search context to the
1565  * next object before the object is deleted.
1566  *
1567  * Many readdirs (and thus seach conexts) may be alive simulateously so
1568  * each struct yaffs_dev has a list of these.
1569  *
1570  * A seach context lives for the duration of a readdir.
1571  *
1572  * All these functions must be called while yaffs is locked.
1573  */
1574 
1575 struct yaffs_search_context {
1576 	struct yaffs_dev *dev;
1577 	struct yaffs_obj *dir_obj;
1578 	struct yaffs_obj *next_return;
1579 	struct list_head others;
1580 };
1581 
1582 /*
1583  * yaffs_new_search() creates a new search context, initialises it and
1584  * adds it to the device's search context list.
1585  *
1586  * Called at start of readdir.
1587  */
1588 static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir)
1589 {
1590 	struct yaffs_dev *dev = dir->my_dev;
1591 	struct yaffs_search_context *sc =
1592 	    kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS);
1593 	if (sc) {
1594 		sc->dir_obj = dir;
1595 		sc->dev = dev;
1596 		if (list_empty(&sc->dir_obj->variant.dir_variant.children))
1597 			sc->next_return = NULL;
1598 		else
1599 			sc->next_return =
1600 			    list_entry(dir->variant.dir_variant.children.next,
1601 				       struct yaffs_obj, siblings);
1602 		INIT_LIST_HEAD(&sc->others);
1603 		list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts));
1604 	}
1605 	return sc;
1606 }
1607 
1608 /*
1609  * yaffs_search_end() disposes of a search context and cleans up.
1610  */
1611 static void yaffs_search_end(struct yaffs_search_context *sc)
1612 {
1613 	if (sc) {
1614 		list_del(&sc->others);
1615 		kfree(sc);
1616 	}
1617 }
1618 
1619 /*
1620  * yaffs_search_advance() moves a search context to the next object.
1621  * Called when the search iterates or when an object removal causes
1622  * the search context to be moved to the next object.
1623  */
1624 static void yaffs_search_advance(struct yaffs_search_context *sc)
1625 {
1626 	if (!sc)
1627 		return;
1628 
1629 	if (sc->next_return == NULL ||
1630 	    list_empty(&sc->dir_obj->variant.dir_variant.children))
1631 		sc->next_return = NULL;
1632 	else {
1633 		struct list_head *next = sc->next_return->siblings.next;
1634 
1635 		if (next == &sc->dir_obj->variant.dir_variant.children)
1636 			sc->next_return = NULL;	/* end of list */
1637 		else
1638 			sc->next_return =
1639 			    list_entry(next, struct yaffs_obj, siblings);
1640 	}
1641 }
1642 
1643 /*
1644  * yaffs_remove_obj_callback() is called when an object is unlinked.
1645  * We check open search contexts and advance any which are currently
1646  * on the object being iterated.
1647  */
1648 static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
1649 {
1650 
1651 	struct list_head *i;
1652 	struct yaffs_search_context *sc;
1653 	struct list_head *search_contexts =
1654 	    &(yaffs_dev_to_lc(obj->my_dev)->search_contexts);
1655 
1656 	/* Iterate through the directory search contexts.
1657 	 * If any are currently on the object being removed, then advance
1658 	 * the search context to the next object to prevent a hanging pointer.
1659 	 */
1660 	list_for_each(i, search_contexts) {
1661 		sc = list_entry(i, struct yaffs_search_context, others);
1662 		if (sc->next_return == obj)
1663 			yaffs_search_advance(sc);
1664 	}
1665 
1666 }
1667 
1668 
1669 /*-----------------------------------------------------------------*/
1670 
1671 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
1672 {
1673 	struct yaffs_obj *obj;
1674 	struct yaffs_dev *dev;
1675 	struct yaffs_search_context *sc;
1676 	struct inode *inode = f->f_dentry->d_inode;
1677 	unsigned long offset, curoffs;
1678 	struct yaffs_obj *l;
1679 	int ret_val = 0;
1680 
1681 	char name[YAFFS_MAX_NAME_LENGTH + 1];
1682 
1683 	obj = yaffs_dentry_to_obj(f->f_dentry);
1684 	dev = obj->my_dev;
1685 
1686 	yaffs_gross_lock(dev);
1687 
1688 	yaffs_dev_to_lc(dev)->readdir_process = current;
1689 
1690 	offset = f->f_pos;
1691 
1692 	sc = yaffs_new_search(obj);
1693 	if (!sc) {
1694 		ret_val = -ENOMEM;
1695 		goto out;
1696 	}
1697 
1698 	yaffs_trace(YAFFS_TRACE_OS,
1699 		"yaffs_readdir: starting at %d", (int)offset);
1700 
1701 	if (offset == 0) {
1702 		yaffs_trace(YAFFS_TRACE_OS,
1703 			"yaffs_readdir: entry . ino %d",
1704 			(int)inode->i_ino);
1705 		yaffs_gross_unlock(dev);
1706 		if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) {
1707 			yaffs_gross_lock(dev);
1708 			goto out;
1709 		}
1710 		yaffs_gross_lock(dev);
1711 		offset++;
1712 		f->f_pos++;
1713 	}
1714 	if (offset == 1) {
1715 		yaffs_trace(YAFFS_TRACE_OS,
1716 			"yaffs_readdir: entry .. ino %d",
1717 			(int)f->f_dentry->d_parent->d_inode->i_ino);
1718 		yaffs_gross_unlock(dev);
1719 		if (filldir(dirent, "..", 2, offset,
1720 			    f->f_dentry->d_parent->d_inode->i_ino,
1721 			    DT_DIR) < 0) {
1722 			yaffs_gross_lock(dev);
1723 			goto out;
1724 		}
1725 		yaffs_gross_lock(dev);
1726 		offset++;
1727 		f->f_pos++;
1728 	}
1729 
1730 	curoffs = 1;
1731 
1732 	/* If the directory has changed since the open or last call to
1733 	   readdir, rewind to after the 2 canned entries. */
1734 	if (f->f_version != inode->i_version) {
1735 		offset = 2;
1736 		f->f_pos = offset;
1737 		f->f_version = inode->i_version;
1738 	}
1739 
1740 	while (sc->next_return) {
1741 		curoffs++;
1742 		l = sc->next_return;
1743 		if (curoffs >= offset) {
1744 			int this_inode = yaffs_get_obj_inode(l);
1745 			int this_type = yaffs_get_obj_type(l);
1746 
1747 			yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
1748 			yaffs_trace(YAFFS_TRACE_OS,
1749 				"yaffs_readdir: %s inode %d",
1750 				name, yaffs_get_obj_inode(l));
1751 
1752 			yaffs_gross_unlock(dev);
1753 
1754 			if (filldir(dirent,
1755 				    name,
1756 				    strlen(name),
1757 				    offset, this_inode, this_type) < 0) {
1758 				yaffs_gross_lock(dev);
1759 				goto out;
1760 			}
1761 
1762 			yaffs_gross_lock(dev);
1763 
1764 			offset++;
1765 			f->f_pos++;
1766 		}
1767 		yaffs_search_advance(sc);
1768 	}
1769 
1770 out:
1771 	yaffs_search_end(sc);
1772 	yaffs_dev_to_lc(dev)->readdir_process = NULL;
1773 	yaffs_gross_unlock(dev);
1774 
1775 	return ret_val;
1776 }
1777 
1778 static const struct file_operations yaffs_dir_operations = {
1779 	.read = generic_read_dir,
1780 	.readdir = yaffs_readdir,
1781 	.fsync = yaffs_sync_object,
1782 	.llseek = generic_file_llseek,
1783 };
1784 
1785 static void yaffs_fill_inode_from_obj(struct inode *inode,
1786 				      struct yaffs_obj *obj)
1787 {
1788 	if (inode && obj) {
1789 
1790 		/* Check mode against the variant type and attempt to repair if broken. */
1791 		u32 mode = obj->yst_mode;
1792 		switch (obj->variant_type) {
1793 		case YAFFS_OBJECT_TYPE_FILE:
1794 			if (!S_ISREG(mode)) {
1795 				obj->yst_mode &= ~S_IFMT;
1796 				obj->yst_mode |= S_IFREG;
1797 			}
1798 
1799 			break;
1800 		case YAFFS_OBJECT_TYPE_SYMLINK:
1801 			if (!S_ISLNK(mode)) {
1802 				obj->yst_mode &= ~S_IFMT;
1803 				obj->yst_mode |= S_IFLNK;
1804 			}
1805 
1806 			break;
1807 		case YAFFS_OBJECT_TYPE_DIRECTORY:
1808 			if (!S_ISDIR(mode)) {
1809 				obj->yst_mode &= ~S_IFMT;
1810 				obj->yst_mode |= S_IFDIR;
1811 			}
1812 
1813 			break;
1814 		case YAFFS_OBJECT_TYPE_UNKNOWN:
1815 		case YAFFS_OBJECT_TYPE_HARDLINK:
1816 		case YAFFS_OBJECT_TYPE_SPECIAL:
1817 		default:
1818 			/* TODO? */
1819 			break;
1820 		}
1821 
1822 		inode->i_flags |= S_NOATIME;
1823 
1824 		inode->i_ino = obj->obj_id;
1825 		inode->i_mode = obj->yst_mode;
1826 		inode->i_uid = obj->yst_uid;
1827 		inode->i_gid = obj->yst_gid;
1828 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
1829 		inode->i_blksize = inode->i_sb->s_blocksize;
1830 #endif
1831 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1832 
1833 		inode->i_rdev = old_decode_dev(obj->yst_rdev);
1834 		inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
1835 		inode->i_atime.tv_nsec = 0;
1836 		inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
1837 		inode->i_mtime.tv_nsec = 0;
1838 		inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
1839 		inode->i_ctime.tv_nsec = 0;
1840 #else
1841 		inode->i_rdev = obj->yst_rdev;
1842 		inode->i_atime = obj->yst_atime;
1843 		inode->i_mtime = obj->yst_mtime;
1844 		inode->i_ctime = obj->yst_ctime;
1845 #endif
1846 		inode->i_size = yaffs_get_obj_length(obj);
1847 		inode->i_blocks = (inode->i_size + 511) >> 9;
1848 
1849 		set_nlink(inode, yaffs_get_obj_link_count(obj));
1850 
1851 		yaffs_trace(YAFFS_TRACE_OS,
1852 			"yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
1853 			inode->i_mode, inode->i_uid, inode->i_gid,
1854 			inode->i_size, atomic_read(&inode->i_count));
1855 
1856 		switch (obj->yst_mode & S_IFMT) {
1857 		default:	/* fifo, device or socket */
1858 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1859 			init_special_inode(inode, obj->yst_mode,
1860 					   old_decode_dev(obj->yst_rdev));
1861 #else
1862 			init_special_inode(inode, obj->yst_mode,
1863 					   (dev_t) (obj->yst_rdev));
1864 #endif
1865 			break;
1866 		case S_IFREG:	/* file */
1867 			inode->i_op = &yaffs_file_inode_operations;
1868 			inode->i_fop = &yaffs_file_operations;
1869 			inode->i_mapping->a_ops =
1870 			    &yaffs_file_address_operations;
1871 			break;
1872 		case S_IFDIR:	/* directory */
1873 			inode->i_op = &yaffs_dir_inode_operations;
1874 			inode->i_fop = &yaffs_dir_operations;
1875 			break;
1876 		case S_IFLNK:	/* symlink */
1877 			inode->i_op = &yaffs_symlink_inode_operations;
1878 			break;
1879 		}
1880 
1881 		yaffs_inode_to_obj_lv(inode) = obj;
1882 
1883 		obj->my_inode = inode;
1884 
1885 	} else {
1886 		yaffs_trace(YAFFS_TRACE_OS,
1887 			"yaffs_fill_inode invalid parameters");
1888 	}
1889 
1890 }
1891 
1892 
1893 
1894 /*
1895  * yaffs background thread functions .
1896  * yaffs_bg_thread_fn() the thread function
1897  * yaffs_bg_start() launches the background thread.
1898  * yaffs_bg_stop() cleans up the background thread.
1899  *
1900  * NB:
1901  * The thread should only run after the yaffs is initialised
1902  * The thread should be stopped before yaffs is unmounted.
1903  * The thread should not do any writing while the fs is in read only.
1904  */
1905 
1906 static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
1907 {
1908 	unsigned erased_chunks =
1909 	    dev->n_erased_blocks * dev->param.chunks_per_block;
1910 	struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
1911 	unsigned scattered = 0;	/* Free chunks not in an erased block */
1912 
1913 	if (erased_chunks < dev->n_free_chunks)
1914 		scattered = (dev->n_free_chunks - erased_chunks);
1915 
1916 	if (!context->bg_running)
1917 		return 0;
1918 	else if (scattered < (dev->param.chunks_per_block * 2))
1919 		return 0;
1920 	else if (erased_chunks > dev->n_free_chunks / 2)
1921 		return 0;
1922 	else if (erased_chunks > dev->n_free_chunks / 4)
1923 		return 1;
1924 	else
1925 		return 2;
1926 }
1927 
1928 #ifdef YAFFS_COMPILE_BACKGROUND
1929 
1930 void yaffs_background_waker(unsigned long data)
1931 {
1932 	wake_up_process((struct task_struct *)data);
1933 }
1934 
1935 static int yaffs_bg_thread_fn(void *data)
1936 {
1937 	struct yaffs_dev *dev = (struct yaffs_dev *)data;
1938 	struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
1939 	unsigned long now = jiffies;
1940 	unsigned long next_dir_update = now;
1941 	unsigned long next_gc = now;
1942 	unsigned long expires;
1943 	unsigned int urgency;
1944 
1945 	int gc_result;
1946 	struct timer_list timer;
1947 
1948 	yaffs_trace(YAFFS_TRACE_BACKGROUND,
1949 		"yaffs_background starting for dev %p", (void *)dev);
1950 
1951 #ifdef YAFFS_COMPILE_FREEZER
1952 	set_freezable();
1953 #endif
1954 	while (context->bg_running) {
1955 		yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background");
1956 
1957 		if (kthread_should_stop())
1958 			break;
1959 
1960 #ifdef YAFFS_COMPILE_FREEZER
1961 		if (try_to_freeze())
1962 			continue;
1963 #endif
1964 		yaffs_gross_lock(dev);
1965 
1966 		now = jiffies;
1967 
1968 		if (time_after(now, next_dir_update) && yaffs_bg_enable) {
1969 			yaffs_update_dirty_dirs(dev);
1970 			next_dir_update = now + HZ;
1971 		}
1972 
1973 		if (time_after(now, next_gc) && yaffs_bg_enable) {
1974 			if (!dev->is_checkpointed) {
1975 				urgency = yaffs_bg_gc_urgency(dev);
1976 				gc_result = yaffs_bg_gc(dev, urgency);
1977 				if (urgency > 1)
1978 					next_gc = now + HZ / 20 + 1;
1979 				else if (urgency > 0)
1980 					next_gc = now + HZ / 10 + 1;
1981 				else
1982 					next_gc = now + HZ * 2;
1983 			} else	{
1984 			        /*
1985 				 * gc not running so set to next_dir_update
1986 				 * to cut down on wake ups
1987 				 */
1988 				next_gc = next_dir_update;
1989                         }
1990 		}
1991 		yaffs_gross_unlock(dev);
1992 #if 1
1993 		expires = next_dir_update;
1994 		if (time_before(next_gc, expires))
1995 			expires = next_gc;
1996 		if (time_before(expires, now))
1997 			expires = now + HZ;
1998 
1999 		Y_INIT_TIMER(&timer);
2000 		timer.expires = expires + 1;
2001 		timer.data = (unsigned long)current;
2002 		timer.function = yaffs_background_waker;
2003 
2004 		set_current_state(TASK_INTERRUPTIBLE);
2005 		add_timer(&timer);
2006 		schedule();
2007 		del_timer_sync(&timer);
2008 #else
2009 		msleep(10);
2010 #endif
2011 	}
2012 
2013 	return 0;
2014 }
2015 
2016 static int yaffs_bg_start(struct yaffs_dev *dev)
2017 {
2018 	int retval = 0;
2019 	struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
2020 
2021 	if (dev->read_only)
2022 		return -1;
2023 
2024 	context->bg_running = 1;
2025 
2026 	context->bg_thread = kthread_run(yaffs_bg_thread_fn,
2027 					 (void *)dev, "yaffs-bg-%d",
2028 					 context->mount_id);
2029 
2030 	if (IS_ERR(context->bg_thread)) {
2031 		retval = PTR_ERR(context->bg_thread);
2032 		context->bg_thread = NULL;
2033 		context->bg_running = 0;
2034 	}
2035 	return retval;
2036 }
2037 
2038 static void yaffs_bg_stop(struct yaffs_dev *dev)
2039 {
2040 	struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev);
2041 
2042 	ctxt->bg_running = 0;
2043 
2044 	if (ctxt->bg_thread) {
2045 		kthread_stop(ctxt->bg_thread);
2046 		ctxt->bg_thread = NULL;
2047 	}
2048 }
2049 #else
2050 static int yaffs_bg_thread_fn(void *data)
2051 {
2052 	return 0;
2053 }
2054 
2055 static int yaffs_bg_start(struct yaffs_dev *dev)
2056 {
2057 	return 0;
2058 }
2059 
2060 static void yaffs_bg_stop(struct yaffs_dev *dev)
2061 {
2062 }
2063 #endif
2064 
2065 
2066 static void yaffs_flush_inodes(struct super_block *sb)
2067 {
2068 	struct inode *iptr;
2069 	struct yaffs_obj *obj;
2070 
2071 	list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
2072 		obj = yaffs_inode_to_obj(iptr);
2073 		if (obj) {
2074 			yaffs_trace(YAFFS_TRACE_OS,
2075 				"flushing obj %d",
2076 				obj->obj_id);
2077 			yaffs_flush_file(obj, 1, 0);
2078 		}
2079 	}
2080 }
2081 
2082 static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
2083 {
2084 	struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2085 	if (!dev)
2086 		return;
2087 
2088 	yaffs_flush_inodes(sb);
2089 	yaffs_update_dirty_dirs(dev);
2090 	yaffs_flush_whole_cache(dev);
2091 	if (do_checkpoint)
2092 		yaffs_checkpoint_save(dev);
2093 }
2094 
2095 static LIST_HEAD(yaffs_context_list);
2096 struct mutex yaffs_context_lock;
2097 
2098 static void yaffs_put_super(struct super_block *sb)
2099 {
2100 	struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2101 	struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
2102 
2103 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
2104 			"yaffs_put_super");
2105 
2106 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
2107 		"Shutting down yaffs background thread");
2108 	yaffs_bg_stop(dev);
2109 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
2110 		"yaffs background thread shut down");
2111 
2112 	yaffs_gross_lock(dev);
2113 
2114 	yaffs_flush_super(sb, 1);
2115 
2116 	yaffs_deinitialise(dev);
2117 
2118 	yaffs_gross_unlock(dev);
2119 
2120 	mutex_lock(&yaffs_context_lock);
2121 	list_del_init(&(yaffs_dev_to_lc(dev)->context_list));
2122 	mutex_unlock(&yaffs_context_lock);
2123 
2124 	if (yaffs_dev_to_lc(dev)->spare_buffer) {
2125 		kfree(yaffs_dev_to_lc(dev)->spare_buffer);
2126 		yaffs_dev_to_lc(dev)->spare_buffer = NULL;
2127 	}
2128 
2129 	kfree(dev);
2130 
2131 	yaffs_put_mtd_device(mtd);
2132 
2133 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
2134 			"yaffs_put_super done");
2135 }
2136 
2137 
2138 static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev)
2139 {
2140 	return yaffs_gc_control;
2141 }
2142 
2143 
2144 #ifdef YAFFS_COMPILE_EXPORTFS
2145 
2146 static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
2147 					  uint32_t generation)
2148 {
2149 	return Y_IGET(sb, ino);
2150 }
2151 
2152 static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb,
2153 					  struct fid *fid, int fh_len,
2154 					  int fh_type)
2155 {
2156 	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
2157 				    yaffs2_nfs_get_inode);
2158 }
2159 
2160 static struct dentry *yaffs2_fh_to_parent(struct super_block *sb,
2161 					  struct fid *fid, int fh_len,
2162 					  int fh_type)
2163 {
2164 	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
2165 				    yaffs2_nfs_get_inode);
2166 }
2167 
2168 struct dentry *yaffs2_get_parent(struct dentry *dentry)
2169 {
2170 
2171 	struct super_block *sb = dentry->d_inode->i_sb;
2172 	struct dentry *parent = ERR_PTR(-ENOENT);
2173 	struct inode *inode;
2174 	unsigned long parent_ino;
2175 	struct yaffs_obj *d_obj;
2176 	struct yaffs_obj *parent_obj;
2177 
2178 	d_obj = yaffs_inode_to_obj(dentry->d_inode);
2179 
2180 	if (d_obj) {
2181 		parent_obj = d_obj->parent;
2182 		if (parent_obj) {
2183 			parent_ino = yaffs_get_obj_inode(parent_obj);
2184 			inode = Y_IGET(sb, parent_ino);
2185 
2186 			if (IS_ERR(inode)) {
2187 				parent = ERR_CAST(inode);
2188 			} else {
2189 				parent = d_obtain_alias(inode);
2190 				if (!IS_ERR(parent)) {
2191 					parent = ERR_PTR(-ENOMEM);
2192 					iput(inode);
2193 				}
2194 			}
2195 		}
2196 	}
2197 
2198 	return parent;
2199 }
2200 
2201 /* Just declare a zero structure as a NULL value implies
2202  * using the default functions of exportfs.
2203  */
2204 
2205 static struct export_operations yaffs_export_ops = {
2206 	.fh_to_dentry = yaffs2_fh_to_dentry,
2207 	.fh_to_parent = yaffs2_fh_to_parent,
2208 	.get_parent = yaffs2_get_parent,
2209 };
2210 
2211 #endif
2212 
2213 static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj)
2214 {
2215 	/* Clear the association between the inode and
2216 	 * the struct yaffs_obj.
2217 	 */
2218 	obj->my_inode = NULL;
2219 	yaffs_inode_to_obj_lv(inode) = NULL;
2220 
2221 	/* If the object freeing was deferred, then the real
2222 	 * free happens now.
2223 	 * This should fix the inode inconsistency problem.
2224 	 */
2225 	yaffs_handle_defered_free(obj);
2226 }
2227 
2228 #ifdef YAFFS_HAS_EVICT_INODE
2229 /* yaffs_evict_inode combines into one operation what was previously done in
2230  * yaffs_clear_inode() and yaffs_delete_inode()
2231  *
2232  */
2233 static void yaffs_evict_inode(struct inode *inode)
2234 {
2235 	struct yaffs_obj *obj;
2236 	struct yaffs_dev *dev;
2237 	int deleteme = 0;
2238 
2239 	obj = yaffs_inode_to_obj(inode);
2240 
2241 	yaffs_trace(YAFFS_TRACE_OS,
2242 		"yaffs_evict_inode: ino %d, count %d %s",
2243 		(int)inode->i_ino, atomic_read(&inode->i_count),
2244 		obj ? "object exists" : "null object");
2245 
2246 	if (!inode->i_nlink && !is_bad_inode(inode))
2247 		deleteme = 1;
2248 	truncate_inode_pages(&inode->i_data, 0);
2249 	Y_CLEAR_INODE(inode);
2250 
2251 	if (deleteme && obj) {
2252 		dev = obj->my_dev;
2253 		yaffs_gross_lock(dev);
2254 		yaffs_del_obj(obj);
2255 		yaffs_gross_unlock(dev);
2256 	}
2257 	if (obj) {
2258 		dev = obj->my_dev;
2259 		yaffs_gross_lock(dev);
2260 		yaffs_unstitch_obj(inode, obj);
2261 		yaffs_gross_unlock(dev);
2262 	}
2263 }
2264 #else
2265 
2266 /* clear is called to tell the fs to release any per-inode data it holds.
2267  * The object might still exist on disk and is just being thrown out of the cache
2268  * or else the object has actually been deleted and we're being called via
2269  * the chain
2270  *   yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
2271  */
2272 
2273 static void yaffs_clear_inode(struct inode *inode)
2274 {
2275 	struct yaffs_obj *obj;
2276 	struct yaffs_dev *dev;
2277 
2278 	obj = yaffs_inode_to_obj(inode);
2279 
2280 	yaffs_trace(YAFFS_TRACE_OS,
2281 		"yaffs_clear_inode: ino %d, count %d %s",
2282 		(int)inode->i_ino, atomic_read(&inode->i_count),
2283 		obj ? "object exists" : "null object");
2284 
2285 	if (obj) {
2286 		dev = obj->my_dev;
2287 		yaffs_gross_lock(dev);
2288 		yaffs_unstitch_obj(inode, obj);
2289 		yaffs_gross_unlock(dev);
2290 	}
2291 
2292 }
2293 
2294 /* delete is called when the link count is zero and the inode
2295  * is put (ie. nobody wants to know about it anymore, time to
2296  * delete the file).
2297  * NB Must call clear_inode()
2298  */
2299 static void yaffs_delete_inode(struct inode *inode)
2300 {
2301 	struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
2302 	struct yaffs_dev *dev;
2303 
2304 	yaffs_trace(YAFFS_TRACE_OS,
2305 		"yaffs_delete_inode: ino %d, count %d %s",
2306 		(int)inode->i_ino, atomic_read(&inode->i_count),
2307 		obj ? "object exists" : "null object");
2308 
2309 	if (obj) {
2310 		dev = obj->my_dev;
2311 		yaffs_gross_lock(dev);
2312 		yaffs_del_obj(obj);
2313 		yaffs_gross_unlock(dev);
2314 	}
2315 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
2316 	truncate_inode_pages(&inode->i_data, 0);
2317 #endif
2318 	clear_inode(inode);
2319 }
2320 #endif
2321 
2322 
2323 
2324 
2325 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2326 static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
2327 {
2328 	struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
2329 	struct super_block *sb = dentry->d_sb;
2330 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2331 static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
2332 {
2333 	struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2334 #else
2335 static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
2336 {
2337 	struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2338 #endif
2339 
2340 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs");
2341 
2342 	yaffs_gross_lock(dev);
2343 
2344 	buf->f_type = YAFFS_MAGIC;
2345 	buf->f_bsize = sb->s_blocksize;
2346 	buf->f_namelen = 255;
2347 
2348 	if (dev->data_bytes_per_chunk & (dev->data_bytes_per_chunk - 1)) {
2349 		/* Do this if chunk size is not a power of 2 */
2350 
2351 		uint64_t bytes_in_dev;
2352 		uint64_t bytes_free;
2353 
2354 		bytes_in_dev =
2355 		    ((uint64_t)
2356 		     ((dev->param.end_block - dev->param.start_block +
2357 		       1))) * ((uint64_t) (dev->param.chunks_per_block *
2358 					   dev->data_bytes_per_chunk));
2359 
2360 		do_div(bytes_in_dev, sb->s_blocksize);	/* bytes_in_dev becomes the number of blocks */
2361 		buf->f_blocks = bytes_in_dev;
2362 
2363 		bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) *
2364 		    ((uint64_t) (dev->data_bytes_per_chunk));
2365 
2366 		do_div(bytes_free, sb->s_blocksize);
2367 
2368 		buf->f_bfree = bytes_free;
2369 
2370 	} else if (sb->s_blocksize > dev->data_bytes_per_chunk) {
2371 
2372 		buf->f_blocks =
2373 		    (dev->param.end_block - dev->param.start_block + 1) *
2374 		    dev->param.chunks_per_block /
2375 		    (sb->s_blocksize / dev->data_bytes_per_chunk);
2376 		buf->f_bfree =
2377 		    yaffs_get_n_free_chunks(dev) /
2378 		    (sb->s_blocksize / dev->data_bytes_per_chunk);
2379 	} else {
2380 		buf->f_blocks =
2381 		    (dev->param.end_block - dev->param.start_block + 1) *
2382 		    dev->param.chunks_per_block *
2383 		    (dev->data_bytes_per_chunk / sb->s_blocksize);
2384 
2385 		buf->f_bfree =
2386 		    yaffs_get_n_free_chunks(dev) *
2387 		    (dev->data_bytes_per_chunk / sb->s_blocksize);
2388 	}
2389 
2390 	buf->f_files = 0;
2391 	buf->f_ffree = 0;
2392 	buf->f_bavail = buf->f_bfree;
2393 
2394 	yaffs_gross_unlock(dev);
2395 	return 0;
2396 }
2397 
2398 
2399 
2400 static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
2401 {
2402 
2403 	struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2404 	unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
2405 	unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
2406 	int do_checkpoint;
2407 	int dirty = yaffs_check_super_dirty(dev);
2408 
2409 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
2410 		"yaffs_do_sync_fs: gc-urgency %d %s %s%s",
2411 		gc_urgent,
2412 		dirty ? "dirty" : "clean",
2413 		request_checkpoint ? "checkpoint requested" : "no checkpoint",
2414 		oneshot_checkpoint ? " one-shot" : "");
2415 
2416 	yaffs_gross_lock(dev);
2417 	do_checkpoint = ((request_checkpoint && !gc_urgent) ||
2418 			 oneshot_checkpoint) && !dev->is_checkpointed;
2419 
2420 	if (dirty || do_checkpoint) {
2421 		yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
2422 		yaffs_clear_super_dirty(dev);
2423 		if (oneshot_checkpoint)
2424 			yaffs_auto_checkpoint &= ~4;
2425 	}
2426 	yaffs_gross_unlock(dev);
2427 
2428 	return 0;
2429 }
2430 
2431 
2432 #ifdef YAFFS_HAS_WRITE_SUPER
2433 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2434 static void yaffs_write_super(struct super_block *sb)
2435 #else
2436 static int yaffs_write_super(struct super_block *sb)
2437 #endif
2438 {
2439 	unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
2440 
2441 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
2442 		"yaffs_write_super %s",
2443 		request_checkpoint ? " checkpt" : "");
2444 
2445 	yaffs_do_sync_fs(sb, request_checkpoint);
2446 
2447 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
2448 	return 0;
2449 #endif
2450 }
2451 #endif
2452 
2453 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2454 static int yaffs_sync_fs(struct super_block *sb, int wait)
2455 #else
2456 static int yaffs_sync_fs(struct super_block *sb)
2457 #endif
2458 {
2459 	unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1);
2460 
2461 	yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
2462 		"yaffs_sync_fs%s", request_checkpoint ? " checkpt" : "");
2463 
2464 	yaffs_do_sync_fs(sb, request_checkpoint);
2465 
2466 	return 0;
2467 }
2468 
2469 
2470 
2471 static const struct super_operations yaffs_super_ops = {
2472 	.statfs = yaffs_statfs,
2473 
2474 #ifndef YAFFS_USE_OWN_IGET
2475 	.read_inode = yaffs_read_inode,
2476 #endif
2477 #ifdef YAFFS_HAS_PUT_INODE
2478 	.put_inode = yaffs_put_inode,
2479 #endif
2480 	.put_super = yaffs_put_super,
2481 #ifdef YAFFS_HAS_EVICT_INODE
2482 	.evict_inode = yaffs_evict_inode,
2483 #else
2484 	.delete_inode = yaffs_delete_inode,
2485 	.clear_inode = yaffs_clear_inode,
2486 #endif
2487 	.sync_fs = yaffs_sync_fs,
2488 #ifdef YAFFS_HAS_WRITE_SUPER
2489 	.write_super = yaffs_write_super,
2490 #endif
2491 };
2492 
2493 struct yaffs_options {
2494 	int inband_tags;
2495 	int skip_checkpoint_read;
2496 	int skip_checkpoint_write;
2497 	int no_cache;
2498 	int tags_ecc_on;
2499 	int tags_ecc_overridden;
2500 	int lazy_loading_enabled;
2501 	int lazy_loading_overridden;
2502 	int empty_lost_and_found;
2503 	int empty_lost_and_found_overridden;
2504 	int disable_summary;
2505 };
2506 
2507 #define MAX_OPT_LEN 30
2508 static int yaffs_parse_options(struct yaffs_options *options,
2509 			       const char *options_str)
2510 {
2511 	char cur_opt[MAX_OPT_LEN + 1];
2512 	int p;
2513 	int error = 0;
2514 
2515 	/* Parse through the options which is a comma seperated list */
2516 
2517 	while (options_str && *options_str && !error) {
2518 		memset(cur_opt, 0, MAX_OPT_LEN + 1);
2519 		p = 0;
2520 
2521 		while (*options_str == ',')
2522 			options_str++;
2523 
2524 		while (*options_str && *options_str != ',') {
2525 			if (p < MAX_OPT_LEN) {
2526 				cur_opt[p] = *options_str;
2527 				p++;
2528 			}
2529 			options_str++;
2530 		}
2531 
2532 		if (!strcmp(cur_opt, "inband-tags")) {
2533 			options->inband_tags = 1;
2534 		} else if (!strcmp(cur_opt, "tags-ecc-off")) {
2535 			options->tags_ecc_on = 0;
2536 			options->tags_ecc_overridden = 1;
2537 		} else if (!strcmp(cur_opt, "tags-ecc-on")) {
2538 			options->tags_ecc_on = 1;
2539 			options->tags_ecc_overridden = 1;
2540 		} else if (!strcmp(cur_opt, "lazy-loading-off")) {
2541 			options->lazy_loading_enabled = 0;
2542 			options->lazy_loading_overridden = 1;
2543 		} else if (!strcmp(cur_opt, "lazy-loading-on")) {
2544 			options->lazy_loading_enabled = 1;
2545 			options->lazy_loading_overridden = 1;
2546 		} else if (!strcmp(cur_opt, "disable-summary")) {
2547 			options->disable_summary = 1;
2548 		} else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
2549 			options->empty_lost_and_found = 0;
2550 			options->empty_lost_and_found_overridden = 1;
2551 		} else if (!strcmp(cur_opt, "empty-lost-and-found-on")) {
2552 			options->empty_lost_and_found = 1;
2553 			options->empty_lost_and_found_overridden = 1;
2554 		} else if (!strcmp(cur_opt, "no-cache")) {
2555 			options->no_cache = 1;
2556 		} else if (!strcmp(cur_opt, "no-checkpoint-read")) {
2557 			options->skip_checkpoint_read = 1;
2558 		} else if (!strcmp(cur_opt, "no-checkpoint-write")) {
2559 			options->skip_checkpoint_write = 1;
2560 		} else if (!strcmp(cur_opt, "no-checkpoint")) {
2561 			options->skip_checkpoint_read = 1;
2562 			options->skip_checkpoint_write = 1;
2563 		} else {
2564 			printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",
2565 			       cur_opt);
2566 			error = 1;
2567 		}
2568 	}
2569 
2570 	return error;
2571 }
2572 
2573 
2574 static struct dentry *yaffs_make_root(struct inode *inode)
2575 {
2576 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
2577 	struct dentry *root = d_alloc_root(inode);
2578 
2579 	if (!root)
2580 		iput(inode);
2581 
2582         return root;
2583 #else
2584         return d_make_root(inode);
2585 #endif
2586 }
2587 
2588 
2589 
2590 
2591 static struct super_block *yaffs_internal_read_super(int yaffs_version,
2592 						     struct super_block *sb,
2593 						     void *data, int silent)
2594 {
2595 	int n_blocks;
2596 	struct inode *inode = NULL;
2597 	struct dentry *root;
2598 	struct yaffs_dev *dev = 0;
2599 	char devname_buf[BDEVNAME_SIZE + 1];
2600 	struct mtd_info *mtd;
2601 	int err;
2602 	char *data_str = (char *)data;
2603 	struct yaffs_linux_context *context = NULL;
2604 	struct yaffs_param *param;
2605 
2606 	int read_only = 0;
2607 
2608 	struct yaffs_options options;
2609 
2610 	unsigned mount_id;
2611 	int found;
2612 	struct yaffs_linux_context *context_iterator;
2613 	struct list_head *l;
2614 
2615 	if (!sb) {
2616 		printk(KERN_INFO "yaffs: sb is NULL\n");
2617 		return NULL;
2618         }
2619 
2620 	sb->s_magic = YAFFS_MAGIC;
2621 	sb->s_op = &yaffs_super_ops;
2622 	sb->s_flags |= MS_NOATIME;
2623 
2624 	read_only = ((sb->s_flags & MS_RDONLY) != 0);
2625 
2626 #ifdef YAFFS_COMPILE_EXPORTFS
2627 	sb->s_export_op = &yaffs_export_ops;
2628 #endif
2629 
2630 	if (!sb->s_dev)
2631 		printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
2632 	else if (!yaffs_devname(sb, devname_buf))
2633 		printk(KERN_INFO "yaffs: devname is NULL\n");
2634 	else
2635 		printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
2636 		       sb->s_dev,
2637 		       yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw");
2638 
2639 	if (!data_str)
2640 		data_str = "";
2641 
2642 	printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str);
2643 
2644 	memset(&options, 0, sizeof(options));
2645 
2646 	if (yaffs_parse_options(&options, data_str)) {
2647 		/* Option parsing failed */
2648 		return NULL;
2649 	}
2650 
2651 	sb->s_blocksize = PAGE_CACHE_SIZE;
2652 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
2653 
2654 	yaffs_trace(YAFFS_TRACE_OS,
2655 		"yaffs_read_super: Using yaffs%d", yaffs_version);
2656 	yaffs_trace(YAFFS_TRACE_OS,
2657 		"yaffs_read_super: block size %d", (int)(sb->s_blocksize));
2658 
2659 	yaffs_trace(YAFFS_TRACE_ALWAYS,
2660 		"yaffs: Attempting MTD mount of %u.%u,\"%s\"",
2661 		MAJOR(sb->s_dev), MINOR(sb->s_dev),
2662 		yaffs_devname(sb, devname_buf));
2663 
2664 	/* Get the device */
2665 	mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
2666 	if (!mtd) {
2667 		yaffs_trace(YAFFS_TRACE_ALWAYS,
2668 			"yaffs: MTD device %u either not valid or unavailable",
2669 			MINOR(sb->s_dev));
2670 		return NULL;
2671 	}
2672 
2673 	if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
2674 		yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
2675 		yaffs_version = 2;
2676 	}
2677 
2678 	/* Added NCB 26/5/2006 for completeness */
2679 	if (yaffs_version == 2 && !options.inband_tags
2680 	    && WRITE_SIZE(mtd) == 512) {
2681 		yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
2682 		yaffs_version = 1;
2683 	}
2684 
2685 	if(yaffs_verify_mtd(mtd, yaffs_version, options.inband_tags) < 0)
2686 		return NULL;
2687 
2688 	/* OK, so if we got here, we have an MTD that's NAND and looks
2689 	 * like it has the right capabilities
2690 	 * Set the struct yaffs_dev up for mtd
2691 	 */
2692 
2693 	if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
2694 		read_only = 1;
2695 		printk(KERN_INFO
2696 		       "yaffs: mtd is read only, setting superblock read only\n"
2697 		);
2698 		sb->s_flags |= MS_RDONLY;
2699 	}
2700 
2701 	dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL);
2702 	context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
2703 
2704 	if (!dev || !context) {
2705 		if (dev)
2706 			kfree(dev);
2707 		if (context)
2708 			kfree(context);
2709 		dev = NULL;
2710 		context = NULL;
2711 	}
2712 
2713 	if (!dev) {
2714 		/* Deep shit could not allocate device structure */
2715 		yaffs_trace(YAFFS_TRACE_ALWAYS,
2716 			"yaffs_read_super: Failed trying to allocate struct yaffs_dev."
2717 		);
2718 		return NULL;
2719 	}
2720 	memset(dev, 0, sizeof(struct yaffs_dev));
2721 	param = &(dev->param);
2722 
2723 	memset(context, 0, sizeof(struct yaffs_linux_context));
2724 	dev->os_context = context;
2725 	INIT_LIST_HEAD(&(context->context_list));
2726 	context->dev = dev;
2727 	context->super = sb;
2728 
2729 	dev->read_only = read_only;
2730 
2731 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2732 	sb->s_fs_info = dev;
2733 #else
2734 	sb->u.generic_sbp = dev;
2735 #endif
2736 
2737 
2738 	dev->driver_context = mtd;
2739 	param->name = mtd->name;
2740 
2741 	/* Set up the memory size parameters.... */
2742 
2743 
2744 	param->n_reserved_blocks = 5;
2745 	param->n_caches = (options.no_cache) ? 0 : 10;
2746 	param->inband_tags = options.inband_tags;
2747 
2748 	param->enable_xattr = 1;
2749 	if (options.lazy_loading_overridden)
2750 		param->disable_lazy_load = !options.lazy_loading_enabled;
2751 
2752 	param->defered_dir_update = 1;
2753 
2754 	if (options.tags_ecc_overridden)
2755 		param->no_tags_ecc = !options.tags_ecc_on;
2756 
2757 	param->empty_lost_n_found = 1;
2758 	param->refresh_period = 500;
2759 	param->disable_summary = options.disable_summary;
2760 
2761 	if (options.empty_lost_and_found_overridden)
2762 		param->empty_lost_n_found = options.empty_lost_and_found;
2763 
2764 	/* ... and the functions. */
2765 	if (yaffs_version == 2) {
2766 		param->is_yaffs2 = 1;
2767 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2768 		param->total_bytes_per_chunk = mtd->writesize;
2769 		param->chunks_per_block = mtd->erasesize / mtd->writesize;
2770 #else
2771 		param->total_bytes_per_chunk = mtd->oobblock;
2772 		param->chunks_per_block = mtd->erasesize / mtd->oobblock;
2773 #endif
2774 		n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize);
2775 
2776 		param->start_block = 0;
2777 		param->end_block = n_blocks - 1;
2778 	} else {
2779 		param->is_yaffs2 = 0;
2780 		n_blocks = YCALCBLOCKS(mtd->size,
2781 			     YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
2782 
2783 		param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
2784 		param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
2785 	}
2786 
2787 	param->start_block = 0;
2788 	param->end_block = n_blocks - 1;
2789 
2790 	yaffs_mtd_drv_install(dev);
2791 
2792 	param->sb_dirty_fn = yaffs_set_super_dirty;
2793 	param->gc_control_fn = yaffs_gc_control_callback;
2794 
2795 	yaffs_dev_to_lc(dev)->super = sb;
2796 
2797 	param->use_nand_ecc = 1;
2798 
2799 	param->skip_checkpt_rd = options.skip_checkpoint_read;
2800 	param->skip_checkpt_wr = options.skip_checkpoint_write;
2801 
2802 	mutex_lock(&yaffs_context_lock);
2803 	/* Get a mount id */
2804 	found = 0;
2805 	for (mount_id = 0; !found; mount_id++) {
2806 		found = 1;
2807 		list_for_each(l, &yaffs_context_list) {
2808 			context_iterator =
2809 			    list_entry(l, struct yaffs_linux_context,
2810 				       context_list);
2811 			if (context_iterator->mount_id == mount_id)
2812 				found = 0;
2813 		}
2814 	}
2815 	context->mount_id = mount_id;
2816 
2817 	list_add_tail(&(yaffs_dev_to_lc(dev)->context_list),
2818 		      &yaffs_context_list);
2819 	mutex_unlock(&yaffs_context_lock);
2820 
2821 	/* Directory search handling... */
2822 	INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts));
2823 	param->remove_obj_fn = yaffs_remove_obj_callback;
2824 
2825 	mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock));
2826 
2827 	yaffs_gross_lock(dev);
2828 
2829 	err = yaffs_guts_initialise(dev);
2830 
2831 	yaffs_trace(YAFFS_TRACE_OS,
2832 		"yaffs_read_super: guts initialised %s",
2833 		(err == YAFFS_OK) ? "OK" : "FAILED");
2834 
2835 	if (err == YAFFS_OK)
2836 		yaffs_bg_start(dev);
2837 
2838 	if (!context->bg_thread)
2839 		param->defered_dir_update = 0;
2840 
2841 	sb->s_maxbytes = yaffs_max_file_size(dev);
2842 
2843 	/* Release lock before yaffs_get_inode() */
2844 	yaffs_gross_unlock(dev);
2845 
2846 	/* Create root inode */
2847 	if (err == YAFFS_OK)
2848 		inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev));
2849 
2850 	if (!inode)
2851 		return NULL;
2852 
2853 	inode->i_op = &yaffs_dir_inode_operations;
2854 	inode->i_fop = &yaffs_dir_operations;
2855 
2856 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: got root inode");
2857 
2858 	root = yaffs_make_root(inode);
2859 
2860 	if (!root)
2861 		return NULL;
2862 
2863 	sb->s_root = root;
2864 	if(!dev->is_checkpointed)
2865 		yaffs_set_super_dirty(dev);
2866 
2867 	yaffs_trace(YAFFS_TRACE_ALWAYS,
2868 		"yaffs_read_super: is_checkpointed %d",
2869 		dev->is_checkpointed);
2870 
2871 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done");
2872 	return sb;
2873 }
2874 
2875 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2876 static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
2877 					 int silent)
2878 {
2879 	return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
2880 }
2881 
2882 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2883 static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags,
2884         const char *dev_name, void *data)
2885 {
2886     return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd);
2887 }
2888 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2889 static int yaffs_read_super(struct file_system_type *fs,
2890 			    int flags, const char *dev_name,
2891 			    void *data, struct vfsmount *mnt)
2892 {
2893 
2894 	return get_sb_bdev(fs, flags, dev_name, data,
2895 			   yaffs_internal_read_super_mtd, mnt);
2896 }
2897 #else
2898 static struct super_block *yaffs_read_super(struct file_system_type *fs,
2899 					    int flags, const char *dev_name,
2900 					    void *data)
2901 {
2902 
2903 	return get_sb_bdev(fs, flags, dev_name, data,
2904 			   yaffs_internal_read_super_mtd);
2905 }
2906 #endif
2907 
2908 static struct file_system_type yaffs_fs_type = {
2909 	.owner = THIS_MODULE,
2910 	.name = "yaffs",
2911 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2912         .mount = yaffs_mount,
2913 #else
2914         .get_sb = yaffs_read_super,
2915 #endif
2916      	.kill_sb = kill_block_super,
2917 	.fs_flags = FS_REQUIRES_DEV,
2918 };
2919 #else
2920 static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
2921 					    int silent)
2922 {
2923 	return yaffs_internal_read_super(1, sb, data, silent);
2924 }
2925 
2926 static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
2927 		      FS_REQUIRES_DEV);
2928 #endif
2929 
2930 
2931 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2932 static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
2933 					  int silent)
2934 {
2935 	return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
2936 }
2937 
2938 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2939 static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags,
2940         const char *dev_name, void *data)
2941 {
2942         return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd);
2943 }
2944 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2945 static int yaffs2_read_super(struct file_system_type *fs,
2946 			     int flags, const char *dev_name, void *data,
2947 			     struct vfsmount *mnt)
2948 {
2949 	return get_sb_bdev(fs, flags, dev_name, data,
2950 			   yaffs2_internal_read_super_mtd, mnt);
2951 }
2952 #else
2953 static struct super_block *yaffs2_read_super(struct file_system_type *fs,
2954 					     int flags, const char *dev_name,
2955 					     void *data)
2956 {
2957 
2958 	return get_sb_bdev(fs, flags, dev_name, data,
2959 			   yaffs2_internal_read_super_mtd);
2960 }
2961 #endif
2962 
2963 static struct file_system_type yaffs2_fs_type = {
2964 	.owner = THIS_MODULE,
2965 	.name = "yaffs2",
2966 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2967         .mount = yaffs2_mount,
2968 #else
2969         .get_sb = yaffs2_read_super,
2970 #endif
2971      	.kill_sb = kill_block_super,
2972 	.fs_flags = FS_REQUIRES_DEV,
2973 };
2974 #else
2975 static struct super_block *yaffs2_read_super(struct super_block *sb,
2976 					     void *data, int silent)
2977 {
2978 	return yaffs_internal_read_super(2, sb, data, silent);
2979 }
2980 
2981 static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
2982 		      FS_REQUIRES_DEV);
2983 #endif
2984 
2985 
2986 static struct proc_dir_entry *my_proc_entry;
2987 
2988 static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
2989 {
2990 	struct yaffs_param *param = &dev->param;
2991 
2992 	buf += sprintf(buf, "start_block.......... %d\n", param->start_block);
2993 	buf += sprintf(buf, "end_block............ %d\n", param->end_block);
2994 	buf += sprintf(buf, "total_bytes_per_chunk %d\n",
2995 				param->total_bytes_per_chunk);
2996 	buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc);
2997 	buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc);
2998 	buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2);
2999 	buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags);
3000 	buf += sprintf(buf, "empty_lost_n_found... %d\n",
3001 				param->empty_lost_n_found);
3002 	buf += sprintf(buf, "disable_lazy_load.... %d\n",
3003 				param->disable_lazy_load);
3004 	buf += sprintf(buf, "refresh_period....... %d\n",
3005 				param->refresh_period);
3006 	buf += sprintf(buf, "n_caches............. %d\n", param->n_caches);
3007 	buf += sprintf(buf, "n_reserved_blocks.... %d\n",
3008 				param->n_reserved_blocks);
3009 	buf += sprintf(buf, "always_check_erased.. %d\n",
3010 				param->always_check_erased);
3011 	buf += sprintf(buf, "\n");
3012 
3013 	return buf;
3014 }
3015 
3016 static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
3017 {
3018 	buf += sprintf(buf, "max file size....... %lld\n",
3019 				(long long) yaffs_max_file_size(dev));
3020 	buf += sprintf(buf, "data_bytes_per_chunk. %d\n",
3021 				dev->data_bytes_per_chunk);
3022 	buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits);
3023 	buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size);
3024 	buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks);
3025 	buf += sprintf(buf, "blocks_in_checkpt.... %d\n",
3026 				dev->blocks_in_checkpt);
3027 	buf += sprintf(buf, "\n");
3028 	buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes);
3029 	buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj);
3030 	buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks);
3031 	buf += sprintf(buf, "\n");
3032 	buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes);
3033 	buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads);
3034 	buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures);
3035 	buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies);
3036 	buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs);
3037 	buf += sprintf(buf, "passive_gc_count..... %u\n",
3038 				dev->passive_gc_count);
3039 	buf += sprintf(buf, "oldest_dirty_gc_count %u\n",
3040 				dev->oldest_dirty_gc_count);
3041 	buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks);
3042 	buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs);
3043 	buf += sprintf(buf, "n_retried_writes..... %u\n",
3044 				dev->n_retried_writes);
3045 	buf += sprintf(buf, "n_retired_blocks..... %u\n",
3046 				dev->n_retired_blocks);
3047 	buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed);
3048 	buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed);
3049 	buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n",
3050 				dev->n_tags_ecc_fixed);
3051 	buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n",
3052 				dev->n_tags_ecc_unfixed);
3053 	buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits);
3054 	buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files);
3055 	buf += sprintf(buf, "n_unlinked_files..... %u\n",
3056 				dev->n_unlinked_files);
3057 	buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
3058 	buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
3059 	buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
3060 	buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
3061 
3062 	return buf;
3063 }
3064 
3065 static int yaffs_proc_read(char *page,
3066 			   char **start,
3067 			   off_t offset, int count, int *eof, void *data)
3068 {
3069 	struct list_head *item;
3070 	char *buf = page;
3071 	int step = offset;
3072 	int n = 0;
3073 
3074 	/* Get proc_file_read() to step 'offset' by one on each sucessive call.
3075 	 * We use 'offset' (*ppos) to indicate where we are in dev_list.
3076 	 * This also assumes the user has posted a read buffer large
3077 	 * enough to hold the complete output; but that's life in /proc.
3078 	 */
3079 
3080 	*(int *)start = 1;
3081 
3082 	/* Print header first */
3083 	if (step == 0)
3084 		buf +=
3085 		    sprintf(buf,
3086 			    "Multi-version YAFFS built:" __DATE__ " " __TIME__
3087 			    "\n");
3088 	else if (step == 1)
3089 		buf += sprintf(buf, "\n");
3090 	else {
3091 		step -= 2;
3092 
3093 		mutex_lock(&yaffs_context_lock);
3094 
3095 		/* Locate and print the Nth entry.  Order N-squared but N is small. */
3096 		list_for_each(item, &yaffs_context_list) {
3097 			struct yaffs_linux_context *dc =
3098 			    list_entry(item, struct yaffs_linux_context,
3099 				       context_list);
3100 			struct yaffs_dev *dev = dc->dev;
3101 
3102 			if (n < (step & ~1)) {
3103 				n += 2;
3104 				continue;
3105 			}
3106 			if ((step & 1) == 0) {
3107 				buf +=
3108 				    sprintf(buf, "\nDevice %d \"%s\"\n", n,
3109 					    dev->param.name);
3110 				buf = yaffs_dump_dev_part0(buf, dev);
3111 			} else {
3112 				buf = yaffs_dump_dev_part1(buf, dev);
3113                         }
3114 
3115 			break;
3116 		}
3117 		mutex_unlock(&yaffs_context_lock);
3118 	}
3119 
3120 	return buf - page < count ? buf - page : count;
3121 }
3122 
3123 /**
3124  * Set the verbosity of the warnings and error messages.
3125  *
3126  * Note that the names can only be a..z or _ with the current code.
3127  */
3128 
3129 static struct {
3130 	char *mask_name;
3131 	unsigned mask_bitfield;
3132 } mask_flags[] = {
3133 	{"allocate", YAFFS_TRACE_ALLOCATE},
3134 	{"always", YAFFS_TRACE_ALWAYS},
3135 	{"background", YAFFS_TRACE_BACKGROUND},
3136 	{"bad_blocks", YAFFS_TRACE_BAD_BLOCKS},
3137 	{"buffers", YAFFS_TRACE_BUFFERS},
3138 	{"bug", YAFFS_TRACE_BUG},
3139 	{"checkpt", YAFFS_TRACE_CHECKPOINT},
3140 	{"deletion", YAFFS_TRACE_DELETION},
3141 	{"erase", YAFFS_TRACE_ERASE},
3142 	{"error", YAFFS_TRACE_ERROR},
3143 	{"gc_detail", YAFFS_TRACE_GC_DETAIL},
3144 	{"gc", YAFFS_TRACE_GC},
3145 	{"lock", YAFFS_TRACE_LOCK},
3146 	{"mtd", YAFFS_TRACE_MTD},
3147 	{"nandaccess", YAFFS_TRACE_NANDACCESS},
3148 	{"os", YAFFS_TRACE_OS},
3149 	{"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
3150 	{"scan", YAFFS_TRACE_SCAN},
3151 	{"mount", YAFFS_TRACE_MOUNT},
3152 	{"tracing", YAFFS_TRACE_TRACING},
3153 	{"sync", YAFFS_TRACE_SYNC},
3154 	{"write", YAFFS_TRACE_WRITE},
3155 	{"verify", YAFFS_TRACE_VERIFY},
3156 	{"verify_nand", YAFFS_TRACE_VERIFY_NAND},
3157 	{"verify_full", YAFFS_TRACE_VERIFY_FULL},
3158 	{"verify_all", YAFFS_TRACE_VERIFY_ALL},
3159 	{"all", 0xffffffff},
3160 	{"none", 0},
3161 	{NULL, 0},
3162 };
3163 
3164 #define MAX_MASK_NAME_LENGTH 40
3165 static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
3166 					  unsigned long count, void *data)
3167 {
3168 	unsigned rg = 0, mask_bitfield;
3169 	char *end;
3170 	char *mask_name;
3171 	const char *x;
3172 	char substring[MAX_MASK_NAME_LENGTH + 1];
3173 	int i;
3174 	int done = 0;
3175 	int add, len = 0;
3176 	int pos = 0;
3177 
3178 	rg = yaffs_trace_mask;
3179 
3180 	while (!done && (pos < count)) {
3181 		done = 1;
3182 		while ((pos < count) && isspace(buf[pos]))
3183 			pos++;
3184 
3185 		switch (buf[pos]) {
3186 		case '+':
3187 		case '-':
3188 		case '=':
3189 			add = buf[pos];
3190 			pos++;
3191 			break;
3192 
3193 		default:
3194 			add = ' ';
3195 			break;
3196 		}
3197 		mask_name = NULL;
3198 
3199 		mask_bitfield = simple_strtoul(buf + pos, &end, 0);
3200 
3201 		if (end > buf + pos) {
3202 			mask_name = "numeral";
3203 			len = end - (buf + pos);
3204 			pos += len;
3205 			done = 0;
3206 		} else {
3207 			for (x = buf + pos, i = 0;
3208 			     (*x == '_' || (*x >= 'a' && *x <= 'z')) &&
3209 			     i < MAX_MASK_NAME_LENGTH; x++, i++, pos++)
3210 				substring[i] = *x;
3211 			substring[i] = '\0';
3212 
3213 			for (i = 0; mask_flags[i].mask_name != NULL; i++) {
3214 				if (strcmp(substring, mask_flags[i].mask_name)
3215 				    == 0) {
3216 					mask_name = mask_flags[i].mask_name;
3217 					mask_bitfield =
3218 					    mask_flags[i].mask_bitfield;
3219 					done = 0;
3220 					break;
3221 				}
3222 			}
3223 		}
3224 
3225 		if (mask_name != NULL) {
3226 			done = 0;
3227 			switch (add) {
3228 			case '-':
3229 				rg &= ~mask_bitfield;
3230 				break;
3231 			case '+':
3232 				rg |= mask_bitfield;
3233 				break;
3234 			case '=':
3235 				rg = mask_bitfield;
3236 				break;
3237 			default:
3238 				rg |= mask_bitfield;
3239 				break;
3240 			}
3241 		}
3242 	}
3243 
3244 	yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS;
3245 
3246 	printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask);
3247 
3248 	if (rg & YAFFS_TRACE_ALWAYS) {
3249 		for (i = 0; mask_flags[i].mask_name != NULL; i++) {
3250 			char flag;
3251 			flag = ((rg & mask_flags[i].mask_bitfield) ==
3252 				mask_flags[i].mask_bitfield) ? '+' : '-';
3253 			printk(KERN_DEBUG "%c%s\n", flag,
3254 			       mask_flags[i].mask_name);
3255 		}
3256 	}
3257 
3258 	return count;
3259 }
3260 
3261 static int yaffs_proc_write(struct file *file, const char *buf,
3262 			    unsigned long count, void *data)
3263 {
3264 	return yaffs_proc_write_trace_options(file, buf, count, data);
3265 }
3266 
3267 /* Stuff to handle installation of file systems */
3268 struct file_system_to_install {
3269 	struct file_system_type *fst;
3270 	int installed;
3271 };
3272 
3273 static struct file_system_to_install fs_to_install[] = {
3274 	{&yaffs_fs_type, 0},
3275 	{&yaffs2_fs_type, 0},
3276 	{NULL, 0}
3277 };
3278 
3279 static int __init init_yaffs_fs(void)
3280 {
3281 	int error = 0;
3282 	struct file_system_to_install *fsinst;
3283 
3284 	yaffs_trace(YAFFS_TRACE_ALWAYS,
3285 		"yaffs built " __DATE__ " " __TIME__ " Installing.");
3286 
3287 	mutex_init(&yaffs_context_lock);
3288 
3289 	/* Install the proc_fs entries */
3290 	my_proc_entry = create_proc_entry("yaffs",
3291 					  S_IRUGO | S_IFREG, YPROC_ROOT);
3292 
3293 	if (my_proc_entry) {
3294 		my_proc_entry->write_proc = yaffs_proc_write;
3295 		my_proc_entry->read_proc = yaffs_proc_read;
3296 		my_proc_entry->data = NULL;
3297 	} else {
3298 		return -ENOMEM;
3299         }
3300 
3301 	/* Now add the file system entries */
3302 
3303 	fsinst = fs_to_install;
3304 
3305 	while (fsinst->fst && !error) {
3306 		error = register_filesystem(fsinst->fst);
3307 		if (!error)
3308 			fsinst->installed = 1;
3309 		fsinst++;
3310 	}
3311 
3312 	/* Any errors? uninstall  */
3313 	if (error) {
3314 		fsinst = fs_to_install;
3315 
3316 		while (fsinst->fst) {
3317 			if (fsinst->installed) {
3318 				unregister_filesystem(fsinst->fst);
3319 				fsinst->installed = 0;
3320 			}
3321 			fsinst++;
3322 		}
3323 	}
3324 
3325 	return error;
3326 }
3327 
3328 static void __exit exit_yaffs_fs(void)
3329 {
3330 
3331 	struct file_system_to_install *fsinst;
3332 
3333 	yaffs_trace(YAFFS_TRACE_ALWAYS,
3334 		"yaffs built " __DATE__ " " __TIME__ " removing.");
3335 
3336 	remove_proc_entry("yaffs", YPROC_ROOT);
3337 
3338 	fsinst = fs_to_install;
3339 
3340 	while (fsinst->fst) {
3341 		if (fsinst->installed) {
3342 			unregister_filesystem(fsinst->fst);
3343 			fsinst->installed = 0;
3344 		}
3345 		fsinst++;
3346 	}
3347 }
3348 
3349 module_init(init_yaffs_fs)
3350     module_exit(exit_yaffs_fs)
3351 
3352     MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
3353 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
3354 MODULE_LICENSE("GPL");
3355