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