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