2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2010 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
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
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.
23 * This is the file system front-end to YAFFS that hooks it up to
27 * >> 2.4: sb->u.generic_sbp points to the yaffs_dev_t associated with
29 * >> 2.6: sb->s_fs_info points to the yaffs_dev_t associated with this
31 * >> inode->u.generic_ip points to the associated yaffs_obj_t.
35 * There are two variants of the VFS glue code. This variant should compile
36 * for any version of Linux.
38 #include <linux/version.h>
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
47 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
48 #define YAFFS_COMPILE_EXPORTFS
51 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
52 #define YAFFS_USE_SETATTR_COPY
53 #define YAFFS_USE_TRUNCATE_SETSIZE
55 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
56 #define YAFFS_HAS_EVICT_INODE
59 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
60 #define YAFFS_NEW_FOLLOW_LINK 1
62 #define YAFFS_NEW_FOLLOW_LINK 0
65 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
66 #include <linux/config.h>
69 #include <linux/kernel.h>
70 #include <linux/module.h>
71 #include <linux/slab.h>
72 #include <linux/init.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>
82 #if (YAFFS_NEW_FOLLOW_LINK == 1)
83 #include <linux/namei.h>
86 #ifdef YAFFS_COMPILE_EXPORTFS
87 #include <linux/exportfs.h>
90 #ifdef YAFFS_COMPILE_BACKGROUND
91 #include <linux/kthread.h>
92 #include <linux/delay.h>
94 #ifdef YAFFS_COMPILE_FREEZER
95 #include <linux/freezer.h>
98 #include <asm/div64.h>
100 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
102 #include <linux/statfs.h>
104 #define UnlockPage(p) unlock_page(p)
105 #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
107 /* FIXME: use sb->s_id instead ? */
108 #define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
112 #include <linux/locks.h>
113 #define BDEVNAME_SIZE 0
114 #define yaffs_devname(sb, buf) kdevname(sb->s_dev)
116 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
117 /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
123 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
124 #define YPROC_ROOT (&proc_root)
126 #define YPROC_ROOT NULL
129 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
130 #define Y_INIT_TIMER(a) init_timer(a)
132 #define Y_INIT_TIMER(a) init_timer_on_stack(a)
135 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
136 #define WRITE_SIZE_STR "writesize"
137 #define WRITE_SIZE(mtd) ((mtd)->writesize)
139 #define WRITE_SIZE_STR "oobblock"
140 #define WRITE_SIZE(mtd) ((mtd)->oobblock)
143 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
144 #define YAFFS_USE_WRITE_BEGIN_END 1
146 #define YAFFS_USE_WRITE_BEGIN_END 0
149 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
150 static uint32_t YCALCBLOCKS(uint64_t partition_size
, uint32_t block_size
)
152 uint64_t result
= partition_size
;
153 do_div(result
, block_size
);
154 return (uint32_t)result
;
157 #define YCALCBLOCKS(s, b) ((s)/(b))
160 #include <linux/uaccess.h>
161 #include <linux/mtd/mtd.h>
163 #include "yportenv.h"
164 #include "yaffs_trace.h"
165 #include "yaffs_guts.h"
167 #include "yaffs_linux.h"
169 #include "yaffs_mtdif.h"
170 #include "yaffs_mtdif1.h"
171 #include "yaffs_mtdif2.h"
173 unsigned int yaffs_trace_mask
= YAFFS_TRACE_BAD_BLOCKS
| YAFFS_TRACE_ALWAYS
;
174 unsigned int yaffs_wr_attempts
= YAFFS_WR_ATTEMPTS
;
175 unsigned int yaffs_auto_checkpoint
= 1;
176 unsigned int yaffs_gc_control
= 1;
177 unsigned int yaffs_bg_enable
= 1;
179 /* Module Parameters */
180 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
181 module_param(yaffs_trace_mask
, uint
, 0644);
182 module_param(yaffs_wr_attempts
, uint
, 0644);
183 module_param(yaffs_auto_checkpoint
, uint
, 0644);
184 module_param(yaffs_gc_control
, uint
, 0644);
185 module_param(yaffs_bg_enable
, uint
, 0644);
187 MODULE_PARM(yaffs_trace_mask
, "i");
188 MODULE_PARM(yaffs_wr_attempts
, "i");
189 MODULE_PARM(yaffs_auto_checkpoint
, "i");
190 MODULE_PARM(yaffs_gc_control
, "i");
193 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
194 /* use iget and read_inode */
195 #define Y_IGET(sb, inum) iget((sb), (inum))
196 static void yaffs_read_inode(struct inode
*inode
);
199 /* Call local equivalent */
200 #define YAFFS_USE_OWN_IGET
201 #define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
203 static struct inode
*yaffs_iget(struct super_block
*sb
, unsigned long ino
);
206 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
207 #define yaffs_InodeToObjectLV(iptr) ((iptr)->i_private)
209 #define yaffs_InodeToObjectLV(iptr) ((iptr)->u.generic_ip)
212 #define yaffs_InodeToObject(iptr) ((yaffs_obj_t *)(yaffs_InodeToObjectLV(iptr)))
213 #define yaffs_dentry_to_obj(dptr) yaffs_InodeToObject((dptr)->d_inode)
215 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
216 #define yaffs_SuperToDevice(sb) ((yaffs_dev_t *)sb->s_fs_info)
218 #define yaffs_SuperToDevice(sb) ((yaffs_dev_t *)sb->u.generic_sbp)
222 #define update_dir_time(dir) do {\
223 (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
226 static void yaffs_put_super(struct super_block
*sb
);
228 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
230 static ssize_t
yaffs_hold_space(struct file
*f
);
231 static void yaffs_release_space(struct file
*f
);
233 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
234 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
);
236 static int yaffs_file_flush(struct file
*file
);
239 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
240 static int yaffs_sync_object(struct file
*file
, int datasync
);
242 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
246 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
);
248 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
249 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
250 struct nameidata
*n
);
251 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
252 struct nameidata
*n
);
254 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
);
255 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
);
257 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
258 struct dentry
*dentry
);
259 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
);
260 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
261 const char *symname
);
262 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
);
264 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
265 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
268 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
271 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
272 struct inode
*new_dir
, struct dentry
*new_dentry
);
273 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
);
275 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
276 static int yaffs_sync_fs(struct super_block
*sb
, int wait
);
277 static void yaffs_write_super(struct super_block
*sb
);
279 static int yaffs_sync_fs(struct super_block
*sb
);
280 static int yaffs_write_super(struct super_block
*sb
);
283 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
284 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
);
285 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
286 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
);
288 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
);
291 #ifdef YAFFS_HAS_PUT_INODE
292 static void yaffs_put_inode(struct inode
*inode
);
295 #ifdef YAFFS_HAS_EVICT_INODE
296 static void yaffs_evict_inode(struct inode
*);
298 static void yaffs_delete_inode(struct inode
*);
299 static void yaffs_clear_inode(struct inode
*);
302 static int yaffs_readpage(struct file
*file
, struct page
*page
);
303 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
304 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
);
306 static int yaffs_writepage(struct page
*page
);
309 #ifdef CONFIG_YAFFS_XATTR
310 int yaffs_setxattr(struct dentry
*dentry
, const char *name
,
311 const void *value
, size_t size
, int flags
);
312 ssize_t
yaffs_getxattr(struct dentry
*dentry
, const char *name
, void *buff
,
314 int yaffs_removexattr(struct dentry
*dentry
, const char *name
);
315 ssize_t
yaffs_listxattr(struct dentry
*dentry
, char *buff
, size_t size
);
319 #if (YAFFS_USE_WRITE_BEGIN_END != 0)
320 static int yaffs_write_begin(struct file
*filp
, struct address_space
*mapping
,
321 loff_t pos
, unsigned len
, unsigned flags
,
322 struct page
**pagep
, void **fsdata
);
323 static int yaffs_write_end(struct file
*filp
, struct address_space
*mapping
,
324 loff_t pos
, unsigned len
, unsigned copied
,
325 struct page
*pg
, void *fsdadata
);
327 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
328 unsigned offset
, unsigned to
);
329 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
334 static int yaffs_readlink(struct dentry
*dentry
, char __user
*buffer
,
336 #if (YAFFS_NEW_FOLLOW_LINK == 1)
337 void yaffs_put_link(struct dentry
*dentry
, struct nameidata
*nd
, void *alias
);
338 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
);
340 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
);
343 static void yaffs_touch_super(yaffs_dev_t
*dev
);
345 static loff_t
yaffs_dir_llseek(struct file
*file
, loff_t offset
, int origin
);
347 static int yaffs_vfs_setattr(struct inode
*, struct iattr
*);
350 static struct address_space_operations yaffs_file_address_operations
= {
351 .readpage
= yaffs_readpage
,
352 .writepage
= yaffs_writepage
,
353 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
354 .write_begin
= yaffs_write_begin
,
355 .write_end
= yaffs_write_end
,
357 .prepare_write
= yaffs_prepare_write
,
358 .commit_write
= yaffs_commit_write
,
363 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
364 static const struct file_operations yaffs_file_operations
= {
365 .read
= do_sync_read
,
366 .write
= do_sync_write
,
367 .aio_read
= generic_file_aio_read
,
368 .aio_write
= generic_file_aio_write
,
369 .mmap
= generic_file_mmap
,
370 .flush
= yaffs_file_flush
,
371 .fsync
= yaffs_sync_object
,
372 .splice_read
= generic_file_splice_read
,
373 .splice_write
= generic_file_splice_write
,
374 .llseek
= generic_file_llseek
,
377 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
379 static const struct file_operations yaffs_file_operations
= {
380 .read
= do_sync_read
,
381 .write
= do_sync_write
,
382 .aio_read
= generic_file_aio_read
,
383 .aio_write
= generic_file_aio_write
,
384 .mmap
= generic_file_mmap
,
385 .flush
= yaffs_file_flush
,
386 .fsync
= yaffs_sync_object
,
387 .sendfile
= generic_file_sendfile
,
392 static const struct file_operations yaffs_file_operations
= {
393 .read
= generic_file_read
,
394 .write
= generic_file_write
,
395 .mmap
= generic_file_mmap
,
396 .flush
= yaffs_file_flush
,
397 .fsync
= yaffs_sync_object
,
398 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
399 .sendfile
= generic_file_sendfile
,
404 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
405 static void zero_user_segment(struct page
*page
, unsigned start
, unsigned end
)
407 void * kaddr
= kmap_atomic(page
, KM_USER0
);
408 memset(kaddr
+ start
, 0, end
- start
);
409 kunmap_atomic(kaddr
, KM_USER0
);
410 flush_dcache_page(page
);
415 static const struct inode_operations yaffs_file_inode_operations
= {
416 .setattr
= yaffs_setattr
,
417 #ifdef CONFIG_YAFFS_XATTR
418 .setxattr
= yaffs_setxattr
,
419 .getxattr
= yaffs_getxattr
,
420 .listxattr
= yaffs_listxattr
,
421 .removexattr
= yaffs_removexattr
,
425 static const struct inode_operations yaffs_symlink_inode_operations
= {
426 .readlink
= yaffs_readlink
,
427 .follow_link
= yaffs_follow_link
,
428 #if (YAFFS_NEW_FOLLOW_LINK == 1)
429 .put_link
= yaffs_put_link
,
431 .setattr
= yaffs_setattr
,
432 #ifdef CONFIG_YAFFS_XATTR
433 .setxattr
= yaffs_setxattr
,
434 .getxattr
= yaffs_getxattr
,
435 .listxattr
= yaffs_listxattr
,
436 .removexattr
= yaffs_removexattr
,
440 static const struct inode_operations yaffs_dir_inode_operations
= {
441 .create
= yaffs_create
,
442 .lookup
= yaffs_lookup
,
444 .unlink
= yaffs_unlink
,
445 .symlink
= yaffs_symlink
,
446 .mkdir
= yaffs_mkdir
,
447 .rmdir
= yaffs_unlink
,
448 .mknod
= yaffs_mknod
,
449 .rename
= yaffs_rename
,
450 .setattr
= yaffs_setattr
,
451 #ifdef CONFIG_YAFFS_XATTR
452 .setxattr
= yaffs_setxattr
,
453 .getxattr
= yaffs_getxattr
,
454 .listxattr
= yaffs_listxattr
,
455 .removexattr
= yaffs_removexattr
,
459 static const struct file_operations yaffs_dir_operations
= {
460 .read
= generic_read_dir
,
461 .readdir
= yaffs_readdir
,
462 .fsync
= yaffs_sync_object
,
463 .llseek
= yaffs_dir_llseek
,
466 static const struct super_operations yaffs_super_ops
= {
467 .statfs
= yaffs_statfs
,
469 #ifndef YAFFS_USE_OWN_IGET
470 .read_inode
= yaffs_read_inode
,
472 #ifdef YAFFS_HAS_PUT_INODE
473 .put_inode
= yaffs_put_inode
,
475 .put_super
= yaffs_put_super
,
476 #ifdef YAFFS_HAS_EVICT_INODE
477 .evict_inode
= yaffs_evict_inode
,
479 .delete_inode
= yaffs_delete_inode
,
480 .clear_inode
= yaffs_clear_inode
,
482 .sync_fs
= yaffs_sync_fs
,
483 .write_super
= yaffs_write_super
,
487 static int yaffs_vfs_setattr(struct inode
*inode
, struct iattr
*attr
)
489 #ifdef YAFFS_USE_SETATTR_COPY
490 setattr_copy(inode
,attr
);
493 return inode_setattr(inode
, attr
);
498 static int yaffs_vfs_setsize(struct inode
*inode
, loff_t newsize
)
500 #ifdef YAFFS_USE_TRUNCATE_SETSIZE
501 truncate_setsize(inode
,newsize
);
504 truncate_inode_pages(&inode
->i_data
,newsize
);
510 static unsigned yaffs_gc_control_callback(yaffs_dev_t
*dev
)
512 return yaffs_gc_control
;
515 static void yaffs_gross_lock(yaffs_dev_t
*dev
)
517 T(YAFFS_TRACE_LOCK
, (TSTR("yaffs locking %p\n"), current
));
518 down(&(yaffs_dev_to_lc(dev
)->grossLock
));
519 T(YAFFS_TRACE_LOCK
, (TSTR("yaffs locked %p\n"), current
));
522 static void yaffs_gross_unlock(yaffs_dev_t
*dev
)
524 T(YAFFS_TRACE_LOCK
, (TSTR("yaffs unlocking %p\n"), current
));
525 up(&(yaffs_dev_to_lc(dev
)->grossLock
));
528 #ifdef YAFFS_COMPILE_EXPORTFS
530 static struct inode
*
531 yaffs2_nfs_get_inode(struct super_block
*sb
, uint64_t ino
, uint32_t generation
)
533 return Y_IGET(sb
, ino
);
536 static struct dentry
*
537 yaffs2_fh_to_dentry(struct super_block
*sb
, struct fid
*fid
, int fh_len
, int fh_type
)
539 return generic_fh_to_dentry(sb
, fid
, fh_len
, fh_type
, yaffs2_nfs_get_inode
) ;
542 static struct dentry
*
543 yaffs2_fh_to_parent(struct super_block
*sb
, struct fid
*fid
, int fh_len
, int fh_type
)
545 return generic_fh_to_parent(sb
, fid
, fh_len
, fh_type
, yaffs2_nfs_get_inode
);
548 struct dentry
*yaffs2_get_parent(struct dentry
*dentry
)
551 struct super_block
*sb
= dentry
->d_inode
->i_sb
;
552 struct dentry
*parent
= ERR_PTR(-ENOENT
);
554 unsigned long parent_ino
;
556 yaffs_obj_t
*parent_obj
;
558 d_obj
= yaffs_InodeToObject(dentry
->d_inode
);
561 parent_obj
= d_obj
->parent
;
563 parent_ino
= yaffs_get_obj_inode(parent_obj
);
564 inode
= Y_IGET(sb
, parent_ino
);
567 parent
= ERR_CAST(inode
);
569 parent
= d_obtain_alias(inode
);
570 if (!IS_ERR(parent
)) {
571 parent
= ERR_PTR(-ENOMEM
);
581 /* Just declare a zero structure as a NULL value implies
582 * using the default functions of exportfs.
585 static struct export_operations yaffs_export_ops
=
587 .fh_to_dentry
= yaffs2_fh_to_dentry
,
588 .fh_to_parent
= yaffs2_fh_to_parent
,
589 .get_parent
= yaffs2_get_parent
,
594 /*-----------------------------------------------------------------*/
595 /* Directory search context allows us to unlock access to yaffs during
596 * filldir without causing problems with the directory being modified.
597 * This is similar to the tried and tested mechanism used in yaffs direct.
599 * A search context iterates along a doubly linked list of siblings in the
600 * directory. If the iterating object is deleted then this would corrupt
601 * the list iteration, likely causing a crash. The search context avoids
602 * this by using the remove_obj_fn to move the search context to the
603 * next object before the object is deleted.
605 * Many readdirs (and thus seach conexts) may be alive simulateously so
606 * each yaffs_dev_t has a list of these.
608 * A seach context lives for the duration of a readdir.
610 * All these functions must be called while yaffs is locked.
613 struct yaffs_SearchContext
{
616 yaffs_obj_t
*nextReturn
;
617 struct ylist_head others
;
621 * yaffs_NewSearch() creates a new search context, initialises it and
622 * adds it to the device's search context list.
624 * Called at start of readdir.
626 static struct yaffs_SearchContext
* yaffs_NewSearch(yaffs_obj_t
*dir
)
628 yaffs_dev_t
*dev
= dir
->my_dev
;
629 struct yaffs_SearchContext
*sc
= YMALLOC(sizeof(struct yaffs_SearchContext
));
633 if( ylist_empty(&sc
->dirObj
->variant
.dir_variant
.children
))
634 sc
->nextReturn
= NULL
;
636 sc
->nextReturn
= ylist_entry(
637 dir
->variant
.dir_variant
.children
.next
,
638 yaffs_obj_t
,siblings
);
639 YINIT_LIST_HEAD(&sc
->others
);
640 ylist_add(&sc
->others
,&(yaffs_dev_to_lc(dev
)->searchContexts
));
646 * yaffs_search_end() disposes of a search context and cleans up.
648 static void yaffs_search_end(struct yaffs_SearchContext
* sc
)
651 ylist_del(&sc
->others
);
657 * yaffs_search_advance() moves a search context to the next object.
658 * Called when the search iterates or when an object removal causes
659 * the search context to be moved to the next object.
661 static void yaffs_search_advance(struct yaffs_SearchContext
*sc
)
666 if( sc
->nextReturn
== NULL
||
667 ylist_empty(&sc
->dirObj
->variant
.dir_variant
.children
))
668 sc
->nextReturn
= NULL
;
670 struct ylist_head
*next
= sc
->nextReturn
->siblings
.next
;
672 if( next
== &sc
->dirObj
->variant
.dir_variant
.children
)
673 sc
->nextReturn
= NULL
; /* end of list */
675 sc
->nextReturn
= ylist_entry(next
,yaffs_obj_t
,siblings
);
680 * yaffs_remove_obj_callback() is called when an object is unlinked.
681 * We check open search contexts and advance any which are currently
682 * on the object being iterated.
684 static void yaffs_remove_obj_callback(yaffs_obj_t
*obj
)
687 struct ylist_head
*i
;
688 struct yaffs_SearchContext
*sc
;
689 struct ylist_head
*search_contexts
= &(yaffs_dev_to_lc(obj
->my_dev
)->searchContexts
);
692 /* Iterate through the directory search contexts.
693 * If any are currently on the object being removed, then advance
694 * the search context to the next object to prevent a hanging pointer.
696 ylist_for_each(i
, search_contexts
) {
698 sc
= ylist_entry(i
, struct yaffs_SearchContext
,others
);
699 if(sc
->nextReturn
== obj
)
700 yaffs_search_advance(sc
);
707 /*-----------------------------------------------------------------*/
709 static int yaffs_readlink(struct dentry
*dentry
, char __user
*buffer
,
712 unsigned char *alias
;
715 yaffs_dev_t
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
717 yaffs_gross_lock(dev
);
719 alias
= yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry
));
721 yaffs_gross_unlock(dev
);
726 ret
= vfs_readlink(dentry
, buffer
, buflen
, alias
);
731 #if (YAFFS_NEW_FOLLOW_LINK == 1)
732 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
734 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
737 unsigned char *alias
;
739 yaffs_dev_t
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
741 yaffs_gross_lock(dev
);
743 alias
= yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry
));
744 yaffs_gross_unlock(dev
);
751 #if (YAFFS_NEW_FOLLOW_LINK == 1)
752 nd_set_link(nd
, alias
);
757 ret
= vfs_follow_link(nd
, alias
);
764 #if (YAFFS_NEW_FOLLOW_LINK == 1)
765 void yaffs_put_link(struct dentry
*dentry
, struct nameidata
*nd
, void *alias
) {
770 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
774 * Lookup is used to find objects in the fs
776 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
778 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
781 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
)
785 struct inode
*inode
= NULL
; /* NCB 2.5/2.6 needs NULL here */
787 yaffs_dev_t
*dev
= yaffs_InodeToObject(dir
)->my_dev
;
789 if(current
!= yaffs_dev_to_lc(dev
)->readdirProcess
)
790 yaffs_gross_lock(dev
);
793 (TSTR("yaffs_lookup for %d:%s\n"),
794 yaffs_InodeToObject(dir
)->obj_id
, dentry
->d_name
.name
));
796 obj
= yaffs_find_by_name(yaffs_InodeToObject(dir
),
797 dentry
->d_name
.name
);
799 obj
= yaffs_get_equivalent_obj(obj
); /* in case it was a hardlink */
801 /* Can't hold gross lock when calling yaffs_get_inode() */
802 if(current
!= yaffs_dev_to_lc(dev
)->readdirProcess
)
803 yaffs_gross_unlock(dev
);
807 (TSTR("yaffs_lookup found %d\n"), obj
->obj_id
));
809 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
813 (TSTR("yaffs_loookup dentry \n")));
814 /* #if 0 asserted by NCB for 2.5/6 compatability - falls through to
815 * d_add even if NULL inode */
817 /*dget(dentry); // try to solve directory bug */
818 d_add(dentry
, inode
);
826 T(YAFFS_TRACE_OS
,(TSTR("yaffs_lookup not found\n")));
830 /* added NCB for 2.5/6 compatability - forces add even if inode is
831 * NULL which creates dentry hash */
832 d_add(dentry
, inode
);
838 #ifdef YAFFS_HAS_PUT_INODE
840 /* For now put inode is just for debugging
841 * Put inode is called when the inode **structure** is put.
843 static void yaffs_put_inode(struct inode
*inode
)
846 (TSTR("yaffs_put_inode: ino %d, count %d\n"), (int)inode
->i_ino
,
847 atomic_read(&inode
->i_count
)));
853 static void yaffs_unstitch_obj(struct inode
*inode
, yaffs_obj_t
*obj
)
855 /* Clear the association between the inode and
858 obj
->my_inode
= NULL
;
859 yaffs_InodeToObjectLV(inode
) = NULL
;
861 /* If the object freeing was deferred, then the real
863 * This should fix the inode inconsistency problem.
865 yaffs_handle_defered_free(obj
);
868 #ifdef YAFFS_HAS_EVICT_INODE
869 /* yaffs_evict_inode combines into one operation what was previously done in
870 * yaffs_clear_inode() and yaffs_delete_inode()
873 static void yaffs_evict_inode( struct inode
*inode
)
879 obj
= yaffs_InodeToObject(inode
);
882 (TSTR("yaffs_evict_inode: ino %d, count %d %s\n"), (int)inode
->i_ino
,
883 atomic_read(&inode
->i_count
),
884 obj
? "object exists" : "null object"));
886 if (!inode
->i_nlink
&& !is_bad_inode(inode
))
888 truncate_inode_pages(&inode
->i_data
,0);
889 end_writeback(inode
);
893 yaffs_gross_lock(dev
);
895 yaffs_gross_unlock(dev
);
899 yaffs_gross_lock(dev
);
900 yaffs_unstitch_obj(inode
,obj
);
901 yaffs_gross_unlock(dev
);
908 /* clear is called to tell the fs to release any per-inode data it holds.
909 * The object might still exist on disk and is just being thrown out of the cache
910 * or else the object has actually been deleted and we're being called via
912 * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
915 static void yaffs_clear_inode(struct inode
*inode
)
920 obj
= yaffs_InodeToObject(inode
);
923 (TSTR("yaffs_clear_inode: ino %d, count %d %s\n"), (int)inode
->i_ino
,
924 atomic_read(&inode
->i_count
),
925 obj
? "object exists" : "null object"));
929 yaffs_gross_lock(dev
);
930 yaffs_unstitch_obj(inode
,obj
);
931 yaffs_gross_unlock(dev
);
936 /* delete is called when the link count is zero and the inode
937 * is put (ie. nobody wants to know about it anymore, time to
939 * NB Must call clear_inode()
941 static void yaffs_delete_inode(struct inode
*inode
)
943 yaffs_obj_t
*obj
= yaffs_InodeToObject(inode
);
947 (TSTR("yaffs_delete_inode: ino %d, count %d %s\n"), (int)inode
->i_ino
,
948 atomic_read(&inode
->i_count
),
949 obj
? "object exists" : "null object"));
953 yaffs_gross_lock(dev
);
955 yaffs_gross_unlock(dev
);
957 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
958 truncate_inode_pages(&inode
->i_data
, 0);
965 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
966 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
)
968 static int yaffs_file_flush(struct file
*file
)
971 yaffs_obj_t
*obj
= yaffs_dentry_to_obj(file
->f_dentry
);
973 yaffs_dev_t
*dev
= obj
->my_dev
;
976 (TSTR("yaffs_file_flush object %d (%s)\n"), obj
->obj_id
,
977 obj
->dirty
? "dirty" : "clean"));
979 yaffs_gross_lock(dev
);
981 yaffs_flush_file(obj
, 1, 0);
983 yaffs_gross_unlock(dev
);
988 static int yaffs_readpage_nolock(struct file
*f
, struct page
*pg
)
990 /* Lifted from jffs2 */
993 unsigned char *pg_buf
;
999 (TSTR("yaffs_readpage_nolock at %08x, size %08x\n"),
1000 (unsigned)(pg
->index
<< PAGE_CACHE_SHIFT
),
1001 (unsigned)PAGE_CACHE_SIZE
));
1003 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1007 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1008 BUG_ON(!PageLocked(pg
));
1010 if (!PageLocked(pg
))
1015 /* FIXME: Can kmap fail? */
1017 yaffs_gross_lock(dev
);
1019 ret
= yaffs_file_rd(obj
, pg_buf
,
1020 pg
->index
<< PAGE_CACHE_SHIFT
,
1023 yaffs_gross_unlock(dev
);
1029 ClearPageUptodate(pg
);
1032 SetPageUptodate(pg
);
1036 flush_dcache_page(pg
);
1039 T(YAFFS_TRACE_OS
, (TSTR("yaffs_readpage_nolock done\n")));
1043 static int yaffs_readpage_unlock(struct file
*f
, struct page
*pg
)
1045 int ret
= yaffs_readpage_nolock(f
, pg
);
1050 static int yaffs_readpage(struct file
*f
, struct page
*pg
)
1054 T(YAFFS_TRACE_OS
, (TSTR("yaffs_readpage\n")));
1055 ret
=yaffs_readpage_unlock(f
, pg
);
1056 T(YAFFS_TRACE_OS
, (TSTR("yaffs_readpage done\n")));
1060 /* writepage inspired by/stolen from smbfs */
1062 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1063 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
)
1065 static int yaffs_writepage(struct page
*page
)
1069 struct address_space
*mapping
= page
->mapping
;
1070 struct inode
*inode
;
1071 unsigned long end_index
;
1080 inode
= mapping
->host
;
1083 i_size
= i_size_read(inode
);
1085 end_index
= i_size
>> PAGE_CACHE_SHIFT
;
1087 if(page
->index
< end_index
)
1088 n_bytes
= PAGE_CACHE_SIZE
;
1090 n_bytes
= i_size
& (PAGE_CACHE_SIZE
-1);
1092 if (page
->index
> end_index
|| !n_bytes
) {
1094 (TSTR("yaffs_writepage at %08x, inode size = %08x!!!\n"),
1095 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
),
1096 (unsigned)inode
->i_size
));
1098 (TSTR(" -> don't care!!\n")));
1100 zero_user_segment(page
,0,PAGE_CACHE_SIZE
);
1101 set_page_writeback(page
);
1103 end_page_writeback(page
);
1108 if(n_bytes
!= PAGE_CACHE_SIZE
)
1109 zero_user_segment(page
,n_bytes
,PAGE_CACHE_SIZE
);
1113 buffer
= kmap(page
);
1115 obj
= yaffs_InodeToObject(inode
);
1117 yaffs_gross_lock(dev
);
1120 (TSTR("yaffs_writepage at %08x, size %08x\n"),
1121 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
), n_bytes
));
1123 (TSTR("writepag0: obj = %05x, ino = %05x\n"),
1124 (int)obj
->variant
.file_variant
.file_size
, (int)inode
->i_size
));
1126 nWritten
= yaffs_wr_file(obj
, buffer
,
1127 page
->index
<< PAGE_CACHE_SHIFT
, n_bytes
, 0);
1129 yaffs_touch_super(dev
);
1132 (TSTR("writepag1: obj = %05x, ino = %05x\n"),
1133 (int)obj
->variant
.file_variant
.file_size
, (int)inode
->i_size
));
1135 yaffs_gross_unlock(dev
);
1138 set_page_writeback(page
);
1140 end_page_writeback(page
);
1143 return (nWritten
== n_bytes
) ? 0 : -ENOSPC
;
1147 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
1148 static int yaffs_write_begin(struct file
*filp
, struct address_space
*mapping
,
1149 loff_t pos
, unsigned len
, unsigned flags
,
1150 struct page
**pagep
, void **fsdata
)
1152 struct page
*pg
= NULL
;
1153 pgoff_t index
= pos
>> PAGE_CACHE_SHIFT
;
1159 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
1160 pg
= grab_cache_page_write_begin(mapping
, index
, flags
);
1162 pg
= __grab_cache_page(mapping
, index
);
1171 (TSTR("start yaffs_write_begin index %d(%x) uptodate %d\n"),
1172 (int)index
,(int)index
,Page_Uptodate(pg
) ? 1 : 0));
1175 space_held
= yaffs_hold_space(filp
);
1182 /* Update page if required */
1184 if (!Page_Uptodate(pg
))
1185 ret
= yaffs_readpage_nolock(filp
, pg
);
1190 /* Happy path return */
1191 T(YAFFS_TRACE_OS
, (TSTR("end yaffs_write_begin - ok\n")));
1197 (TSTR("end yaffs_write_begin fail returning %d\n"), ret
));
1199 yaffs_release_space(filp
);
1202 page_cache_release(pg
);
1209 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
1210 unsigned offset
, unsigned to
)
1212 T(YAFFS_TRACE_OS
, (TSTR("yaffs_prepair_write\n")));
1214 if (!Page_Uptodate(pg
))
1215 return yaffs_readpage_nolock(f
, pg
);
1220 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
1221 static int yaffs_write_end(struct file
*filp
, struct address_space
*mapping
,
1222 loff_t pos
, unsigned len
, unsigned copied
,
1223 struct page
*pg
, void *fsdadata
)
1227 uint32_t offset_into_page
= pos
& (PAGE_CACHE_SIZE
- 1);
1230 addr
= kva
+ offset_into_page
;
1233 ("yaffs_write_end addr %p pos %x n_bytes %d\n",
1234 addr
,(unsigned)pos
, copied
));
1236 ret
= yaffs_file_write(filp
, addr
, copied
, &pos
);
1238 if (ret
!= copied
) {
1240 (TSTR("yaffs_write_end not same size ret %d copied %d\n"),
1249 yaffs_release_space(filp
);
1251 page_cache_release(pg
);
1256 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
1261 loff_t pos
= (((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
) + offset
;
1262 int n_bytes
= to
- offset
;
1265 unsigned spos
= pos
;
1269 addr
= kva
+ offset
;
1271 saddr
= (unsigned) addr
;
1274 (TSTR("yaffs_commit_write addr %x pos %x n_bytes %d\n"),
1275 saddr
, spos
, n_bytes
));
1277 nWritten
= yaffs_file_write(f
, addr
, n_bytes
, &pos
);
1279 if (nWritten
!= n_bytes
) {
1281 (TSTR("yaffs_commit_write not same size nWritten %d n_bytes %d\n"),
1282 nWritten
, n_bytes
));
1291 (TSTR("yaffs_commit_write returning %d\n"),
1292 nWritten
== n_bytes
? 0 : nWritten
));
1294 return nWritten
== n_bytes
? 0 : nWritten
;
1299 static void yaffs_fill_inode_from_obj(struct inode
*inode
, yaffs_obj_t
*obj
)
1304 /* Check mode against the variant type and attempt to repair if broken. */
1305 __u32 mode
= obj
->yst_mode
;
1306 switch (obj
->variant_type
) {
1307 case YAFFS_OBJECT_TYPE_FILE
:
1308 if (!S_ISREG(mode
)) {
1309 obj
->yst_mode
&= ~S_IFMT
;
1310 obj
->yst_mode
|= S_IFREG
;
1314 case YAFFS_OBJECT_TYPE_SYMLINK
:
1315 if (!S_ISLNK(mode
)) {
1316 obj
->yst_mode
&= ~S_IFMT
;
1317 obj
->yst_mode
|= S_IFLNK
;
1321 case YAFFS_OBJECT_TYPE_DIRECTORY
:
1322 if (!S_ISDIR(mode
)) {
1323 obj
->yst_mode
&= ~S_IFMT
;
1324 obj
->yst_mode
|= S_IFDIR
;
1328 case YAFFS_OBJECT_TYPE_UNKNOWN
:
1329 case YAFFS_OBJECT_TYPE_HARDLINK
:
1330 case YAFFS_OBJECT_TYPE_SPECIAL
:
1336 inode
->i_flags
|= S_NOATIME
;
1338 inode
->i_ino
= obj
->obj_id
;
1339 inode
->i_mode
= obj
->yst_mode
;
1340 inode
->i_uid
= obj
->yst_uid
;
1341 inode
->i_gid
= obj
->yst_gid
;
1342 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
1343 inode
->i_blksize
= inode
->i_sb
->s_blocksize
;
1345 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1347 inode
->i_rdev
= old_decode_dev(obj
->yst_rdev
);
1348 inode
->i_atime
.tv_sec
= (time_t) (obj
->yst_atime
);
1349 inode
->i_atime
.tv_nsec
= 0;
1350 inode
->i_mtime
.tv_sec
= (time_t) obj
->yst_mtime
;
1351 inode
->i_mtime
.tv_nsec
= 0;
1352 inode
->i_ctime
.tv_sec
= (time_t) obj
->yst_ctime
;
1353 inode
->i_ctime
.tv_nsec
= 0;
1355 inode
->i_rdev
= obj
->yst_rdev
;
1356 inode
->i_atime
= obj
->yst_atime
;
1357 inode
->i_mtime
= obj
->yst_mtime
;
1358 inode
->i_ctime
= obj
->yst_ctime
;
1360 inode
->i_size
= yaffs_get_obj_length(obj
);
1361 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
1363 inode
->i_nlink
= yaffs_get_obj_link_count(obj
);
1366 (TSTR("yaffs_fill_inode mode %x uid %d gid %d size %d count %d\n"),
1367 inode
->i_mode
, inode
->i_uid
, inode
->i_gid
,
1368 (int)inode
->i_size
, atomic_read(&inode
->i_count
)));
1370 switch (obj
->yst_mode
& S_IFMT
) {
1371 default: /* fifo, device or socket */
1372 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1373 init_special_inode(inode
, obj
->yst_mode
,
1374 old_decode_dev(obj
->yst_rdev
));
1376 init_special_inode(inode
, obj
->yst_mode
,
1377 (dev_t
) (obj
->yst_rdev
));
1380 case S_IFREG
: /* file */
1381 inode
->i_op
= &yaffs_file_inode_operations
;
1382 inode
->i_fop
= &yaffs_file_operations
;
1383 inode
->i_mapping
->a_ops
=
1384 &yaffs_file_address_operations
;
1386 case S_IFDIR
: /* directory */
1387 inode
->i_op
= &yaffs_dir_inode_operations
;
1388 inode
->i_fop
= &yaffs_dir_operations
;
1390 case S_IFLNK
: /* symlink */
1391 inode
->i_op
= &yaffs_symlink_inode_operations
;
1395 yaffs_InodeToObjectLV(inode
) = obj
;
1397 obj
->my_inode
= inode
;
1401 (TSTR("yaffs_FileInode invalid parameters\n")));
1406 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
1409 struct inode
*inode
;
1413 (TSTR("yaffs_get_inode for NULL super_block!!\n")));
1420 (TSTR("yaffs_get_inode for NULL object!!\n")));
1426 (TSTR("yaffs_get_inode for object %d\n"), obj
->obj_id
));
1428 inode
= Y_IGET(sb
, obj
->obj_id
);
1432 /* NB Side effect: iget calls back to yaffs_read_inode(). */
1433 /* iget also increments the inode's i_count */
1434 /* NB You can't be holding grossLock or deadlock will happen! */
1439 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
1444 struct inode
*inode
;
1447 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1451 yaffs_gross_lock(dev
);
1453 inode
= f
->f_dentry
->d_inode
;
1455 if (!S_ISBLK(inode
->i_mode
) && f
->f_flags
& O_APPEND
)
1456 ipos
= inode
->i_size
;
1462 (TSTR("yaffs_file_write: hey obj is null!\n")));
1465 (TSTR("yaffs_file_write about to write writing %u(%x) bytes"
1466 "to object %d at %d(%x)\n"),
1467 (unsigned) n
, (unsigned) n
, obj
->obj_id
, ipos
,ipos
));
1469 nWritten
= yaffs_wr_file(obj
, buf
, ipos
, n
, 0);
1471 yaffs_touch_super(dev
);
1474 (TSTR("yaffs_file_write: %d(%x) bytes written\n"),
1475 (unsigned )n
,(unsigned)n
));
1480 if (ipos
> inode
->i_size
) {
1481 inode
->i_size
= ipos
;
1482 inode
->i_blocks
= (ipos
+ 511) >> 9;
1485 (TSTR("yaffs_file_write size updated to %d bytes, "
1487 ipos
, (int)(inode
->i_blocks
)));
1491 yaffs_gross_unlock(dev
);
1492 return (nWritten
== 0) && (n
> 0) ? -ENOSPC
: nWritten
;
1495 /* Space holding and freeing is done to ensure we have space available for write_begin/end */
1496 /* For now we just assume few parallel writes and check against a small number. */
1497 /* Todo: need to do this with a counter to handle parallel reads better */
1499 static ssize_t
yaffs_hold_space(struct file
*f
)
1507 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1511 yaffs_gross_lock(dev
);
1513 n_free_chunks
= yaffs_get_n_free_chunks(dev
);
1515 yaffs_gross_unlock(dev
);
1517 return (n_free_chunks
> 20) ? 1 : 0;
1520 static void yaffs_release_space(struct file
*f
)
1526 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1530 yaffs_gross_lock(dev
);
1533 yaffs_gross_unlock(dev
);
1537 static loff_t
yaffs_dir_llseek(struct file
*file
, loff_t offset
, int origin
)
1545 offset
+= i_size_read(file
->f_path
.dentry
->d_inode
);
1548 offset
+= file
->f_pos
;
1553 if (offset
!= file
->f_pos
)
1554 file
->f_pos
= offset
;
1563 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
)
1567 struct yaffs_SearchContext
*sc
;
1568 struct inode
*inode
= f
->f_dentry
->d_inode
;
1569 unsigned long offset
, curoffs
;
1573 char name
[YAFFS_MAX_NAME_LENGTH
+ 1];
1575 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1578 yaffs_gross_lock(dev
);
1580 yaffs_dev_to_lc(dev
)->readdirProcess
= current
;
1584 sc
= yaffs_NewSearch(obj
);
1590 T(YAFFS_TRACE_OS
, (TSTR("yaffs_readdir: starting at %d\n"), (int)offset
));
1594 (TSTR("yaffs_readdir: entry . ino %d \n"),
1595 (int)inode
->i_ino
));
1596 yaffs_gross_unlock(dev
);
1597 if (filldir(dirent
, ".", 1, offset
, inode
->i_ino
, DT_DIR
) < 0){
1598 yaffs_gross_lock(dev
);
1601 yaffs_gross_lock(dev
);
1607 (TSTR("yaffs_readdir: entry .. ino %d \n"),
1608 (int)f
->f_dentry
->d_parent
->d_inode
->i_ino
));
1609 yaffs_gross_unlock(dev
);
1610 if (filldir(dirent
, "..", 2, offset
,
1611 f
->f_dentry
->d_parent
->d_inode
->i_ino
, DT_DIR
) < 0){
1612 yaffs_gross_lock(dev
);
1615 yaffs_gross_lock(dev
);
1622 /* If the directory has changed since the open or last call to
1623 readdir, rewind to after the 2 canned entries. */
1624 if (f
->f_version
!= inode
->i_version
) {
1627 f
->f_version
= inode
->i_version
;
1630 while(sc
->nextReturn
){
1633 if (curoffs
>= offset
) {
1634 int this_inode
= yaffs_get_obj_inode(l
);
1635 int this_type
= yaffs_get_obj_type(l
);
1637 yaffs_get_obj_name(l
, name
,
1638 YAFFS_MAX_NAME_LENGTH
+ 1);
1640 (TSTR("yaffs_readdir: %s inode %d\n"),
1641 name
, yaffs_get_obj_inode(l
)));
1643 yaffs_gross_unlock(dev
);
1651 yaffs_gross_lock(dev
);
1655 yaffs_gross_lock(dev
);
1660 yaffs_search_advance(sc
);
1664 yaffs_search_end(sc
);
1665 yaffs_dev_to_lc(dev
)->readdirProcess
= NULL
;
1666 yaffs_gross_unlock(dev
);
1674 * File creation. Allocate an inode, and we're done..
1677 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
1680 #define YCRED(x) (x->cred)
1683 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1684 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1687 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1691 struct inode
*inode
;
1693 yaffs_obj_t
*obj
= NULL
;
1696 yaffs_obj_t
*parent
= yaffs_InodeToObject(dir
);
1698 int error
= -ENOSPC
;
1699 uid_t uid
= YCRED(current
)->fsuid
;
1700 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: YCRED(current
)->fsgid
;
1702 if ((dir
->i_mode
& S_ISGID
) && S_ISDIR(mode
))
1707 (TSTR("yaffs_mknod: parent object %d type %d\n"),
1708 parent
->obj_id
, parent
->variant_type
));
1711 (TSTR("yaffs_mknod: could not get parent object\n")));
1715 T(YAFFS_TRACE_OS
, (TSTR("yaffs_mknod: making oject for %s, "
1716 "mode %x dev %x\n"),
1717 dentry
->d_name
.name
, mode
, rdev
));
1719 dev
= parent
->my_dev
;
1721 yaffs_gross_lock(dev
);
1723 switch (mode
& S_IFMT
) {
1725 /* Special (socket, fifo, device...) */
1726 T(YAFFS_TRACE_OS
, (TSTR("yaffs_mknod: making special\n")));
1727 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1728 obj
= yaffs_create_special(parent
, dentry
->d_name
.name
, mode
, uid
,
1729 gid
, old_encode_dev(rdev
));
1731 obj
= yaffs_create_special(parent
, dentry
->d_name
.name
, mode
, uid
,
1735 case S_IFREG
: /* file */
1736 T(YAFFS_TRACE_OS
, (TSTR("yaffs_mknod: making file\n")));
1737 obj
= yaffs_create_file(parent
, dentry
->d_name
.name
, mode
, uid
,
1740 case S_IFDIR
: /* directory */
1742 (TSTR("yaffs_mknod: making directory\n")));
1743 obj
= yaffs_create_dir(parent
, dentry
->d_name
.name
, mode
,
1746 case S_IFLNK
: /* symlink */
1747 T(YAFFS_TRACE_OS
, (TSTR("yaffs_mknod: making symlink\n")));
1748 obj
= NULL
; /* Do we ever get here? */
1752 /* Can not call yaffs_get_inode() with gross lock held */
1753 yaffs_gross_unlock(dev
);
1756 inode
= yaffs_get_inode(dir
->i_sb
, mode
, rdev
, obj
);
1757 d_instantiate(dentry
, inode
);
1758 update_dir_time(dir
);
1760 (TSTR("yaffs_mknod created object %d count = %d\n"),
1761 obj
->obj_id
, atomic_read(&inode
->i_count
)));
1763 yaffs_fill_inode_from_obj(dir
,parent
);
1766 (TSTR("yaffs_mknod failed making object\n")));
1773 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1776 T(YAFFS_TRACE_OS
, (TSTR("yaffs_mkdir\n")));
1777 retVal
= yaffs_mknod(dir
, dentry
, mode
| S_IFDIR
, 0);
1781 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1782 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1783 struct nameidata
*n
)
1785 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1788 T(YAFFS_TRACE_OS
,(TSTR("yaffs_create\n")));
1789 return yaffs_mknod(dir
, dentry
, mode
| S_IFREG
, 0);
1792 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
)
1800 (TSTR("yaffs_unlink %d:%s\n"),
1802 dentry
->d_name
.name
));
1803 obj
= yaffs_InodeToObject(dir
);
1806 yaffs_gross_lock(dev
);
1808 retVal
= yaffs_unlinker(obj
, dentry
->d_name
.name
);
1810 if (retVal
== YAFFS_OK
) {
1811 dentry
->d_inode
->i_nlink
--;
1813 yaffs_gross_unlock(dev
);
1814 mark_inode_dirty(dentry
->d_inode
);
1815 update_dir_time(dir
);
1818 yaffs_gross_unlock(dev
);
1825 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
1826 struct dentry
*dentry
)
1828 struct inode
*inode
= old_dentry
->d_inode
;
1829 yaffs_obj_t
*obj
= NULL
;
1830 yaffs_obj_t
*link
= NULL
;
1833 T(YAFFS_TRACE_OS
, (TSTR("yaffs_link\n")));
1835 obj
= yaffs_InodeToObject(inode
);
1838 yaffs_gross_lock(dev
);
1840 if (!S_ISDIR(inode
->i_mode
)) /* Don't link directories */
1841 link
= yaffs_link_obj(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1845 old_dentry
->d_inode
->i_nlink
= yaffs_get_obj_link_count(obj
);
1846 d_instantiate(dentry
, old_dentry
->d_inode
);
1847 atomic_inc(&old_dentry
->d_inode
->i_count
);
1849 (TSTR("yaffs_link link count %d i_count %d\n"),
1850 old_dentry
->d_inode
->i_nlink
,
1851 atomic_read(&old_dentry
->d_inode
->i_count
)));
1854 yaffs_gross_unlock(dev
);
1857 update_dir_time(dir
);
1864 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
1865 const char *symname
)
1869 uid_t uid
= YCRED(current
)->fsuid
;
1870 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: YCRED(current
)->fsgid
;
1872 T(YAFFS_TRACE_OS
, (TSTR("yaffs_symlink\n")));
1874 dev
= yaffs_InodeToObject(dir
)->my_dev
;
1875 yaffs_gross_lock(dev
);
1876 obj
= yaffs_create_symlink(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1877 S_IFLNK
| S_IRWXUGO
, uid
, gid
, symname
);
1878 yaffs_gross_unlock(dev
);
1881 struct inode
*inode
;
1883 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1884 d_instantiate(dentry
, inode
);
1885 update_dir_time(dir
);
1886 T(YAFFS_TRACE_OS
, (TSTR("symlink created OK\n")));
1889 T(YAFFS_TRACE_OS
, (TSTR("symlink not created\n")));
1895 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
1896 static int yaffs_sync_object(struct file
*file
, int datasync
)
1898 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
1905 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
1906 struct dentry
*dentry
= file
->f_path
.dentry
;
1909 obj
= yaffs_dentry_to_obj(dentry
);
1913 T(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
,
1914 (TSTR("yaffs_sync_object\n")));
1915 yaffs_gross_lock(dev
);
1916 yaffs_flush_file(obj
, 1, datasync
);
1917 yaffs_gross_unlock(dev
);
1922 * The VFS layer already does all the dentry stuff for rename.
1924 * NB: POSIX says you can rename an object over an old object of the same name
1926 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1927 struct inode
*new_dir
, struct dentry
*new_dentry
)
1930 int retVal
= YAFFS_FAIL
;
1931 yaffs_obj_t
*target
;
1933 T(YAFFS_TRACE_OS
, (TSTR("yaffs_rename\n")));
1934 dev
= yaffs_InodeToObject(old_dir
)->my_dev
;
1936 yaffs_gross_lock(dev
);
1938 /* Check if the target is an existing directory that is not empty. */
1939 target
= yaffs_find_by_name(yaffs_InodeToObject(new_dir
),
1940 new_dentry
->d_name
.name
);
1944 if (target
&& target
->variant_type
== YAFFS_OBJECT_TYPE_DIRECTORY
&&
1945 !ylist_empty(&target
->variant
.dir_variant
.children
)) {
1947 T(YAFFS_TRACE_OS
, (TSTR("target is non-empty dir\n")));
1949 retVal
= YAFFS_FAIL
;
1951 /* Now does unlinking internally using shadowing mechanism */
1952 T(YAFFS_TRACE_OS
, (TSTR("calling yaffs_rename_obj\n")));
1954 retVal
= yaffs_rename_obj(yaffs_InodeToObject(old_dir
),
1955 old_dentry
->d_name
.name
,
1956 yaffs_InodeToObject(new_dir
),
1957 new_dentry
->d_name
.name
);
1959 yaffs_gross_unlock(dev
);
1961 if (retVal
== YAFFS_OK
) {
1963 new_dentry
->d_inode
->i_nlink
--;
1964 mark_inode_dirty(new_dentry
->d_inode
);
1967 update_dir_time(old_dir
);
1968 if(old_dir
!= new_dir
)
1969 update_dir_time(new_dir
);
1976 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
)
1978 struct inode
*inode
= dentry
->d_inode
;
1983 (TSTR("yaffs_setattr of object %d\n"),
1984 yaffs_InodeToObject(inode
)->obj_id
));
1986 /* Fail if a requested resize >= 2GB */
1987 if (attr
->ia_valid
& ATTR_SIZE
&&
1988 (attr
->ia_size
>> 31))
1992 error
= inode_change_ok(inode
, attr
);
1996 error
= yaffs_vfs_setattr(inode
, attr
);
1997 T(YAFFS_TRACE_OS
,(TSTR("inode_setattr called\n")));
1998 if (attr
->ia_valid
& ATTR_SIZE
){
1999 yaffs_vfs_setsize(inode
,attr
->ia_size
);
2000 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
2003 dev
= yaffs_InodeToObject(inode
)->my_dev
;
2004 if (attr
->ia_valid
& ATTR_SIZE
){
2005 T(YAFFS_TRACE_OS
,(TSTR("resize to %d(%x)\n"),
2006 (int)(attr
->ia_size
),(int)(attr
->ia_size
)));
2008 yaffs_gross_lock(dev
);
2009 result
= yaffs_set_attribs(yaffs_InodeToObject(inode
), attr
);
2010 if(result
== YAFFS_OK
) {
2015 yaffs_gross_unlock(dev
);
2020 (TSTR("yaffs_setattr done returning %d\n"),error
));
2025 #ifdef CONFIG_YAFFS_XATTR
2026 int yaffs_setxattr(struct dentry
*dentry
, const char *name
,
2027 const void *value
, size_t size
, int flags
)
2029 struct inode
*inode
= dentry
->d_inode
;
2032 yaffs_obj_t
*obj
= yaffs_InodeToObject(inode
);
2035 (TSTR("yaffs_setxattr of object %d\n"),
2042 yaffs_gross_lock(dev
);
2043 result
= yaffs_set_xattrib(obj
, name
, value
, size
, flags
);
2044 if(result
== YAFFS_OK
)
2048 yaffs_gross_unlock(dev
);
2052 (TSTR("yaffs_setxattr done returning %d\n"),error
));
2058 ssize_t
yaffs_getxattr(struct dentry
*dentry
, const char *name
, void *buff
,
2061 struct inode
*inode
= dentry
->d_inode
;
2064 yaffs_obj_t
*obj
= yaffs_InodeToObject(inode
);
2067 (TSTR("yaffs_getxattr \"%s\" from object %d\n"),
2068 name
, obj
->obj_id
));
2072 yaffs_gross_lock(dev
);
2073 error
= yaffs_get_xattrib(obj
, name
, buff
, size
);
2074 yaffs_gross_unlock(dev
);
2078 (TSTR("yaffs_getxattr done returning %d\n"),error
));
2083 int yaffs_removexattr(struct dentry
*dentry
, const char *name
)
2085 struct inode
*inode
= dentry
->d_inode
;
2088 yaffs_obj_t
*obj
= yaffs_InodeToObject(inode
);
2091 (TSTR("yaffs_removexattr of object %d\n"),
2098 yaffs_gross_lock(dev
);
2099 result
= yaffs_remove_xattrib(obj
, name
);
2100 if(result
== YAFFS_OK
)
2104 yaffs_gross_unlock(dev
);
2108 (TSTR("yaffs_removexattr done returning %d\n"),error
));
2113 ssize_t
yaffs_listxattr(struct dentry
*dentry
, char *buff
, size_t size
)
2115 struct inode
*inode
= dentry
->d_inode
;
2118 yaffs_obj_t
*obj
= yaffs_InodeToObject(inode
);
2121 (TSTR("yaffs_listxattr of object %d\n"),
2127 yaffs_gross_lock(dev
);
2128 error
= yaffs_list_xattrib(obj
, buff
, size
);
2129 yaffs_gross_unlock(dev
);
2133 (TSTR("yaffs_listxattr done returning %d\n"),error
));
2141 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2142 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
2144 yaffs_dev_t
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
2145 struct super_block
*sb
= dentry
->d_sb
;
2146 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2147 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
)
2149 yaffs_dev_t
*dev
= yaffs_SuperToDevice(sb
);
2151 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
)
2153 yaffs_dev_t
*dev
= yaffs_SuperToDevice(sb
);
2156 T(YAFFS_TRACE_OS
, (TSTR("yaffs_statfs\n")));
2158 yaffs_gross_lock(dev
);
2160 buf
->f_type
= YAFFS_MAGIC
;
2161 buf
->f_bsize
= sb
->s_blocksize
;
2162 buf
->f_namelen
= 255;
2164 if (dev
->data_bytes_per_chunk
& (dev
->data_bytes_per_chunk
- 1)) {
2165 /* Do this if chunk size is not a power of 2 */
2167 uint64_t bytesInDev
;
2170 bytesInDev
= ((uint64_t)((dev
->param
.end_block
- dev
->param
.start_block
+ 1))) *
2171 ((uint64_t)(dev
->param
.chunks_per_block
* dev
->data_bytes_per_chunk
));
2173 do_div(bytesInDev
, sb
->s_blocksize
); /* bytesInDev becomes the number of blocks */
2174 buf
->f_blocks
= bytesInDev
;
2176 bytesFree
= ((uint64_t)(yaffs_get_n_free_chunks(dev
))) *
2177 ((uint64_t)(dev
->data_bytes_per_chunk
));
2179 do_div(bytesFree
, sb
->s_blocksize
);
2181 buf
->f_bfree
= bytesFree
;
2183 } else if (sb
->s_blocksize
> dev
->data_bytes_per_chunk
) {
2186 (dev
->param
.end_block
- dev
->param
.start_block
+ 1) *
2187 dev
->param
.chunks_per_block
/
2188 (sb
->s_blocksize
/ dev
->data_bytes_per_chunk
);
2190 yaffs_get_n_free_chunks(dev
) /
2191 (sb
->s_blocksize
/ dev
->data_bytes_per_chunk
);
2194 (dev
->param
.end_block
- dev
->param
.start_block
+ 1) *
2195 dev
->param
.chunks_per_block
*
2196 (dev
->data_bytes_per_chunk
/ sb
->s_blocksize
);
2199 yaffs_get_n_free_chunks(dev
) *
2200 (dev
->data_bytes_per_chunk
/ sb
->s_blocksize
);
2205 buf
->f_bavail
= buf
->f_bfree
;
2207 yaffs_gross_unlock(dev
);
2213 static void yaffs_flush_inodes(struct super_block
*sb
)
2218 list_for_each_entry(iptr
,&sb
->s_inodes
, i_sb_list
){
2219 obj
= yaffs_InodeToObject(iptr
);
2221 T(YAFFS_TRACE_OS
, (TSTR("flushing obj %d\n"),
2223 yaffs_flush_file(obj
,1,0);
2229 static void yaffs_flush_super(struct super_block
*sb
, int do_checkpoint
)
2231 yaffs_dev_t
*dev
= yaffs_SuperToDevice(sb
);
2235 yaffs_flush_inodes(sb
);
2236 yaffs_update_dirty_dirs(dev
);
2237 yaffs_flush_whole_cache(dev
);
2239 yaffs_checkpoint_save(dev
);
2243 static unsigned yaffs_bg_gc_urgency(yaffs_dev_t
*dev
)
2245 unsigned erasedChunks
= dev
->n_erased_blocks
* dev
->param
.chunks_per_block
;
2246 struct yaffs_LinuxContext
*context
= yaffs_dev_to_lc(dev
);
2247 unsigned scatteredFree
= 0; /* Free chunks not in an erased block */
2249 if(erasedChunks
< dev
->n_free_chunks
)
2250 scatteredFree
= (dev
->n_free_chunks
- erasedChunks
);
2252 if(!context
->bgRunning
)
2254 else if(scatteredFree
< (dev
->param
.chunks_per_block
* 2))
2256 else if(erasedChunks
> dev
->n_free_chunks
/2)
2258 else if(erasedChunks
> dev
->n_free_chunks
/4)
2264 static int yaffs_do_sync_fs(struct super_block
*sb
,
2265 int request_checkpoint
)
2268 yaffs_dev_t
*dev
= yaffs_SuperToDevice(sb
);
2269 unsigned int oneshot_checkpoint
= (yaffs_auto_checkpoint
& 4);
2270 unsigned gc_urgent
= yaffs_bg_gc_urgency(dev
);
2273 T(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
| YAFFS_TRACE_BACKGROUND
,
2274 (TSTR("yaffs_do_sync_fs: gc-urgency %d %s %s%s\n"),
2276 sb
->s_dirt
? "dirty" : "clean",
2277 request_checkpoint
? "checkpoint requested" : "no checkpoint",
2278 oneshot_checkpoint
? " one-shot" : "" ));
2280 yaffs_gross_lock(dev
);
2281 do_checkpoint
= ((request_checkpoint
&& !gc_urgent
) ||
2282 oneshot_checkpoint
) &&
2283 !dev
->is_checkpointed
;
2285 if (sb
->s_dirt
|| do_checkpoint
) {
2286 yaffs_flush_super(sb
, !dev
->is_checkpointed
&& do_checkpoint
);
2288 if(oneshot_checkpoint
)
2289 yaffs_auto_checkpoint
&= ~4;
2291 yaffs_gross_unlock(dev
);
2297 * yaffs background thread functions .
2298 * yaffs_bg_thread_fn() the thread function
2299 * yaffs_bg_start() launches the background thread.
2300 * yaffs_bg_stop() cleans up the background thread.
2303 * The thread should only run after the yaffs is initialised
2304 * The thread should be stopped before yaffs is unmounted.
2305 * The thread should not do any writing while the fs is in read only.
2308 #ifdef YAFFS_COMPILE_BACKGROUND
2310 void yaffs_background_waker(unsigned long data
)
2312 wake_up_process((struct task_struct
*)data
);
2315 static int yaffs_bg_thread_fn(void *data
)
2317 yaffs_dev_t
*dev
= (yaffs_dev_t
*)data
;
2318 struct yaffs_LinuxContext
*context
= yaffs_dev_to_lc(dev
);
2319 unsigned long now
= jiffies
;
2320 unsigned long next_dir_update
= now
;
2321 unsigned long next_gc
= now
;
2322 unsigned long expires
;
2323 unsigned int urgency
;
2326 struct timer_list timer
;
2328 T(YAFFS_TRACE_BACKGROUND
,
2329 (TSTR("yaffs_background starting for dev %p\n"),
2332 #ifdef YAFFS_COMPILE_FREEZER
2335 while(context
->bgRunning
){
2336 T(YAFFS_TRACE_BACKGROUND
,
2337 (TSTR("yaffs_background\n")));
2339 if(kthread_should_stop())
2342 #ifdef YAFFS_COMPILE_FREEZER
2346 yaffs_gross_lock(dev
);
2350 if(time_after(now
, next_dir_update
) && yaffs_bg_enable
){
2351 yaffs_update_dirty_dirs(dev
);
2352 next_dir_update
= now
+ HZ
;
2355 if(time_after(now
,next_gc
) && yaffs_bg_enable
){
2356 if(!dev
->is_checkpointed
){
2357 urgency
= yaffs_bg_gc_urgency(dev
);
2358 gcResult
= yaffs_bg_gc(dev
, urgency
);
2360 next_gc
= now
+ HZ
/20+1;
2361 else if(urgency
> 0)
2362 next_gc
= now
+ HZ
/10+1;
2364 next_gc
= now
+ HZ
* 2;
2366 * gc not running so set to next_dir_update
2367 * to cut down on wake ups
2369 next_gc
= next_dir_update
;
2371 yaffs_gross_unlock(dev
);
2373 expires
= next_dir_update
;
2374 if (time_before(next_gc
,expires
))
2376 if(time_before(expires
,now
))
2379 Y_INIT_TIMER(&timer
);
2380 timer
.expires
= expires
+1;
2381 timer
.data
= (unsigned long) current
;
2382 timer
.function
= yaffs_background_waker
;
2384 set_current_state(TASK_INTERRUPTIBLE
);
2387 del_timer_sync(&timer
);
2396 static int yaffs_bg_start(yaffs_dev_t
*dev
)
2399 struct yaffs_LinuxContext
*context
= yaffs_dev_to_lc(dev
);
2404 context
->bgRunning
= 1;
2406 context
->bgThread
= kthread_run(yaffs_bg_thread_fn
,
2407 (void *)dev
,"yaffs-bg-%d",context
->mount_id
);
2409 if(IS_ERR(context
->bgThread
)){
2410 retval
= PTR_ERR(context
->bgThread
);
2411 context
->bgThread
= NULL
;
2412 context
->bgRunning
= 0;
2417 static void yaffs_bg_stop(yaffs_dev_t
*dev
)
2419 struct yaffs_LinuxContext
*ctxt
= yaffs_dev_to_lc(dev
);
2421 ctxt
->bgRunning
= 0;
2423 if( ctxt
->bgThread
){
2424 kthread_stop(ctxt
->bgThread
);
2425 ctxt
->bgThread
= NULL
;
2429 static int yaffs_bg_thread_fn(void *data
)
2434 static int yaffs_bg_start(yaffs_dev_t
*dev
)
2439 static void yaffs_bg_stop(yaffs_dev_t
*dev
)
2445 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2446 static void yaffs_write_super(struct super_block
*sb
)
2448 static int yaffs_write_super(struct super_block
*sb
)
2451 unsigned request_checkpoint
= (yaffs_auto_checkpoint
>= 2);
2453 T(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
| YAFFS_TRACE_BACKGROUND
,
2454 (TSTR("yaffs_write_super%s\n"),
2455 request_checkpoint
? " checkpt" : ""));
2457 yaffs_do_sync_fs(sb
, request_checkpoint
);
2459 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
2465 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2466 static int yaffs_sync_fs(struct super_block
*sb
, int wait
)
2468 static int yaffs_sync_fs(struct super_block
*sb
)
2471 unsigned request_checkpoint
= (yaffs_auto_checkpoint
>= 1);
2473 T(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
,
2474 (TSTR("yaffs_sync_fs%s\n"),
2475 request_checkpoint
? " checkpt" : ""));
2477 yaffs_do_sync_fs(sb
, request_checkpoint
);
2482 #ifdef YAFFS_USE_OWN_IGET
2484 static struct inode
*yaffs_iget(struct super_block
*sb
, unsigned long ino
)
2486 struct inode
*inode
;
2488 yaffs_dev_t
*dev
= yaffs_SuperToDevice(sb
);
2491 (TSTR("yaffs_iget for %lu\n"), ino
));
2493 inode
= iget_locked(sb
, ino
);
2495 return ERR_PTR(-ENOMEM
);
2496 if (!(inode
->i_state
& I_NEW
))
2499 /* NB This is called as a side effect of other functions, but
2500 * we had to release the lock to prevent deadlocks, so
2501 * need to lock again.
2504 yaffs_gross_lock(dev
);
2506 obj
= yaffs_find_by_number(dev
, inode
->i_ino
);
2508 yaffs_fill_inode_from_obj(inode
, obj
);
2510 yaffs_gross_unlock(dev
);
2512 unlock_new_inode(inode
);
2518 static void yaffs_read_inode(struct inode
*inode
)
2520 /* NB This is called as a side effect of other functions, but
2521 * we had to release the lock to prevent deadlocks, so
2522 * need to lock again.
2526 yaffs_dev_t
*dev
= yaffs_SuperToDevice(inode
->i_sb
);
2529 (TSTR("yaffs_read_inode for %d\n"), (int)inode
->i_ino
));
2531 if(current
!= yaffs_dev_to_lc(dev
)->readdirProcess
)
2532 yaffs_gross_lock(dev
);
2534 obj
= yaffs_find_by_number(dev
, inode
->i_ino
);
2536 yaffs_fill_inode_from_obj(inode
, obj
);
2538 if(current
!= yaffs_dev_to_lc(dev
)->readdirProcess
)
2539 yaffs_gross_unlock(dev
);
2544 static YLIST_HEAD(yaffs_context_list
);
2545 struct semaphore yaffs_context_lock
;
2547 static void yaffs_put_super(struct super_block
*sb
)
2549 yaffs_dev_t
*dev
= yaffs_SuperToDevice(sb
);
2551 T(YAFFS_TRACE_OS
, (TSTR("yaffs_put_super\n")));
2553 T(YAFFS_TRACE_OS
| YAFFS_TRACE_BACKGROUND
,
2554 (TSTR("Shutting down yaffs background thread\n")));
2556 T(YAFFS_TRACE_OS
| YAFFS_TRACE_BACKGROUND
,
2557 (TSTR("yaffs background thread shut down\n")));
2559 yaffs_gross_lock(dev
);
2561 yaffs_flush_super(sb
,1);
2563 if (yaffs_dev_to_lc(dev
)->putSuperFunc
)
2564 yaffs_dev_to_lc(dev
)->putSuperFunc(sb
);
2567 yaffs_deinitialise(dev
);
2569 yaffs_gross_unlock(dev
);
2571 down(&yaffs_context_lock
);
2572 ylist_del_init(&(yaffs_dev_to_lc(dev
)->contextList
));
2573 up(&yaffs_context_lock
);
2575 if (yaffs_dev_to_lc(dev
)->spareBuffer
) {
2576 YFREE(yaffs_dev_to_lc(dev
)->spareBuffer
);
2577 yaffs_dev_to_lc(dev
)->spareBuffer
= NULL
;
2584 static void yaffs_MTDPutSuper(struct super_block
*sb
)
2586 struct mtd_info
*mtd
= yaffs_dev_to_mtd(yaffs_SuperToDevice(sb
));
2591 put_mtd_device(mtd
);
2595 static void yaffs_touch_super(yaffs_dev_t
*dev
)
2597 struct super_block
*sb
= yaffs_dev_to_lc(dev
)->superBlock
;
2599 T(YAFFS_TRACE_OS
, (TSTR("yaffs_touch_super() sb = %p\n"), sb
));
2606 int skip_checkpoint_read
;
2607 int skip_checkpoint_write
;
2610 int tags_ecc_overridden
;
2611 int lazy_loading_enabled
;
2612 int lazy_loading_overridden
;
2613 int empty_lost_and_found
;
2614 int empty_lost_and_found_overridden
;
2617 #define MAX_OPT_LEN 30
2618 static int yaffs_parse_options(yaffs_options
*options
, const char *options_str
)
2620 char cur_opt
[MAX_OPT_LEN
+ 1];
2624 /* Parse through the options which is a comma seperated list */
2626 while (options_str
&& *options_str
&& !error
) {
2627 memset(cur_opt
, 0, MAX_OPT_LEN
+ 1);
2630 while(*options_str
== ',')
2633 while (*options_str
&& *options_str
!= ',') {
2634 if (p
< MAX_OPT_LEN
) {
2635 cur_opt
[p
] = *options_str
;
2641 if (!strcmp(cur_opt
, "inband-tags"))
2642 options
->inband_tags
= 1;
2643 else if (!strcmp(cur_opt
, "tags-ecc-off")){
2644 options
->tags_ecc_on
= 0;
2645 options
->tags_ecc_overridden
=1;
2646 } else if (!strcmp(cur_opt
, "tags-ecc-on")){
2647 options
->tags_ecc_on
= 1;
2648 options
->tags_ecc_overridden
= 1;
2649 } else if (!strcmp(cur_opt
, "lazy-loading-off")){
2650 options
->lazy_loading_enabled
= 0;
2651 options
->lazy_loading_overridden
=1;
2652 } else if (!strcmp(cur_opt
, "lazy-loading-on")){
2653 options
->lazy_loading_enabled
= 1;
2654 options
->lazy_loading_overridden
= 1;
2655 } else if (!strcmp(cur_opt
, "empty-lost-and-found-off")){
2656 options
->empty_lost_and_found
= 0;
2657 options
->empty_lost_and_found_overridden
=1;
2658 } else if (!strcmp(cur_opt
, "empty-lost-and-found-on")){
2659 options
->empty_lost_and_found
= 1;
2660 options
->empty_lost_and_found_overridden
=1;
2661 } else if (!strcmp(cur_opt
, "no-cache"))
2662 options
->no_cache
= 1;
2663 else if (!strcmp(cur_opt
, "no-checkpoint-read"))
2664 options
->skip_checkpoint_read
= 1;
2665 else if (!strcmp(cur_opt
, "no-checkpoint-write"))
2666 options
->skip_checkpoint_write
= 1;
2667 else if (!strcmp(cur_opt
, "no-checkpoint")) {
2668 options
->skip_checkpoint_read
= 1;
2669 options
->skip_checkpoint_write
= 1;
2671 printk(KERN_INFO
"yaffs: Bad mount option \"%s\"\n",
2680 static struct super_block
*yaffs_internal_read_super(int yaffs_version
,
2681 struct super_block
*sb
,
2682 void *data
, int silent
)
2685 struct inode
*inode
= NULL
;
2686 struct dentry
*root
;
2687 yaffs_dev_t
*dev
= 0;
2688 char devname_buf
[BDEVNAME_SIZE
+ 1];
2689 struct mtd_info
*mtd
;
2691 char *data_str
= (char *)data
;
2692 struct yaffs_LinuxContext
*context
= NULL
;
2693 yaffs_param_t
*param
;
2697 yaffs_options options
;
2701 struct yaffs_LinuxContext
*context_iterator
;
2702 struct ylist_head
*l
;
2704 sb
->s_magic
= YAFFS_MAGIC
;
2705 sb
->s_op
= &yaffs_super_ops
;
2706 sb
->s_flags
|= MS_NOATIME
;
2708 read_only
=((sb
->s_flags
& MS_RDONLY
) != 0);
2711 #ifdef YAFFS_COMPILE_EXPORTFS
2712 sb
->s_export_op
= &yaffs_export_ops
;
2716 printk(KERN_INFO
"yaffs: sb is NULL\n");
2717 else if (!sb
->s_dev
)
2718 printk(KERN_INFO
"yaffs: sb->s_dev is NULL\n");
2719 else if (!yaffs_devname(sb
, devname_buf
))
2720 printk(KERN_INFO
"yaffs: devname is NULL\n");
2722 printk(KERN_INFO
"yaffs: dev is %d name is \"%s\" %s\n",
2724 yaffs_devname(sb
, devname_buf
),
2725 read_only
? "ro" : "rw");
2730 printk(KERN_INFO
"yaffs: passed flags \"%s\"\n", data_str
);
2732 memset(&options
, 0, sizeof(options
));
2734 if (yaffs_parse_options(&options
, data_str
)) {
2735 /* Option parsing failed */
2740 sb
->s_blocksize
= PAGE_CACHE_SIZE
;
2741 sb
->s_blocksize_bits
= PAGE_CACHE_SHIFT
;
2744 (TSTR("yaffs_read_super: Using yaffs%d\n"), yaffs_version
));
2746 (TSTR("yaffs_read_super: block size %d\n"),
2747 (int)(sb
->s_blocksize
)));
2749 T(YAFFS_TRACE_ALWAYS
,
2750 (TSTR("yaffs: Attempting MTD mount of %u.%u,\"%s\"\n"),
2751 MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
),
2752 yaffs_devname(sb
, devname_buf
)));
2754 /* Check it's an mtd device..... */
2755 if (MAJOR(sb
->s_dev
) != MTD_BLOCK_MAJOR
)
2756 return NULL
; /* This isn't an mtd device */
2758 /* Get the device */
2759 mtd
= get_mtd_device(NULL
, MINOR(sb
->s_dev
));
2761 T(YAFFS_TRACE_ALWAYS
,
2762 (TSTR("yaffs: MTD device #%u doesn't appear to exist\n"),
2766 /* Check it's NAND */
2767 if (mtd
->type
!= MTD_NANDFLASH
) {
2768 T(YAFFS_TRACE_ALWAYS
,
2769 (TSTR("yaffs: MTD device is not NAND it's type %d\n"),
2774 T(YAFFS_TRACE_OS
, (TSTR(" erase %p\n"), mtd
->erase
));
2775 T(YAFFS_TRACE_OS
, (TSTR(" read %p\n"), mtd
->read
));
2776 T(YAFFS_TRACE_OS
, (TSTR(" write %p\n"), mtd
->write
));
2777 T(YAFFS_TRACE_OS
, (TSTR(" readoob %p\n"), mtd
->read_oob
));
2778 T(YAFFS_TRACE_OS
, (TSTR(" writeoob %p\n"), mtd
->write_oob
));
2779 T(YAFFS_TRACE_OS
, (TSTR(" block_isbad %p\n"), mtd
->block_isbad
));
2780 T(YAFFS_TRACE_OS
, (TSTR(" block_markbad %p\n"), mtd
->block_markbad
));
2781 T(YAFFS_TRACE_OS
, (TSTR(" %s %d\n"), WRITE_SIZE_STR
, WRITE_SIZE(mtd
)));
2782 T(YAFFS_TRACE_OS
, (TSTR(" oobsize %d\n"), mtd
->oobsize
));
2783 T(YAFFS_TRACE_OS
, (TSTR(" erasesize %d\n"), mtd
->erasesize
));
2784 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
2785 T(YAFFS_TRACE_OS
, (TSTR(" size %u\n"), mtd
->size
));
2787 T(YAFFS_TRACE_OS
, (TSTR(" size %lld\n"), mtd
->size
));
2790 #ifdef CONFIG_YAFFS_AUTO_YAFFS2
2792 if (yaffs_version
== 1 && WRITE_SIZE(mtd
) >= 2048) {
2793 T(YAFFS_TRACE_ALWAYS
,
2794 (TSTR("yaffs: auto selecting yaffs2\n")));
2798 /* Added NCB 26/5/2006 for completeness */
2799 if (yaffs_version
== 2 && !options
.inband_tags
&& WRITE_SIZE(mtd
) == 512) {
2800 T(YAFFS_TRACE_ALWAYS
,
2801 (TSTR("yaffs: auto selecting yaffs1\n")));
2807 if (yaffs_version
== 2) {
2808 /* Check for version 2 style functions */
2810 !mtd
->block_isbad
||
2811 !mtd
->block_markbad
||
2814 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2815 !mtd
->read_oob
|| !mtd
->write_oob
) {
2818 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
2820 T(YAFFS_TRACE_ALWAYS
,
2821 (TSTR("yaffs: MTD device does not support required "
2826 if ((WRITE_SIZE(mtd
) < YAFFS_MIN_YAFFS2_CHUNK_SIZE
||
2827 mtd
->oobsize
< YAFFS_MIN_YAFFS2_SPARE_SIZE
) &&
2828 !options
.inband_tags
) {
2829 T(YAFFS_TRACE_ALWAYS
,
2830 (TSTR("yaffs: MTD device does not have the "
2831 "right page sizes\n")));
2835 /* Check for V1 style functions */
2839 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2840 !mtd
->read_oob
|| !mtd
->write_oob
) {
2843 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
2845 T(YAFFS_TRACE_ALWAYS
,
2846 (TSTR("yaffs: MTD device does not support required "
2851 if (WRITE_SIZE(mtd
) < YAFFS_BYTES_PER_CHUNK
||
2852 mtd
->oobsize
!= YAFFS_BYTES_PER_SPARE
) {
2853 T(YAFFS_TRACE_ALWAYS
,
2854 (TSTR("yaffs: MTD device does not support have the "
2855 "right page sizes\n")));
2860 /* OK, so if we got here, we have an MTD that's NAND and looks
2861 * like it has the right capabilities
2862 * Set the yaffs_dev_t up for mtd
2865 if (!read_only
&& !(mtd
->flags
& MTD_WRITEABLE
)){
2867 printk(KERN_INFO
"yaffs: mtd is read only, setting superblock read only");
2868 sb
->s_flags
|= MS_RDONLY
;
2871 dev
= kmalloc(sizeof(yaffs_dev_t
), GFP_KERNEL
);
2872 context
= kmalloc(sizeof(struct yaffs_LinuxContext
),GFP_KERNEL
);
2874 if(!dev
|| !context
){
2884 /* Deep shit could not allocate device structure */
2885 T(YAFFS_TRACE_ALWAYS
,
2886 (TSTR("yaffs_read_super: Failed trying to allocate "
2887 "yaffs_dev_t. \n")));
2890 memset(dev
, 0, sizeof(yaffs_dev_t
));
2891 param
= &(dev
->param
);
2893 memset(context
,0,sizeof(struct yaffs_LinuxContext
));
2894 dev
->os_context
= context
;
2895 YINIT_LIST_HEAD(&(context
->contextList
));
2897 context
->superBlock
= sb
;
2899 dev
->read_only
= read_only
;
2901 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2902 sb
->s_fs_info
= dev
;
2904 sb
->u
.generic_sbp
= dev
;
2907 dev
->driver_context
= mtd
;
2908 param
->name
= mtd
->name
;
2910 /* Set up the memory size parameters.... */
2912 nBlocks
= YCALCBLOCKS(mtd
->size
, (YAFFS_CHUNKS_PER_BLOCK
* YAFFS_BYTES_PER_CHUNK
));
2914 param
->start_block
= 0;
2915 param
->end_block
= nBlocks
- 1;
2916 param
->chunks_per_block
= YAFFS_CHUNKS_PER_BLOCK
;
2917 param
->total_bytes_per_chunk
= YAFFS_BYTES_PER_CHUNK
;
2918 param
->n_reserved_blocks
= 5;
2919 param
->n_caches
= (options
.no_cache
) ? 0 : 10;
2920 param
->inband_tags
= options
.inband_tags
;
2922 #ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
2923 param
->disable_lazy_load
= 1;
2925 #ifdef CONFIG_YAFFS_XATTR
2926 param
->enable_xattr
= 1;
2928 if(options
.lazy_loading_overridden
)
2929 param
->disable_lazy_load
= !options
.lazy_loading_enabled
;
2931 #ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC
2932 param
->no_tags_ecc
= 1;
2935 #ifdef CONFIG_YAFFS_DISABLE_BACKGROUND
2937 param
->defered_dir_update
= 1;
2940 if(options
.tags_ecc_overridden
)
2941 param
->no_tags_ecc
= !options
.tags_ecc_on
;
2943 #ifdef CONFIG_YAFFS_EMPTY_LOST_AND_FOUND
2944 param
->empty_lost_n_found
= 1;
2947 #ifdef CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING
2948 param
->refresh_period
= 0;
2950 param
->refresh_period
= 500;
2953 #ifdef CONFIG_YAFFS__ALWAYS_CHECK_CHUNK_ERASED
2954 param
->always_check_erased
= 1;
2957 if(options
.empty_lost_and_found_overridden
)
2958 param
->empty_lost_n_found
= options
.empty_lost_and_found
;
2960 /* ... and the functions. */
2961 if (yaffs_version
== 2) {
2962 param
->write_chunk_tags_fn
=
2963 nandmtd2_WriteChunkWithTagsToNAND
;
2964 param
->read_chunk_tags_fn
=
2965 nandmtd2_ReadChunkWithTagsFromNAND
;
2966 param
->bad_block_fn
= nandmtd2_MarkNANDBlockBad
;
2967 param
->query_block_fn
= nandmtd2_QueryNANDBlock
;
2968 yaffs_dev_to_lc(dev
)->spareBuffer
= YMALLOC(mtd
->oobsize
);
2969 param
->is_yaffs2
= 1;
2970 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2971 param
->total_bytes_per_chunk
= mtd
->writesize
;
2972 param
->chunks_per_block
= mtd
->erasesize
/ mtd
->writesize
;
2974 param
->total_bytes_per_chunk
= mtd
->oobblock
;
2975 param
->chunks_per_block
= mtd
->erasesize
/ mtd
->oobblock
;
2977 nBlocks
= YCALCBLOCKS(mtd
->size
, mtd
->erasesize
);
2979 param
->start_block
= 0;
2980 param
->end_block
= nBlocks
- 1;
2982 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2983 /* use the MTD interface in yaffs_mtdif1.c */
2984 param
->write_chunk_tags_fn
=
2985 nandmtd1_WriteChunkWithTagsToNAND
;
2986 param
->read_chunk_tags_fn
=
2987 nandmtd1_ReadChunkWithTagsFromNAND
;
2988 param
->bad_block_fn
= nandmtd1_MarkNANDBlockBad
;
2989 param
->query_block_fn
= nandmtd1_QueryNANDBlock
;
2991 param
->write_chunk_fn
= nandmtd_WriteChunkToNAND
;
2992 param
->read_chunk_fn
= nandmtd_ReadChunkFromNAND
;
2994 param
->is_yaffs2
= 0;
2996 /* ... and common functions */
2997 param
->erase_fn
= nandmtd_EraseBlockInNAND
;
2998 param
->initialise_flash_fn
= nandmtd_InitialiseNAND
;
3000 yaffs_dev_to_lc(dev
)->putSuperFunc
= yaffs_MTDPutSuper
;
3002 param
->sb_dirty_fn
= yaffs_touch_super
;
3003 param
->gc_control
= yaffs_gc_control_callback
;
3005 yaffs_dev_to_lc(dev
)->superBlock
= sb
;
3008 #ifndef CONFIG_YAFFS_DOES_ECC
3009 param
->use_nand_ecc
= 1;
3012 #ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
3013 param
->wide_tnodes_disabled
= 1;
3016 param
->skip_checkpt_rd
= options
.skip_checkpoint_read
;
3017 param
->skip_checkpt_wr
= options
.skip_checkpoint_write
;
3019 down(&yaffs_context_lock
);
3020 /* Get a mount id */
3022 for(mount_id
=0; ! found
; mount_id
++){
3024 ylist_for_each(l
,&yaffs_context_list
){
3025 context_iterator
= ylist_entry(l
,struct yaffs_LinuxContext
,contextList
);
3026 if(context_iterator
->mount_id
== mount_id
)
3030 context
->mount_id
= mount_id
;
3032 ylist_add_tail(&(yaffs_dev_to_lc(dev
)->contextList
), &yaffs_context_list
);
3033 up(&yaffs_context_lock
);
3035 /* Directory search handling...*/
3036 YINIT_LIST_HEAD(&(yaffs_dev_to_lc(dev
)->searchContexts
));
3037 param
->remove_obj_fn
= yaffs_remove_obj_callback
;
3039 init_MUTEX(&(yaffs_dev_to_lc(dev
)->grossLock
));
3041 yaffs_gross_lock(dev
);
3043 err
= yaffs_guts_initialise(dev
);
3046 (TSTR("yaffs_read_super: guts initialised %s\n"),
3047 (err
== YAFFS_OK
) ? "OK" : "FAILED"));
3050 yaffs_bg_start(dev
);
3052 if(!context
->bgThread
)
3053 param
->defered_dir_update
= 0;
3056 /* Release lock before yaffs_get_inode() */
3057 yaffs_gross_unlock(dev
);
3059 /* Create root inode */
3060 if (err
== YAFFS_OK
)
3061 inode
= yaffs_get_inode(sb
, S_IFDIR
| 0755, 0,
3067 inode
->i_op
= &yaffs_dir_inode_operations
;
3068 inode
->i_fop
= &yaffs_dir_operations
;
3070 T(YAFFS_TRACE_OS
, (TSTR("yaffs_read_super: got root inode\n")));
3072 root
= d_alloc_root(inode
);
3074 T(YAFFS_TRACE_OS
, (TSTR("yaffs_read_super: d_alloc_root done\n")));
3081 sb
->s_dirt
= !dev
->is_checkpointed
;
3082 T(YAFFS_TRACE_ALWAYS
,
3083 (TSTR("yaffs_read_super: is_checkpointed %d\n"),
3084 dev
->is_checkpointed
));
3086 T(YAFFS_TRACE_OS
, (TSTR("yaffs_read_super: done\n")));
3091 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
3092 static int yaffs_internal_read_super_mtd(struct super_block
*sb
, void *data
,
3095 return yaffs_internal_read_super(1, sb
, data
, silent
) ? 0 : -EINVAL
;
3098 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3099 static int yaffs_read_super(struct file_system_type
*fs
,
3100 int flags
, const char *dev_name
,
3101 void *data
, struct vfsmount
*mnt
)
3104 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3105 yaffs_internal_read_super_mtd
, mnt
);
3108 static struct super_block
*yaffs_read_super(struct file_system_type
*fs
,
3109 int flags
, const char *dev_name
,
3113 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3114 yaffs_internal_read_super_mtd
);
3118 static struct file_system_type yaffs_fs_type
= {
3119 .owner
= THIS_MODULE
,
3121 .get_sb
= yaffs_read_super
,
3122 .kill_sb
= kill_block_super
,
3123 .fs_flags
= FS_REQUIRES_DEV
,
3126 static struct super_block
*yaffs_read_super(struct super_block
*sb
, void *data
,
3129 return yaffs_internal_read_super(1, sb
, data
, silent
);
3132 static DECLARE_FSTYPE(yaffs_fs_type
, "yaffs", yaffs_read_super
,
3137 #ifdef CONFIG_YAFFS_YAFFS2
3139 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
3140 static int yaffs2_internal_read_super_mtd(struct super_block
*sb
, void *data
,
3143 return yaffs_internal_read_super(2, sb
, data
, silent
) ? 0 : -EINVAL
;
3146 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3147 static int yaffs2_read_super(struct file_system_type
*fs
,
3148 int flags
, const char *dev_name
, void *data
,
3149 struct vfsmount
*mnt
)
3151 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3152 yaffs2_internal_read_super_mtd
, mnt
);
3155 static struct super_block
*yaffs2_read_super(struct file_system_type
*fs
,
3156 int flags
, const char *dev_name
,
3160 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3161 yaffs2_internal_read_super_mtd
);
3165 static struct file_system_type yaffs2_fs_type
= {
3166 .owner
= THIS_MODULE
,
3168 .get_sb
= yaffs2_read_super
,
3169 .kill_sb
= kill_block_super
,
3170 .fs_flags
= FS_REQUIRES_DEV
,
3173 static struct super_block
*yaffs2_read_super(struct super_block
*sb
,
3174 void *data
, int silent
)
3176 return yaffs_internal_read_super(2, sb
, data
, silent
);
3179 static DECLARE_FSTYPE(yaffs2_fs_type
, "yaffs2", yaffs2_read_super
,
3183 #endif /* CONFIG_YAFFS_YAFFS2 */
3185 static struct proc_dir_entry
*my_proc_entry
;
3186 static struct proc_dir_entry
*debug_proc_entry
;
3188 static char *yaffs_dump_dev_part0(char *buf
, yaffs_dev_t
* dev
)
3190 buf
+= sprintf(buf
, "start_block.......... %d\n", dev
->param
.start_block
);
3191 buf
+= sprintf(buf
, "end_block............ %d\n", dev
->param
.end_block
);
3192 buf
+= sprintf(buf
, "total_bytes_per_chunk %d\n", dev
->param
.total_bytes_per_chunk
);
3193 buf
+= sprintf(buf
, "use_nand_ecc......... %d\n", dev
->param
.use_nand_ecc
);
3194 buf
+= sprintf(buf
, "no_tags_ecc.......... %d\n", dev
->param
.no_tags_ecc
);
3195 buf
+= sprintf(buf
, "is_yaffs2............ %d\n", dev
->param
.is_yaffs2
);
3196 buf
+= sprintf(buf
, "inband_tags.......... %d\n", dev
->param
.inband_tags
);
3197 buf
+= sprintf(buf
, "empty_lost_n_found... %d\n", dev
->param
.empty_lost_n_found
);
3198 buf
+= sprintf(buf
, "disable_lazy_load.... %d\n", dev
->param
.disable_lazy_load
);
3199 buf
+= sprintf(buf
, "refresh_period....... %d\n", dev
->param
.refresh_period
);
3200 buf
+= sprintf(buf
, "n_caches............. %d\n", dev
->param
.n_caches
);
3201 buf
+= sprintf(buf
, "n_reserved_blocks.... %d\n", dev
->param
.n_reserved_blocks
);
3202 buf
+= sprintf(buf
, "always_check_erased.. %d\n", dev
->param
.always_check_erased
);
3204 buf
+= sprintf(buf
, "\n");
3210 static char *yaffs_dump_dev_part1(char *buf
, yaffs_dev_t
* dev
)
3212 buf
+= sprintf(buf
, "data_bytes_per_chunk. %d\n", dev
->data_bytes_per_chunk
);
3213 buf
+= sprintf(buf
, "chunk_grp_bits....... %d\n", dev
->chunk_grp_bits
);
3214 buf
+= sprintf(buf
, "chunk_grp_size....... %d\n", dev
->chunk_grp_size
);
3215 buf
+= sprintf(buf
, "n_erased_blocks...... %d\n", dev
->n_erased_blocks
);
3216 buf
+= sprintf(buf
, "blocks_in_checkpt.... %d\n", dev
->blocks_in_checkpt
);
3217 buf
+= sprintf(buf
, "\n");
3218 buf
+= sprintf(buf
, "n_tnodes............. %d\n", dev
->n_tnodes
);
3219 buf
+= sprintf(buf
, "n_obj................ %d\n", dev
->n_obj
);
3220 buf
+= sprintf(buf
, "n_free_chunks........ %d\n", dev
->n_free_chunks
);
3221 buf
+= sprintf(buf
, "\n");
3222 buf
+= sprintf(buf
, "n_page_writes........ %u\n", dev
->n_page_writes
);
3223 buf
+= sprintf(buf
, "n_page_reads......... %u\n", dev
->n_page_reads
);
3224 buf
+= sprintf(buf
, "n_erasures........... %u\n", dev
->n_erasures
);
3225 buf
+= sprintf(buf
, "n_gc_copies.......... %u\n", dev
->n_gc_copies
);
3226 buf
+= sprintf(buf
, "all_gcs.............. %u\n", dev
->all_gcs
);
3227 buf
+= sprintf(buf
, "passive_gc_count..... %u\n", dev
->passive_gc_count
);
3228 buf
+= sprintf(buf
, "oldest_dirty_gc_count %u\n", dev
->oldest_dirty_gc_count
);
3229 buf
+= sprintf(buf
, "n_gc_blocks.......... %u\n", dev
->n_gc_blocks
);
3230 buf
+= sprintf(buf
, "bg_gcs............... %u\n", dev
->bg_gcs
);
3231 buf
+= sprintf(buf
, "n_retired_writes..... %u\n", dev
->n_retired_writes
);
3232 buf
+= sprintf(buf
, "nRetireBlocks........ %u\n", dev
->n_retired_blocks
);
3233 buf
+= sprintf(buf
, "n_ecc_fixed.......... %u\n", dev
->n_ecc_fixed
);
3234 buf
+= sprintf(buf
, "n_ecc_unfixed........ %u\n", dev
->n_ecc_unfixed
);
3235 buf
+= sprintf(buf
, "n_tags_ecc_fixed..... %u\n", dev
->n_tags_ecc_fixed
);
3236 buf
+= sprintf(buf
, "n_tags_ecc_unfixed... %u\n", dev
->n_tags_ecc_unfixed
);
3237 buf
+= sprintf(buf
, "cache_hits........... %u\n", dev
->cache_hits
);
3238 buf
+= sprintf(buf
, "n_deleted_files...... %u\n", dev
->n_deleted_files
);
3239 buf
+= sprintf(buf
, "n_unlinked_files..... %u\n", dev
->n_unlinked_files
);
3240 buf
+= sprintf(buf
, "refresh_count........ %u\n", dev
->refresh_count
);
3241 buf
+= sprintf(buf
, "n_bg_deletions....... %u\n", dev
->n_bg_deletions
);
3246 static int yaffs_proc_read(char *page
,
3248 off_t offset
, int count
, int *eof
, void *data
)
3250 struct ylist_head
*item
;
3255 /* Get proc_file_read() to step 'offset' by one on each sucessive call.
3256 * We use 'offset' (*ppos) to indicate where we are in dev_list.
3257 * This also assumes the user has posted a read buffer large
3258 * enough to hold the complete output; but that's life in /proc.
3263 /* Print header first */
3265 buf
+= sprintf(buf
, "Multi-version YAFFS built:" __DATE__
" " __TIME__
"\n");
3267 buf
+= sprintf(buf
,"\n");
3271 down(&yaffs_context_lock
);
3273 /* Locate and print the Nth entry. Order N-squared but N is small. */
3274 ylist_for_each(item
, &yaffs_context_list
) {
3275 struct yaffs_LinuxContext
*dc
= ylist_entry(item
, struct yaffs_LinuxContext
, contextList
);
3276 yaffs_dev_t
*dev
= dc
->dev
;
3278 if (n
< (step
& ~1)) {
3283 buf
+= sprintf(buf
, "\nDevice %d \"%s\"\n", n
, dev
->param
.name
);
3284 buf
= yaffs_dump_dev_part0(buf
, dev
);
3286 buf
= yaffs_dump_dev_part1(buf
, dev
);
3290 up(&yaffs_context_lock
);
3293 return buf
- page
< count
? buf
- page
: count
;
3296 static int yaffs_stats_proc_read(char *page
,
3298 off_t offset
, int count
, int *eof
, void *data
)
3300 struct ylist_head
*item
;
3304 down(&yaffs_context_lock
);
3306 /* Locate and print the Nth entry. Order N-squared but N is small. */
3307 ylist_for_each(item
, &yaffs_context_list
) {
3308 struct yaffs_LinuxContext
*dc
= ylist_entry(item
, struct yaffs_LinuxContext
, contextList
);
3309 yaffs_dev_t
*dev
= dc
->dev
;
3313 erasedChunks
= dev
->n_erased_blocks
* dev
->param
.chunks_per_block
;
3315 buf
+= sprintf(buf
,"%d, %d, %d, %u, %u, %u, %u\n",
3316 n
, dev
->n_free_chunks
, erasedChunks
,
3317 dev
->bg_gcs
, dev
->oldest_dirty_gc_count
,
3318 dev
->n_obj
, dev
->n_tnodes
);
3320 up(&yaffs_context_lock
);
3323 return buf
- page
< count
? buf
- page
: count
;
3327 * Set the verbosity of the warnings and error messages.
3329 * Note that the names can only be a..z or _ with the current code.
3334 unsigned mask_bitfield
;
3336 {"allocate", YAFFS_TRACE_ALLOCATE
},
3337 {"always", YAFFS_TRACE_ALWAYS
},
3338 {"background", YAFFS_TRACE_BACKGROUND
},
3339 {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS
},
3340 {"buffers", YAFFS_TRACE_BUFFERS
},
3341 {"bug", YAFFS_TRACE_BUG
},
3342 {"checkpt", YAFFS_TRACE_CHECKPOINT
},
3343 {"deletion", YAFFS_TRACE_DELETION
},
3344 {"erase", YAFFS_TRACE_ERASE
},
3345 {"error", YAFFS_TRACE_ERROR
},
3346 {"gc_detail", YAFFS_TRACE_GC_DETAIL
},
3347 {"gc", YAFFS_TRACE_GC
},
3348 {"lock", YAFFS_TRACE_LOCK
},
3349 {"mtd", YAFFS_TRACE_MTD
},
3350 {"nandaccess", YAFFS_TRACE_NANDACCESS
},
3351 {"os", YAFFS_TRACE_OS
},
3352 {"scan_debug", YAFFS_TRACE_SCAN_DEBUG
},
3353 {"scan", YAFFS_TRACE_SCAN
},
3354 {"tracing", YAFFS_TRACE_TRACING
},
3355 {"sync", YAFFS_TRACE_SYNC
},
3356 {"write", YAFFS_TRACE_WRITE
},
3358 {"verify", YAFFS_TRACE_VERIFY
},
3359 {"verify_nand", YAFFS_TRACE_VERIFY_NAND
},
3360 {"verify_full", YAFFS_TRACE_VERIFY_FULL
},
3361 {"verify_all", YAFFS_TRACE_VERIFY_ALL
},
3363 {"all", 0xffffffff},
3368 #define MAX_MASK_NAME_LENGTH 40
3369 static int yaffs_proc_write_trace_options(struct file
*file
, const char *buf
,
3370 unsigned long count
, void *data
)
3372 unsigned rg
= 0, mask_bitfield
;
3376 char substring
[MAX_MASK_NAME_LENGTH
+ 1];
3382 rg
= yaffs_trace_mask
;
3384 while (!done
&& (pos
< count
)) {
3386 while ((pos
< count
) && isspace(buf
[pos
]))
3403 mask_bitfield
= simple_strtoul(buf
+ pos
, &end
, 0);
3405 if (end
> buf
+ pos
) {
3406 mask_name
= "numeral";
3407 len
= end
- (buf
+ pos
);
3411 for (x
= buf
+ pos
, i
= 0;
3412 (*x
== '_' || (*x
>= 'a' && *x
<= 'z')) &&
3413 i
< MAX_MASK_NAME_LENGTH
; x
++, i
++, pos
++)
3415 substring
[i
] = '\0';
3417 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
3418 if (strcmp(substring
, mask_flags
[i
].mask_name
) == 0) {
3419 mask_name
= mask_flags
[i
].mask_name
;
3420 mask_bitfield
= mask_flags
[i
].mask_bitfield
;
3427 if (mask_name
!= NULL
) {
3431 rg
&= ~mask_bitfield
;
3434 rg
|= mask_bitfield
;
3440 rg
|= mask_bitfield
;
3446 yaffs_trace_mask
= rg
| YAFFS_TRACE_ALWAYS
;
3448 printk(KERN_DEBUG
"new trace = 0x%08X\n", yaffs_trace_mask
);
3450 if (rg
& YAFFS_TRACE_ALWAYS
) {
3451 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
3453 flag
= ((rg
& mask_flags
[i
].mask_bitfield
) ==
3454 mask_flags
[i
].mask_bitfield
) ? '+' : '-';
3455 printk(KERN_DEBUG
"%c%s\n", flag
, mask_flags
[i
].mask_name
);
3463 static int yaffs_proc_write(struct file
*file
, const char *buf
,
3464 unsigned long count
, void *data
)
3466 return yaffs_proc_write_trace_options(file
, buf
, count
, data
);
3469 /* Stuff to handle installation of file systems */
3470 struct file_system_to_install
{
3471 struct file_system_type
*fst
;
3475 static struct file_system_to_install fs_to_install
[] = {
3476 {&yaffs_fs_type
, 0},
3477 {&yaffs2_fs_type
, 0},
3481 static int __init
init_yaffs_fs(void)
3484 struct file_system_to_install
*fsinst
;
3486 T(YAFFS_TRACE_ALWAYS
,
3487 (TSTR("yaffs built " __DATE__
" " __TIME__
" Installing. \n")));
3489 #ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
3490 T(YAFFS_TRACE_ALWAYS
,
3491 (TSTR(" \n\n\n\nYAFFS-WARNING CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED selected.\n\n\n\n")));
3497 init_MUTEX(&yaffs_context_lock
);
3499 /* Install the proc_fs entries */
3500 my_proc_entry
= create_proc_entry("yaffs",
3504 if (my_proc_entry
) {
3505 my_proc_entry
->write_proc
= yaffs_proc_write
;
3506 my_proc_entry
->read_proc
= yaffs_proc_read
;
3507 my_proc_entry
->data
= NULL
;
3511 debug_proc_entry
= create_proc_entry("yaffs_stats",
3515 if (debug_proc_entry
) {
3516 debug_proc_entry
->write_proc
= NULL
;
3517 debug_proc_entry
->read_proc
= yaffs_stats_proc_read
;
3518 debug_proc_entry
->data
= NULL
;
3522 /* Now add the file system entries */
3524 fsinst
= fs_to_install
;
3526 while (fsinst
->fst
&& !error
) {
3527 error
= register_filesystem(fsinst
->fst
);
3529 fsinst
->installed
= 1;
3533 /* Any errors? uninstall */
3535 fsinst
= fs_to_install
;
3537 while (fsinst
->fst
) {
3538 if (fsinst
->installed
) {
3539 unregister_filesystem(fsinst
->fst
);
3540 fsinst
->installed
= 0;
3549 static void __exit
exit_yaffs_fs(void)
3552 struct file_system_to_install
*fsinst
;
3554 T(YAFFS_TRACE_ALWAYS
,
3555 (TSTR("yaffs built " __DATE__
" " __TIME__
" removing. \n")));
3557 remove_proc_entry("yaffs", YPROC_ROOT
);
3558 remove_proc_entry("yaffs_stats", YPROC_ROOT
);
3560 fsinst
= fs_to_install
;
3562 while (fsinst
->fst
) {
3563 if (fsinst
->installed
) {
3564 unregister_filesystem(fsinst
->fst
);
3565 fsinst
->installed
= 0;
3571 module_init(init_yaffs_fs
)
3572 module_exit(exit_yaffs_fs
)
3574 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
3575 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2010");
3576 MODULE_LICENSE("GPL");