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