2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2007 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_Device associated with
29 * >> 2.6: sb->s_fs_info points to the yaffs_Device associated with this
31 * >> inode->u.generic_ip points to the associated yaffs_Object.
34 const char *yaffs_fs_c_version
=
36 extern const char *yaffs_guts_c_version
;
38 #include <linux/version.h>
39 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
40 #include <linux/config.h>
42 #include <linux/kernel.h>
43 #include <linux/module.h>
44 #include <linux/slab.h>
45 #include <linux/init.h>
46 #include <linux/list.h>
48 #include <linux/proc_fs.h>
49 #include <linux/smp_lock.h>
50 #include <linux/pagemap.h>
51 #include <linux/mtd/mtd.h>
52 #include <linux/interrupt.h>
53 #include <linux/string.h>
54 #include <linux/ctype.h>
56 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
58 #include <linux/statfs.h> /* Added NCB 15-8-2003 */
59 #include <asm/statfs.h>
60 #define UnlockPage(p) unlock_page(p)
61 #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
63 /* FIXME: use sb->s_id instead ? */
64 #define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
68 #include <linux/locks.h>
69 #define BDEVNAME_SIZE 0
70 #define yaffs_devname(sb, buf) kdevname(sb->s_dev)
72 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
73 /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
79 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
80 #define WRITE_SIZE_STR "writesize"
81 #define WRITE_SIZE(mtd) (mtd)->writesize
83 #define WRITE_SIZE_STR "oobblock"
84 #define WRITE_SIZE(mtd) (mtd)->oobblock
87 #include <asm/uaccess.h>
90 #include "yaffs_guts.h"
92 #include <linux/mtd/mtd.h>
93 #include "yaffs_mtdif.h"
94 #include "yaffs_mtdif1.h"
95 #include "yaffs_mtdif2.h"
97 unsigned int yaffs_traceMask
= YAFFS_TRACE_BAD_BLOCKS
;
98 unsigned int yaffs_wr_attempts
= YAFFS_WR_ATTEMPTS
;
100 /* Module Parameters */
101 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
102 module_param(yaffs_traceMask
,uint
,0644);
103 module_param(yaffs_wr_attempts
,uint
,0644);
105 MODULE_PARM(yaffs_traceMask
,"i");
106 MODULE_PARM(yaffs_wr_attempts
,"i");
109 /*#define T(x) printk x */
111 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
112 #define yaffs_InodeToObjectLV(iptr) (iptr)->i_private
114 #define yaffs_InodeToObjectLV(iptr) (iptr)->u.generic_ip
117 #define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr)))
118 #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode)
120 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
121 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->s_fs_info)
123 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp)
126 static void yaffs_put_super(struct super_block
*sb
);
128 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
131 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
132 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
);
134 static int yaffs_file_flush(struct file
*file
);
137 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
140 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
);
142 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
143 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
144 struct nameidata
*n
);
145 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
146 struct nameidata
*n
);
148 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
);
149 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
);
151 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
152 struct dentry
*dentry
);
153 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
);
154 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
155 const char *symname
);
156 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
);
158 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
159 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
162 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
165 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
166 struct inode
*new_dir
, struct dentry
*new_dentry
);
167 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
);
169 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
170 static int yaffs_sync_fs(struct super_block
*sb
, int wait
);
171 static void yaffs_write_super(struct super_block
*sb
);
173 static int yaffs_sync_fs(struct super_block
*sb
);
174 static int yaffs_write_super(struct super_block
*sb
);
177 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
178 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
);
179 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
180 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
);
182 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
);
184 static void yaffs_read_inode(struct inode
*inode
);
186 static void yaffs_put_inode(struct inode
*inode
);
187 static void yaffs_delete_inode(struct inode
*);
188 static void yaffs_clear_inode(struct inode
*);
190 static int yaffs_readpage(struct file
*file
, struct page
*page
);
191 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
192 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
);
194 static int yaffs_writepage(struct page
*page
);
196 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
197 unsigned offset
, unsigned to
);
198 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
201 static int yaffs_readlink(struct dentry
*dentry
, char __user
* buffer
,
203 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
204 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
);
206 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
);
209 static struct address_space_operations yaffs_file_address_operations
= {
210 .readpage
= yaffs_readpage
,
211 .writepage
= yaffs_writepage
,
212 .prepare_write
= yaffs_prepare_write
,
213 .commit_write
= yaffs_commit_write
,
216 static struct file_operations yaffs_file_operations
= {
217 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
218 .read
= do_sync_read
,
219 .write
= do_sync_write
,
220 .aio_read
= generic_file_aio_read
,
221 .aio_write
= generic_file_aio_write
,
223 .read
= generic_file_read
,
224 .write
= generic_file_write
,
226 .mmap
= generic_file_mmap
,
227 .flush
= yaffs_file_flush
,
228 .fsync
= yaffs_sync_object
,
229 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
230 .sendfile
= generic_file_sendfile
,
235 static struct inode_operations yaffs_file_inode_operations
= {
236 .setattr
= yaffs_setattr
,
239 static struct inode_operations yaffs_symlink_inode_operations
= {
240 .readlink
= yaffs_readlink
,
241 .follow_link
= yaffs_follow_link
,
242 .setattr
= yaffs_setattr
,
245 static struct inode_operations yaffs_dir_inode_operations
= {
246 .create
= yaffs_create
,
247 .lookup
= yaffs_lookup
,
249 .unlink
= yaffs_unlink
,
250 .symlink
= yaffs_symlink
,
251 .mkdir
= yaffs_mkdir
,
252 .rmdir
= yaffs_unlink
,
253 .mknod
= yaffs_mknod
,
254 .rename
= yaffs_rename
,
255 .setattr
= yaffs_setattr
,
258 static struct file_operations yaffs_dir_operations
= {
259 .read
= generic_read_dir
,
260 .readdir
= yaffs_readdir
,
261 .fsync
= yaffs_sync_object
,
264 static struct super_operations yaffs_super_ops
= {
265 .statfs
= yaffs_statfs
,
266 .read_inode
= yaffs_read_inode
,
267 .put_inode
= yaffs_put_inode
,
268 .put_super
= yaffs_put_super
,
269 .delete_inode
= yaffs_delete_inode
,
270 .clear_inode
= yaffs_clear_inode
,
271 .sync_fs
= yaffs_sync_fs
,
272 .write_super
= yaffs_write_super
,
275 static void yaffs_GrossLock(yaffs_Device
* dev
)
277 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs locking\n"));
279 down(&dev
->grossLock
);
282 static void yaffs_GrossUnlock(yaffs_Device
* dev
)
284 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs unlocking\n"));
289 static int yaffs_readlink(struct dentry
*dentry
, char __user
* buffer
,
292 unsigned char *alias
;
295 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
297 yaffs_GrossLock(dev
);
299 alias
= yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry
));
301 yaffs_GrossUnlock(dev
);
306 ret
= vfs_readlink(dentry
, buffer
, buflen
, alias
);
311 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
312 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
314 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
317 unsigned char *alias
;
319 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
321 yaffs_GrossLock(dev
);
323 alias
= yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry
));
325 yaffs_GrossUnlock(dev
);
333 ret
= vfs_follow_link(nd
, alias
);
336 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
337 return ERR_PTR (ret
);
343 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
347 * Lookup is used to find objects in the fs
349 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
351 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
354 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
)
358 struct inode
*inode
= NULL
; /* NCB 2.5/2.6 needs NULL here */
360 yaffs_Device
*dev
= yaffs_InodeToObject(dir
)->myDev
;
362 yaffs_GrossLock(dev
);
365 (KERN_DEBUG
"yaffs_lookup for %d:%s\n",
366 yaffs_InodeToObject(dir
)->objectId
, dentry
->d_name
.name
));
369 yaffs_FindObjectByName(yaffs_InodeToObject(dir
),
370 dentry
->d_name
.name
);
372 obj
= yaffs_GetEquivalentObject(obj
); /* in case it was a hardlink */
374 /* Can't hold gross lock when calling yaffs_get_inode() */
375 yaffs_GrossUnlock(dev
);
379 (KERN_DEBUG
"yaffs_lookup found %d\n", obj
->objectId
));
381 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
385 (KERN_DEBUG
"yaffs_loookup dentry \n"));
386 /* #if 0 asserted by NCB for 2.5/6 compatability - falls through to
387 * d_add even if NULL inode */
389 /*dget(dentry); // try to solve directory bug */
390 d_add(dentry
, inode
);
398 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_lookup not found\n"));
402 /* added NCB for 2.5/6 compatability - forces add even if inode is
403 * NULL which creates dentry hash */
404 d_add(dentry
, inode
);
407 /* return (ERR_PTR(-EIO)); */
411 /* For now put inode is just for debugging
412 * Put inode is called when the inode **structure** is put.
414 static void yaffs_put_inode(struct inode
*inode
)
417 ("yaffs_put_inode: ino %d, count %d\n", (int)inode
->i_ino
,
418 atomic_read(&inode
->i_count
)));
422 /* clear is called to tell the fs to release any per-inode data it holds */
423 static void yaffs_clear_inode(struct inode
*inode
)
428 obj
= yaffs_InodeToObject(inode
);
431 ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode
->i_ino
,
432 atomic_read(&inode
->i_count
),
433 obj
? "object exists" : "null object"));
437 yaffs_GrossLock(dev
);
439 /* Clear the association between the inode and
443 yaffs_InodeToObjectLV(inode
) = NULL
;
445 /* If the object freeing was deferred, then the real
447 * This should fix the inode inconsistency problem.
450 yaffs_HandleDeferedFree(obj
);
452 yaffs_GrossUnlock(dev
);
457 /* delete is called when the link count is zero and the inode
458 * is put (ie. nobody wants to know about it anymore, time to
460 * NB Must call clear_inode()
462 static void yaffs_delete_inode(struct inode
*inode
)
464 yaffs_Object
*obj
= yaffs_InodeToObject(inode
);
468 ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode
->i_ino
,
469 atomic_read(&inode
->i_count
),
470 obj
? "object exists" : "null object"));
474 yaffs_GrossLock(dev
);
475 yaffs_DeleteFile(obj
);
476 yaffs_GrossUnlock(dev
);
478 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
479 truncate_inode_pages (&inode
->i_data
, 0);
484 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
485 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
)
487 static int yaffs_file_flush(struct file
*file
)
490 yaffs_Object
*obj
= yaffs_DentryToObject(file
->f_dentry
);
492 yaffs_Device
*dev
= obj
->myDev
;
495 (KERN_DEBUG
"yaffs_file_flush object %d (%s)\n", obj
->objectId
,
496 obj
->dirty
? "dirty" : "clean"));
498 yaffs_GrossLock(dev
);
500 yaffs_FlushFile(obj
, 1);
502 yaffs_GrossUnlock(dev
);
507 static int yaffs_readpage_nolock(struct file
*f
, struct page
*pg
)
509 /* Lifted from jffs2 */
512 unsigned char *pg_buf
;
517 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_readpage at %08x, size %08x\n",
518 (unsigned)(pg
->index
<< PAGE_CACHE_SHIFT
),
519 (unsigned)PAGE_CACHE_SIZE
));
521 obj
= yaffs_DentryToObject(f
->f_dentry
);
525 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
526 BUG_ON(!PageLocked(pg
));
533 /* FIXME: Can kmap fail? */
535 yaffs_GrossLock(dev
);
538 yaffs_ReadDataFromFile(obj
, pg_buf
, pg
->index
<< PAGE_CACHE_SHIFT
,
541 yaffs_GrossUnlock(dev
);
547 ClearPageUptodate(pg
);
554 flush_dcache_page(pg
);
557 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_readpage done\n"));
561 static int yaffs_readpage_unlock(struct file
*f
, struct page
*pg
)
563 int ret
= yaffs_readpage_nolock(f
, pg
);
568 static int yaffs_readpage(struct file
*f
, struct page
*pg
)
570 return yaffs_readpage_unlock(f
, pg
);
573 /* writepage inspired by/stolen from smbfs */
575 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
576 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
)
578 static int yaffs_writepage(struct page
*page
)
581 struct address_space
*mapping
= page
->mapping
;
582 loff_t offset
= (loff_t
) page
->index
<< PAGE_CACHE_SHIFT
;
584 unsigned long end_index
;
592 inode
= mapping
->host
;
596 if (offset
> inode
->i_size
) {
599 "yaffs_writepage at %08x, inode size = %08x!!!\n",
600 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
),
601 (unsigned)inode
->i_size
));
603 (KERN_DEBUG
" -> don't care!!\n"));
608 end_index
= inode
->i_size
>> PAGE_CACHE_SHIFT
;
611 if (page
->index
< end_index
) {
612 nBytes
= PAGE_CACHE_SIZE
;
614 nBytes
= inode
->i_size
& (PAGE_CACHE_SIZE
- 1);
621 obj
= yaffs_InodeToObject(inode
);
622 yaffs_GrossLock(obj
->myDev
);
625 (KERN_DEBUG
"yaffs_writepage at %08x, size %08x\n",
626 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
), nBytes
));
628 (KERN_DEBUG
"writepag0: obj = %05x, ino = %05x\n",
629 (int)obj
->variant
.fileVariant
.fileSize
, (int)inode
->i_size
));
632 yaffs_WriteDataToFile(obj
, buffer
, page
->index
<< PAGE_CACHE_SHIFT
,
636 (KERN_DEBUG
"writepag1: obj = %05x, ino = %05x\n",
637 (int)obj
->variant
.fileVariant
.fileSize
, (int)inode
->i_size
));
639 yaffs_GrossUnlock(obj
->myDev
);
642 SetPageUptodate(page
);
646 return (nWritten
== nBytes
) ? 0 : -ENOSPC
;
649 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
650 unsigned offset
, unsigned to
)
653 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_prepair_write\n"));
654 if (!Page_Uptodate(pg
) && (offset
|| to
< PAGE_CACHE_SIZE
))
655 return yaffs_readpage_nolock(f
, pg
);
661 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
665 void *addr
= page_address(pg
) + offset
;
666 loff_t pos
= (((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
) + offset
;
667 int nBytes
= to
- offset
;
671 unsigned saddr
= (unsigned)addr
;
674 (KERN_DEBUG
"yaffs_commit_write addr %x pos %x nBytes %d\n", saddr
,
677 nWritten
= yaffs_file_write(f
, addr
, nBytes
, &pos
);
679 if (nWritten
!= nBytes
) {
682 "yaffs_commit_write not same size nWritten %d nBytes %d\n",
685 ClearPageUptodate(pg
);
691 (KERN_DEBUG
"yaffs_commit_write returning %d\n",
692 nWritten
== nBytes
? 0 : nWritten
));
694 return nWritten
== nBytes
? 0 : nWritten
;
698 static void yaffs_FillInodeFromObject(struct inode
*inode
, yaffs_Object
* obj
)
703 /* Check mode against the variant type and attempt to repair if broken. */
704 __u32 mode
= obj
->yst_mode
;
705 switch( obj
->variantType
){
706 case YAFFS_OBJECT_TYPE_FILE
:
707 if( ! S_ISREG(mode
) ){
708 obj
->yst_mode
&= ~S_IFMT
;
709 obj
->yst_mode
|= S_IFREG
;
713 case YAFFS_OBJECT_TYPE_SYMLINK
:
714 if( ! S_ISLNK(mode
) ){
715 obj
->yst_mode
&= ~S_IFMT
;
716 obj
->yst_mode
|= S_IFLNK
;
720 case YAFFS_OBJECT_TYPE_DIRECTORY
:
721 if( ! S_ISDIR(mode
) ){
722 obj
->yst_mode
&= ~S_IFMT
;
723 obj
->yst_mode
|= S_IFDIR
;
727 case YAFFS_OBJECT_TYPE_UNKNOWN
:
728 case YAFFS_OBJECT_TYPE_HARDLINK
:
729 case YAFFS_OBJECT_TYPE_SPECIAL
:
735 inode
->i_ino
= obj
->objectId
;
736 inode
->i_mode
= obj
->yst_mode
;
737 inode
->i_uid
= obj
->yst_uid
;
738 inode
->i_gid
= obj
->yst_gid
;
739 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
740 inode
->i_blksize
= inode
->i_sb
->s_blocksize
;
742 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
744 inode
->i_rdev
= old_decode_dev(obj
->yst_rdev
);
745 inode
->i_atime
.tv_sec
= (time_t) (obj
->yst_atime
);
746 inode
->i_atime
.tv_nsec
= 0;
747 inode
->i_mtime
.tv_sec
= (time_t) obj
->yst_mtime
;
748 inode
->i_mtime
.tv_nsec
= 0;
749 inode
->i_ctime
.tv_sec
= (time_t) obj
->yst_ctime
;
750 inode
->i_ctime
.tv_nsec
= 0;
752 inode
->i_rdev
= obj
->yst_rdev
;
753 inode
->i_atime
= obj
->yst_atime
;
754 inode
->i_mtime
= obj
->yst_mtime
;
755 inode
->i_ctime
= obj
->yst_ctime
;
757 inode
->i_size
= yaffs_GetObjectFileLength(obj
);
758 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
760 inode
->i_nlink
= yaffs_GetObjectLinkCount(obj
);
764 "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
765 inode
->i_mode
, inode
->i_uid
, inode
->i_gid
,
766 (int)inode
->i_size
, atomic_read(&inode
->i_count
)));
768 switch (obj
->yst_mode
& S_IFMT
) {
769 default: /* fifo, device or socket */
770 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
771 init_special_inode(inode
, obj
->yst_mode
,
772 old_decode_dev(obj
->yst_rdev
));
774 init_special_inode(inode
, obj
->yst_mode
,
775 (dev_t
) (obj
->yst_rdev
));
778 case S_IFREG
: /* file */
779 inode
->i_op
= &yaffs_file_inode_operations
;
780 inode
->i_fop
= &yaffs_file_operations
;
781 inode
->i_mapping
->a_ops
=
782 &yaffs_file_address_operations
;
784 case S_IFDIR
: /* directory */
785 inode
->i_op
= &yaffs_dir_inode_operations
;
786 inode
->i_fop
= &yaffs_dir_operations
;
788 case S_IFLNK
: /* symlink */
789 inode
->i_op
= &yaffs_symlink_inode_operations
;
793 yaffs_InodeToObjectLV(inode
) = obj
;
795 obj
->myInode
= inode
;
799 (KERN_DEBUG
"yaffs_FileInode invalid parameters\n"));
804 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
811 (KERN_DEBUG
"yaffs_get_inode for NULL super_block!!\n"));
818 (KERN_DEBUG
"yaffs_get_inode for NULL object!!\n"));
824 (KERN_DEBUG
"yaffs_get_inode for object %d\n", obj
->objectId
));
826 inode
= iget(sb
, obj
->objectId
);
828 /* NB Side effect: iget calls back to yaffs_read_inode(). */
829 /* iget also increments the inode's i_count */
830 /* NB You can't be holding grossLock or deadlock will happen! */
835 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
843 obj
= yaffs_DentryToObject(f
->f_dentry
);
847 yaffs_GrossLock(dev
);
849 inode
= f
->f_dentry
->d_inode
;
851 if (!S_ISBLK(inode
->i_mode
) && f
->f_flags
& O_APPEND
) {
852 ipos
= inode
->i_size
;
859 (KERN_DEBUG
"yaffs_file_write: hey obj is null!\n"));
863 "yaffs_file_write about to write writing %d bytes"
864 "to object %d at %d\n",
865 n
, obj
->objectId
, ipos
));
868 nWritten
= yaffs_WriteDataToFile(obj
, buf
, ipos
, n
, 0);
871 (KERN_DEBUG
"yaffs_file_write writing %d bytes, %d written at %d\n",
876 if (ipos
> inode
->i_size
) {
877 inode
->i_size
= ipos
;
878 inode
->i_blocks
= (ipos
+ 511) >> 9;
882 "yaffs_file_write size updated to %d bytes, "
884 ipos
, (int)(inode
->i_blocks
)));
888 yaffs_GrossUnlock(dev
);
889 return nWritten
== 0 ? -ENOSPC
: nWritten
;
892 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
)
896 struct inode
*inode
= f
->f_dentry
->d_inode
;
897 unsigned long offset
, curoffs
;
901 char name
[YAFFS_MAX_NAME_LENGTH
+ 1];
903 obj
= yaffs_DentryToObject(f
->f_dentry
);
906 yaffs_GrossLock(dev
);
910 T(YAFFS_TRACE_OS
, ("yaffs_readdir: starting at %d\n", (int)offset
));
914 (KERN_DEBUG
"yaffs_readdir: entry . ino %d \n",
916 if (filldir(dirent
, ".", 1, offset
, inode
->i_ino
, DT_DIR
)
925 (KERN_DEBUG
"yaffs_readdir: entry .. ino %d \n",
926 (int)f
->f_dentry
->d_parent
->d_inode
->i_ino
));
928 (dirent
, "..", 2, offset
,
929 f
->f_dentry
->d_parent
->d_inode
->i_ino
, DT_DIR
) < 0) {
938 /* If the directory has changed since the open or last call to
939 readdir, rewind to after the 2 canned entries. */
941 if (f
->f_version
!= inode
->i_version
) {
944 f
->f_version
= inode
->i_version
;
947 list_for_each(i
, &obj
->variant
.directoryVariant
.children
) {
949 if (curoffs
>= offset
) {
950 l
= list_entry(i
, yaffs_Object
, siblings
);
952 yaffs_GetObjectName(l
, name
,
953 YAFFS_MAX_NAME_LENGTH
+ 1);
955 (KERN_DEBUG
"yaffs_readdir: %s inode %d\n", name
,
956 yaffs_GetObjectInode(l
)));
962 yaffs_GetObjectInode(l
),
963 yaffs_GetObjectType(l
))
976 yaffs_GrossUnlock(dev
);
982 * File creation. Allocate an inode, and we're done..
984 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
985 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
988 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
994 yaffs_Object
*obj
= NULL
;
997 yaffs_Object
*parent
= yaffs_InodeToObject(dir
);
1000 uid_t uid
= current
->fsuid
;
1001 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: current
->fsgid
;
1003 if((dir
->i_mode
& S_ISGID
) && S_ISDIR(mode
))
1008 (KERN_DEBUG
"yaffs_mknod: parent object %d type %d\n",
1009 parent
->objectId
, parent
->variantType
));
1012 (KERN_DEBUG
"yaffs_mknod: could not get parent object\n"));
1016 T(YAFFS_TRACE_OS
, ("yaffs_mknod: making oject for %s, "
1018 dentry
->d_name
.name
, mode
, rdev
));
1020 dev
= parent
->myDev
;
1022 yaffs_GrossLock(dev
);
1024 switch (mode
& S_IFMT
) {
1026 /* Special (socket, fifo, device...) */
1027 T(YAFFS_TRACE_OS
, (KERN_DEBUG
1028 "yaffs_mknod: making special\n"));
1029 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1031 yaffs_MknodSpecial(parent
, dentry
->d_name
.name
, mode
, uid
,
1032 gid
, old_encode_dev(rdev
));
1035 yaffs_MknodSpecial(parent
, dentry
->d_name
.name
, mode
, uid
,
1039 case S_IFREG
: /* file */
1040 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_mknod: making file\n"));
1042 yaffs_MknodFile(parent
, dentry
->d_name
.name
, mode
, uid
,
1045 case S_IFDIR
: /* directory */
1047 (KERN_DEBUG
"yaffs_mknod: making directory\n"));
1049 yaffs_MknodDirectory(parent
, dentry
->d_name
.name
, mode
,
1052 case S_IFLNK
: /* symlink */
1053 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_mknod: making file\n"));
1054 obj
= NULL
; /* Do we ever get here? */
1058 /* Can not call yaffs_get_inode() with gross lock held */
1059 yaffs_GrossUnlock(dev
);
1062 inode
= yaffs_get_inode(dir
->i_sb
, mode
, rdev
, obj
);
1063 d_instantiate(dentry
, inode
);
1065 (KERN_DEBUG
"yaffs_mknod created object %d count = %d\n",
1066 obj
->objectId
, atomic_read(&inode
->i_count
)));
1070 (KERN_DEBUG
"yaffs_mknod failed making object\n"));
1077 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1080 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_mkdir\n"));
1081 retVal
= yaffs_mknod(dir
, dentry
, mode
| S_IFDIR
, 0);
1083 /* attempt to fix dir bug - didn't work */
1091 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1092 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1093 struct nameidata
*n
)
1095 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1098 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_create\n"));
1099 return yaffs_mknod(dir
, dentry
, mode
| S_IFREG
, 0);
1102 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
)
1109 (KERN_DEBUG
"yaffs_unlink %d:%s\n", (int)(dir
->i_ino
),
1110 dentry
->d_name
.name
));
1112 dev
= yaffs_InodeToObject(dir
)->myDev
;
1114 yaffs_GrossLock(dev
);
1116 retVal
= yaffs_Unlink(yaffs_InodeToObject(dir
), dentry
->d_name
.name
);
1118 if (retVal
== YAFFS_OK
) {
1119 dentry
->d_inode
->i_nlink
--;
1121 yaffs_GrossUnlock(dev
);
1122 mark_inode_dirty(dentry
->d_inode
);
1125 yaffs_GrossUnlock(dev
);
1132 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
1133 struct dentry
*dentry
)
1135 struct inode
*inode
= old_dentry
->d_inode
;
1136 yaffs_Object
*obj
= NULL
;
1137 yaffs_Object
*link
= NULL
;
1140 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_link\n"));
1142 obj
= yaffs_InodeToObject(inode
);
1145 yaffs_GrossLock(dev
);
1147 if (!S_ISDIR(inode
->i_mode
)) /* Don't link directories */
1150 yaffs_Link(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1155 old_dentry
->d_inode
->i_nlink
= yaffs_GetObjectLinkCount(obj
);
1156 d_instantiate(dentry
, old_dentry
->d_inode
);
1157 atomic_inc(&old_dentry
->d_inode
->i_count
);
1159 (KERN_DEBUG
"yaffs_link link count %d i_count %d\n",
1160 old_dentry
->d_inode
->i_nlink
,
1161 atomic_read(&old_dentry
->d_inode
->i_count
)));
1165 yaffs_GrossUnlock(dev
);
1175 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
1176 const char *symname
)
1180 uid_t uid
= current
->fsuid
;
1181 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: current
->fsgid
;
1183 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_symlink\n"));
1185 dev
= yaffs_InodeToObject(dir
)->myDev
;
1186 yaffs_GrossLock(dev
);
1187 obj
= yaffs_MknodSymLink(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1188 S_IFLNK
| S_IRWXUGO
, uid
, gid
, symname
);
1189 yaffs_GrossUnlock(dev
);
1193 struct inode
*inode
;
1195 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1196 d_instantiate(dentry
, inode
);
1197 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"symlink created OK\n"));
1200 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"symlink not created\n"));
1207 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
1214 obj
= yaffs_DentryToObject(dentry
);
1218 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_sync_object\n"));
1219 yaffs_GrossLock(dev
);
1220 yaffs_FlushFile(obj
, 1);
1221 yaffs_GrossUnlock(dev
);
1226 * The VFS layer already does all the dentry stuff for rename.
1228 * NB: POSIX says you can rename an object over an old object of the same name
1230 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1231 struct inode
*new_dir
, struct dentry
*new_dentry
)
1234 int retVal
= YAFFS_FAIL
;
1235 yaffs_Object
*target
;
1237 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_rename\n"));
1238 dev
= yaffs_InodeToObject(old_dir
)->myDev
;
1240 yaffs_GrossLock(dev
);
1242 /* Check if the target is an existing directory that is not empty. */
1244 yaffs_FindObjectByName(yaffs_InodeToObject(new_dir
),
1245 new_dentry
->d_name
.name
);
1250 target
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
&&
1251 !list_empty(&target
->variant
.directoryVariant
.children
)) {
1253 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"target is non-empty dir\n"));
1255 retVal
= YAFFS_FAIL
;
1258 /* Now does unlinking internally using shadowing mechanism */
1259 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"calling yaffs_RenameObject\n"));
1262 yaffs_RenameObject(yaffs_InodeToObject(old_dir
),
1263 old_dentry
->d_name
.name
,
1264 yaffs_InodeToObject(new_dir
),
1265 new_dentry
->d_name
.name
);
1268 yaffs_GrossUnlock(dev
);
1270 if (retVal
== YAFFS_OK
) {
1272 new_dentry
->d_inode
->i_nlink
--;
1273 mark_inode_dirty(new_dentry
->d_inode
);
1283 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
)
1285 struct inode
*inode
= dentry
->d_inode
;
1290 (KERN_DEBUG
"yaffs_setattr of object %d\n",
1291 yaffs_InodeToObject(inode
)->objectId
));
1293 if ((error
= inode_change_ok(inode
, attr
)) == 0) {
1295 dev
= yaffs_InodeToObject(inode
)->myDev
;
1296 yaffs_GrossLock(dev
);
1297 if (yaffs_SetAttributes(yaffs_InodeToObject(inode
), attr
) ==
1303 yaffs_GrossUnlock(dev
);
1305 error
= inode_setattr(inode
, attr
);
1310 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1311 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
1313 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
1314 struct super_block
*sb
= dentry
->d_sb
;
1315 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1316 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
)
1318 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1320 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
)
1322 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1325 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_statfs\n"));
1327 yaffs_GrossLock(dev
);
1329 buf
->f_type
= YAFFS_MAGIC
;
1330 buf
->f_bsize
= sb
->s_blocksize
;
1331 buf
->f_namelen
= 255;
1332 if (sb
->s_blocksize
> dev
->nDataBytesPerChunk
) {
1335 (dev
->endBlock
- dev
->startBlock
+
1336 1) * dev
->nChunksPerBlock
/ (sb
->s_blocksize
/
1337 dev
->nDataBytesPerChunk
);
1339 yaffs_GetNumberOfFreeChunks(dev
) / (sb
->s_blocksize
/
1340 dev
->nDataBytesPerChunk
);
1344 (dev
->endBlock
- dev
->startBlock
+
1345 1) * dev
->nChunksPerBlock
* (dev
->nDataBytesPerChunk
/
1348 yaffs_GetNumberOfFreeChunks(dev
) * (dev
->nDataBytesPerChunk
/
1353 buf
->f_bavail
= buf
->f_bfree
;
1355 yaffs_GrossUnlock(dev
);
1361 static int yaffs_do_sync_fs(struct super_block *sb)
1364 yaffs_Device *dev = yaffs_SuperToDevice(sb);
1365 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n"));
1368 yaffs_GrossLock(dev);
1371 yaffs_CheckpointSave(dev);
1373 yaffs_GrossUnlock(dev);
1381 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1382 static void yaffs_write_super(struct super_block
*sb
)
1384 static int yaffs_write_super(struct super_block
*sb
)
1388 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_write_super\n"));
1389 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
1390 return 0; /* yaffs_do_sync_fs(sb);*/
1395 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1396 static int yaffs_sync_fs(struct super_block
*sb
, int wait
)
1398 static int yaffs_sync_fs(struct super_block
*sb
)
1402 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_sync_fs\n"));
1404 return 0; /* yaffs_do_sync_fs(sb);*/
1409 static void yaffs_read_inode(struct inode
*inode
)
1411 /* NB This is called as a side effect of other functions, but
1412 * we had to release the lock to prevent deadlocks, so
1413 * need to lock again.
1417 yaffs_Device
*dev
= yaffs_SuperToDevice(inode
->i_sb
);
1420 (KERN_DEBUG
"yaffs_read_inode for %d\n", (int)inode
->i_ino
));
1422 yaffs_GrossLock(dev
);
1424 obj
= yaffs_FindObjectByNumber(dev
, inode
->i_ino
);
1426 yaffs_FillInodeFromObject(inode
, obj
);
1428 yaffs_GrossUnlock(dev
);
1431 static LIST_HEAD(yaffs_dev_list
);
1433 static int yaffs_remount_fs(struct super_block
*sb
, int *flags
, char *data
)
1435 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1437 if( *flags
& MS_RDONLY
) {
1438 struct mtd_info
*mtd
= yaffs_SuperToDevice(sb
)->genericDevice
;
1441 (KERN_DEBUG
"yaffs_remount_fs: %s: RO\n", dev
->name
));
1443 yaffs_GrossLock(dev
);
1445 yaffs_FlushEntireDeviceCache(dev
);
1447 yaffs_CheckpointSave(dev
);
1452 yaffs_GrossUnlock(dev
);
1456 (KERN_DEBUG
"yaffs_remount_fs: %s: RW\n", dev
->name
));
1462 static void yaffs_put_super(struct super_block
*sb
)
1464 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1466 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_put_super\n"));
1468 yaffs_GrossLock(dev
);
1470 yaffs_FlushEntireDeviceCache(dev
);
1472 yaffs_CheckpointSave(dev
);
1474 if (dev
->putSuperFunc
) {
1475 dev
->putSuperFunc(sb
);
1478 yaffs_Deinitialise(dev
);
1480 yaffs_GrossUnlock(dev
);
1482 /* we assume this is protected by lock_kernel() in mount/umount */
1483 list_del(&dev
->devList
);
1485 if(dev
->spareBuffer
){
1486 YFREE(dev
->spareBuffer
);
1487 dev
->spareBuffer
= NULL
;
1494 static void yaffs_MTDPutSuper(struct super_block
*sb
)
1497 struct mtd_info
*mtd
= yaffs_SuperToDevice(sb
)->genericDevice
;
1503 put_mtd_device(mtd
);
1507 static void yaffs_MarkSuperBlockDirty(void *vsb
)
1509 struct super_block
*sb
= (struct super_block
*)vsb
;
1511 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_MarkSuperBlockDirty() sb = %p\n",sb
));
1518 int skip_checkpoint_read
;
1519 int skip_checkpoint_write
;
1523 #define MAX_OPT_LEN 20
1524 static int yaffs_parse_options(yaffs_options
*options
, const char *options_str
)
1526 char cur_opt
[MAX_OPT_LEN
+1];
1530 /* Parse through the options which is a comma seperated list */
1532 while(options_str
&& *options_str
&& !error
){
1533 memset(cur_opt
,0,MAX_OPT_LEN
+1);
1536 while(*options_str
&& *options_str
!= ','){
1537 if(p
< MAX_OPT_LEN
){
1538 cur_opt
[p
] = *options_str
;
1544 if(!strcmp(cur_opt
,"inband-tags"))
1545 options
->inband_tags
= 1;
1546 else if(!strcmp(cur_opt
,"no-cache"))
1547 options
->no_cache
= 1;
1548 else if(!strcmp(cur_opt
,"no-checkpoint-read"))
1549 options
->skip_checkpoint_read
= 1;
1550 else if(!strcmp(cur_opt
,"no-checkpoint-write"))
1551 options
->skip_checkpoint_write
= 1;
1552 else if(!strcmp(cur_opt
,"no-checkpoint")){
1553 options
->skip_checkpoint_read
= 1;
1554 options
->skip_checkpoint_write
= 1;
1556 printk(KERN_INFO
"yaffs: Bad mount option \"%s\"\n",cur_opt
);
1565 static struct super_block
*yaffs_internal_read_super(int yaffsVersion
,
1566 struct super_block
*sb
,
1567 void *data
, int silent
)
1570 struct inode
*inode
= NULL
;
1571 struct dentry
*root
;
1572 yaffs_Device
*dev
= 0;
1573 char devname_buf
[BDEVNAME_SIZE
+ 1];
1574 struct mtd_info
*mtd
;
1576 char *data_str
= (char *)data
;
1578 yaffs_options options
;
1580 sb
->s_magic
= YAFFS_MAGIC
;
1581 sb
->s_op
= &yaffs_super_ops
;
1584 printk(KERN_INFO
"yaffs: sb is NULL\n");
1585 else if (!sb
->s_dev
)
1586 printk(KERN_INFO
"yaffs: sb->s_dev is NULL\n");
1587 else if (!yaffs_devname(sb
, devname_buf
))
1588 printk(KERN_INFO
"yaffs: devname is NULL\n");
1590 printk(KERN_INFO
"yaffs: dev is %d name is \"%s\"\n",
1592 yaffs_devname(sb
, devname_buf
));
1597 printk(KERN_INFO
"yaffs: passed flags \"%s\"\n",data_str
);
1599 memset(&options
,0,sizeof(options
));
1601 if(yaffs_parse_options(&options
,data_str
)){
1602 /* Option parsing failed */
1607 sb
->s_blocksize
= PAGE_CACHE_SIZE
;
1608 sb
->s_blocksize_bits
= PAGE_CACHE_SHIFT
;
1609 T(YAFFS_TRACE_OS
, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion
));
1611 ("yaffs_read_super: block size %d\n", (int)(sb
->s_blocksize
)));
1613 #ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
1615 ("yaffs: Write verification disabled. All guarantees "
1616 "null and void\n"));
1619 T(YAFFS_TRACE_ALWAYS
, ("yaffs: Attempting MTD mount on %u.%u, "
1621 MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
),
1622 yaffs_devname(sb
, devname_buf
)));
1624 /* Check it's an mtd device..... */
1625 if (MAJOR(sb
->s_dev
) != MTD_BLOCK_MAJOR
) {
1626 return NULL
; /* This isn't an mtd device */
1628 /* Get the device */
1629 mtd
= get_mtd_device(NULL
, MINOR(sb
->s_dev
));
1631 T(YAFFS_TRACE_ALWAYS
,
1632 ("yaffs: MTD device #%u doesn't appear to exist\n",
1636 /* Check it's NAND */
1637 if (mtd
->type
!= MTD_NANDFLASH
) {
1638 T(YAFFS_TRACE_ALWAYS
,
1639 ("yaffs: MTD device is not NAND it's type %d\n", mtd
->type
));
1643 T(YAFFS_TRACE_OS
, (" erase %p\n", mtd
->erase
));
1644 T(YAFFS_TRACE_OS
, (" read %p\n", mtd
->read
));
1645 T(YAFFS_TRACE_OS
, (" write %p\n", mtd
->write
));
1646 T(YAFFS_TRACE_OS
, (" readoob %p\n", mtd
->read_oob
));
1647 T(YAFFS_TRACE_OS
, (" writeoob %p\n", mtd
->write_oob
));
1648 T(YAFFS_TRACE_OS
, (" block_isbad %p\n", mtd
->block_isbad
));
1649 T(YAFFS_TRACE_OS
, (" block_markbad %p\n", mtd
->block_markbad
));
1650 T(YAFFS_TRACE_OS
, (" %s %d\n", WRITE_SIZE_STR
, WRITE_SIZE(mtd
)));
1651 T(YAFFS_TRACE_OS
, (" oobsize %d\n", mtd
->oobsize
));
1652 T(YAFFS_TRACE_OS
, (" erasesize %d\n", mtd
->erasesize
));
1653 T(YAFFS_TRACE_OS
, (" size %d\n", mtd
->size
));
1655 #ifdef CONFIG_YAFFS_AUTO_YAFFS2
1657 if (yaffsVersion
== 1 &&
1658 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1659 mtd
->writesize
>= 2048) {
1661 mtd
->oobblock
>= 2048) {
1663 T(YAFFS_TRACE_ALWAYS
,("yaffs: auto selecting yaffs2\n"));
1667 /* Added NCB 26/5/2006 for completeness */
1668 if (yaffsVersion
== 2 &&
1669 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1670 mtd
->writesize
== 512) {
1672 mtd
->oobblock
== 512) {
1674 T(YAFFS_TRACE_ALWAYS
,("yaffs: auto selecting yaffs1\n"));
1680 if (yaffsVersion
== 2) {
1681 /* Check for version 2 style functions */
1683 !mtd
->block_isbad
||
1684 !mtd
->block_markbad
||
1687 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1688 !mtd
->read_oob
|| !mtd
->write_oob
) {
1691 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
1693 T(YAFFS_TRACE_ALWAYS
,
1694 ("yaffs: MTD device does not support required "
1699 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1700 if (mtd
->writesize
< YAFFS_MIN_YAFFS2_CHUNK_SIZE
||
1702 if (mtd
->oobblock
< YAFFS_MIN_YAFFS2_CHUNK_SIZE
||
1704 mtd
->oobsize
< YAFFS_MIN_YAFFS2_SPARE_SIZE
) {
1705 T(YAFFS_TRACE_ALWAYS
,
1706 ("yaffs: MTD device does not have the "
1707 "right page sizes\n"));
1711 /* Check for V1 style functions */
1715 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1716 !mtd
->read_oob
|| !mtd
->write_oob
) {
1719 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
1721 T(YAFFS_TRACE_ALWAYS
,
1722 ("yaffs: MTD device does not support required "
1727 if (WRITE_SIZE(mtd
) < YAFFS_BYTES_PER_CHUNK
||
1728 mtd
->oobsize
!= YAFFS_BYTES_PER_SPARE
) {
1729 T(YAFFS_TRACE_ALWAYS
,
1730 ("yaffs: MTD device does not support have the "
1731 "right page sizes\n"));
1736 /* OK, so if we got here, we have an MTD that's NAND and looks
1737 * like it has the right capabilities
1738 * Set the yaffs_Device up for mtd
1741 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1742 sb
->s_fs_info
= dev
= kmalloc(sizeof(yaffs_Device
), GFP_KERNEL
);
1744 sb
->u
.generic_sbp
= dev
= kmalloc(sizeof(yaffs_Device
), GFP_KERNEL
);
1747 /* Deep shit could not allocate device structure */
1748 T(YAFFS_TRACE_ALWAYS
,
1749 ("yaffs_read_super: Failed trying to allocate "
1750 "yaffs_Device. \n"));
1754 memset(dev
, 0, sizeof(yaffs_Device
));
1755 dev
->genericDevice
= mtd
;
1756 dev
->name
= mtd
->name
;
1758 /* Set up the memory size parameters.... */
1760 nBlocks
= mtd
->size
/ (YAFFS_CHUNKS_PER_BLOCK
* YAFFS_BYTES_PER_CHUNK
);
1761 dev
->startBlock
= 0;
1762 dev
->endBlock
= nBlocks
- 1;
1763 dev
->nChunksPerBlock
= YAFFS_CHUNKS_PER_BLOCK
;
1764 dev
->nDataBytesPerChunk
= YAFFS_BYTES_PER_CHUNK
;
1765 dev
->nReservedBlocks
= 5;
1766 dev
->nShortOpCaches
= (options
.no_cache
) ? 0 : 10;
1768 /* ... and the functions. */
1769 if (yaffsVersion
== 2) {
1770 dev
->writeChunkWithTagsToNAND
=
1771 nandmtd2_WriteChunkWithTagsToNAND
;
1772 dev
->readChunkWithTagsFromNAND
=
1773 nandmtd2_ReadChunkWithTagsFromNAND
;
1774 dev
->markNANDBlockBad
= nandmtd2_MarkNANDBlockBad
;
1775 dev
->queryNANDBlock
= nandmtd2_QueryNANDBlock
;
1776 dev
->spareBuffer
= YMALLOC(mtd
->oobsize
);
1778 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1779 dev
->nDataBytesPerChunk
= mtd
->writesize
;
1780 dev
->nChunksPerBlock
= mtd
->erasesize
/ mtd
->writesize
;
1782 dev
->nDataBytesPerChunk
= mtd
->oobblock
;
1783 dev
->nChunksPerBlock
= mtd
->erasesize
/ mtd
->oobblock
;
1785 nBlocks
= mtd
->size
/ mtd
->erasesize
;
1787 dev
->nCheckpointReservedBlocks
= CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS
;
1788 dev
->startBlock
= 0;
1789 dev
->endBlock
= nBlocks
- 1;
1791 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1792 /* use the MTD interface in yaffs_mtdif1.c */
1793 dev
->writeChunkWithTagsToNAND
=
1794 nandmtd1_WriteChunkWithTagsToNAND
;
1795 dev
->readChunkWithTagsFromNAND
=
1796 nandmtd1_ReadChunkWithTagsFromNAND
;
1797 dev
->markNANDBlockBad
= nandmtd1_MarkNANDBlockBad
;
1798 dev
->queryNANDBlock
= nandmtd1_QueryNANDBlock
;
1800 dev
->writeChunkToNAND
= nandmtd_WriteChunkToNAND
;
1801 dev
->readChunkFromNAND
= nandmtd_ReadChunkFromNAND
;
1805 /* ... and common functions */
1806 dev
->eraseBlockInNAND
= nandmtd_EraseBlockInNAND
;
1807 dev
->initialiseNAND
= nandmtd_InitialiseNAND
;
1809 dev
->putSuperFunc
= yaffs_MTDPutSuper
;
1811 dev
->superBlock
= (void *)sb
;
1812 dev
->markSuperBlockDirty
= yaffs_MarkSuperBlockDirty
;
1815 #ifndef CONFIG_YAFFS_DOES_ECC
1816 dev
->useNANDECC
= 1;
1819 #ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
1820 dev
->wideTnodesDisabled
= 1;
1823 dev
->skipCheckpointRead
= options
.skip_checkpoint_read
;
1824 dev
->skipCheckpointWrite
= options
.skip_checkpoint_write
;
1826 /* we assume this is protected by lock_kernel() in mount/umount */
1827 list_add_tail(&dev
->devList
, &yaffs_dev_list
);
1829 init_MUTEX(&dev
->grossLock
);
1831 yaffs_GrossLock(dev
);
1833 err
= yaffs_GutsInitialise(dev
);
1836 ("yaffs_read_super: guts initialised %s\n",
1837 (err
== YAFFS_OK
) ? "OK" : "FAILED"));
1839 /* Release lock before yaffs_get_inode() */
1840 yaffs_GrossUnlock(dev
);
1842 /* Create root inode */
1843 if (err
== YAFFS_OK
)
1844 inode
= yaffs_get_inode(sb
, S_IFDIR
| 0755, 0,
1850 inode
->i_op
= &yaffs_dir_inode_operations
;
1851 inode
->i_fop
= &yaffs_dir_operations
;
1853 T(YAFFS_TRACE_OS
, ("yaffs_read_super: got root inode\n"));
1855 root
= d_alloc_root(inode
);
1857 T(YAFFS_TRACE_OS
, ("yaffs_read_super: d_alloc_root done\n"));
1865 T(YAFFS_TRACE_OS
, ("yaffs_read_super: done\n"));
1870 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1871 static int yaffs_internal_read_super_mtd(struct super_block
*sb
, void *data
,
1874 return yaffs_internal_read_super(1, sb
, data
, silent
) ? 0 : -EINVAL
;
1877 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1878 static int yaffs_read_super(struct file_system_type
*fs
,
1879 int flags
, const char *dev_name
,
1880 void *data
, struct vfsmount
*mnt
)
1883 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1884 yaffs_internal_read_super_mtd
, mnt
);
1887 static struct super_block
*yaffs_read_super(struct file_system_type
*fs
,
1888 int flags
, const char *dev_name
,
1892 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1893 yaffs_internal_read_super_mtd
);
1897 static struct file_system_type yaffs_fs_type
= {
1898 .owner
= THIS_MODULE
,
1900 .get_sb
= yaffs_read_super
,
1901 .kill_sb
= kill_block_super
,
1902 .fs_flags
= FS_REQUIRES_DEV
,
1905 static struct super_block
*yaffs_read_super(struct super_block
*sb
, void *data
,
1908 return yaffs_internal_read_super(1, sb
, data
, silent
);
1911 static DECLARE_FSTYPE(yaffs_fs_type
, "yaffs", yaffs_read_super
,
1916 #ifdef CONFIG_YAFFS_YAFFS2
1918 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1919 static int yaffs2_internal_read_super_mtd(struct super_block
*sb
, void *data
,
1922 return yaffs_internal_read_super(2, sb
, data
, silent
) ? 0 : -EINVAL
;
1925 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1926 static int yaffs2_read_super(struct file_system_type
*fs
,
1927 int flags
, const char *dev_name
, void *data
,
1928 struct vfsmount
*mnt
)
1930 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1931 yaffs2_internal_read_super_mtd
, mnt
);
1934 static struct super_block
*yaffs2_read_super(struct file_system_type
*fs
,
1935 int flags
, const char *dev_name
,
1939 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1940 yaffs2_internal_read_super_mtd
);
1944 static struct file_system_type yaffs2_fs_type
= {
1945 .owner
= THIS_MODULE
,
1947 .get_sb
= yaffs2_read_super
,
1948 .kill_sb
= kill_block_super
,
1949 .fs_flags
= FS_REQUIRES_DEV
,
1952 static struct super_block
*yaffs2_read_super(struct super_block
*sb
,
1953 void *data
, int silent
)
1955 return yaffs_internal_read_super(2, sb
, data
, silent
);
1958 static DECLARE_FSTYPE(yaffs2_fs_type
, "yaffs2", yaffs2_read_super
,
1962 #endif /* CONFIG_YAFFS_YAFFS2 */
1964 static struct proc_dir_entry
*my_proc_entry
;
1966 static char *yaffs_dump_dev(char *buf
, yaffs_Device
* dev
)
1968 buf
+= sprintf(buf
, "startBlock......... %d\n", dev
->startBlock
);
1969 buf
+= sprintf(buf
, "endBlock........... %d\n", dev
->endBlock
);
1970 buf
+= sprintf(buf
, "nDataBytesPerChunk. %d\n", dev
->nDataBytesPerChunk
);
1971 buf
+= sprintf(buf
, "chunkGroupBits..... %d\n", dev
->chunkGroupBits
);
1972 buf
+= sprintf(buf
, "chunkGroupSize..... %d\n", dev
->chunkGroupSize
);
1973 buf
+= sprintf(buf
, "nErasedBlocks...... %d\n", dev
->nErasedBlocks
);
1974 buf
+= sprintf(buf
, "nReservedBlocks.... %d\n", dev
->nReservedBlocks
);
1975 buf
+= sprintf(buf
, "nCheckptResBlocks.. %d\n", dev
->nCheckpointReservedBlocks
);
1976 buf
+= sprintf(buf
, "blocksInCheckpoint. %d\n", dev
->blocksInCheckpoint
);
1977 buf
+= sprintf(buf
, "nTnodesCreated..... %d\n", dev
->nTnodesCreated
);
1978 buf
+= sprintf(buf
, "nFreeTnodes........ %d\n", dev
->nFreeTnodes
);
1979 buf
+= sprintf(buf
, "nObjectsCreated.... %d\n", dev
->nObjectsCreated
);
1980 buf
+= sprintf(buf
, "nFreeObjects....... %d\n", dev
->nFreeObjects
);
1981 buf
+= sprintf(buf
, "nFreeChunks........ %d\n", dev
->nFreeChunks
);
1982 buf
+= sprintf(buf
, "nPageWrites........ %d\n", dev
->nPageWrites
);
1983 buf
+= sprintf(buf
, "nPageReads......... %d\n", dev
->nPageReads
);
1984 buf
+= sprintf(buf
, "nBlockErasures..... %d\n", dev
->nBlockErasures
);
1985 buf
+= sprintf(buf
, "nGCCopies.......... %d\n", dev
->nGCCopies
);
1987 sprintf(buf
, "garbageCollections. %d\n", dev
->garbageCollections
);
1989 sprintf(buf
, "passiveGCs......... %d\n",
1990 dev
->passiveGarbageCollections
);
1991 buf
+= sprintf(buf
, "nRetriedWrites..... %d\n", dev
->nRetriedWrites
);
1992 buf
+= sprintf(buf
, "nShortOpCaches..... %d\n", dev
->nShortOpCaches
);
1993 buf
+= sprintf(buf
, "nRetireBlocks...... %d\n", dev
->nRetiredBlocks
);
1994 buf
+= sprintf(buf
, "eccFixed........... %d\n", dev
->eccFixed
);
1995 buf
+= sprintf(buf
, "eccUnfixed......... %d\n", dev
->eccUnfixed
);
1996 buf
+= sprintf(buf
, "tagsEccFixed....... %d\n", dev
->tagsEccFixed
);
1997 buf
+= sprintf(buf
, "tagsEccUnfixed..... %d\n", dev
->tagsEccUnfixed
);
1998 buf
+= sprintf(buf
, "cacheHits.......... %d\n", dev
->cacheHits
);
1999 buf
+= sprintf(buf
, "nDeletedFiles...... %d\n", dev
->nDeletedFiles
);
2000 buf
+= sprintf(buf
, "nUnlinkedFiles..... %d\n", dev
->nUnlinkedFiles
);
2002 sprintf(buf
, "nBackgroudDeletions %d\n", dev
->nBackgroundDeletions
);
2003 buf
+= sprintf(buf
, "useNANDECC......... %d\n", dev
->useNANDECC
);
2004 buf
+= sprintf(buf
, "isYaffs2........... %d\n", dev
->isYaffs2
);
2009 static int yaffs_proc_read(char *page
,
2011 off_t offset
, int count
, int *eof
, void *data
)
2013 struct list_head
*item
;
2018 /* Get proc_file_read() to step 'offset' by one on each sucessive call.
2019 * We use 'offset' (*ppos) to indicate where we are in devList.
2020 * This also assumes the user has posted a read buffer large
2021 * enough to hold the complete output; but that's life in /proc.
2026 /* Print header first */
2028 buf
+= sprintf(buf
, "YAFFS built:" __DATE__
" " __TIME__
2029 "\n%s\n%s\n", yaffs_fs_c_version
,
2030 yaffs_guts_c_version
);
2033 /* hold lock_kernel while traversing yaffs_dev_list */
2036 /* Locate and print the Nth entry. Order N-squared but N is small. */
2037 list_for_each(item
, &yaffs_dev_list
) {
2038 yaffs_Device
*dev
= list_entry(item
, yaffs_Device
, devList
);
2043 buf
+= sprintf(buf
, "\nDevice %d \"%s\"\n", n
, dev
->name
);
2044 buf
= yaffs_dump_dev(buf
, dev
);
2049 return buf
- page
< count
? buf
- page
: count
;
2053 * Set the verbosity of the warnings and error messages.
2055 * Note that the names can only be a..z or _ with the current code.
2060 unsigned mask_bitfield
;
2062 {"allocate", YAFFS_TRACE_ALLOCATE
},
2063 {"always", YAFFS_TRACE_ALWAYS
},
2064 {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS
},
2065 {"buffers", YAFFS_TRACE_BUFFERS
},
2066 {"bug", YAFFS_TRACE_BUG
},
2067 {"checkpt", YAFFS_TRACE_CHECKPOINT
},
2068 {"deletion", YAFFS_TRACE_DELETION
},
2069 {"erase", YAFFS_TRACE_ERASE
},
2070 {"error", YAFFS_TRACE_ERROR
},
2071 {"gc_detail", YAFFS_TRACE_GC_DETAIL
},
2072 {"gc", YAFFS_TRACE_GC
},
2073 {"mtd", YAFFS_TRACE_MTD
},
2074 {"nandaccess", YAFFS_TRACE_NANDACCESS
},
2075 {"os", YAFFS_TRACE_OS
},
2076 {"scan_debug", YAFFS_TRACE_SCAN_DEBUG
},
2077 {"scan", YAFFS_TRACE_SCAN
},
2078 {"tracing", YAFFS_TRACE_TRACING
},
2080 {"verify", YAFFS_TRACE_VERIFY
},
2081 {"verify_nand", YAFFS_TRACE_VERIFY_NAND
},
2082 {"verify_full", YAFFS_TRACE_VERIFY_FULL
},
2083 {"verify_all", YAFFS_TRACE_VERIFY_ALL
},
2085 {"write", YAFFS_TRACE_WRITE
},
2086 {"all", 0xffffffff},
2091 #define MAX_MASK_NAME_LENGTH 40
2092 static int yaffs_proc_write(struct file
*file
, const char *buf
,
2093 unsigned long count
, void *data
)
2095 unsigned rg
= 0, mask_bitfield
;
2099 char substring
[MAX_MASK_NAME_LENGTH
+1];
2105 rg
= yaffs_traceMask
;
2107 while (!done
&& (pos
< count
)) {
2109 while ((pos
< count
) && isspace(buf
[pos
])) {
2127 mask_bitfield
= simple_strtoul(buf
+ pos
, &end
, 0);
2128 if (end
> buf
+ pos
) {
2129 mask_name
= "numeral";
2130 len
= end
- (buf
+ pos
);
2133 for(x
= buf
+ pos
, i
= 0;
2134 (*x
== '_' || (*x
>='a' && *x
<= 'z')) &&
2135 i
<MAX_MASK_NAME_LENGTH
; x
++, i
++, pos
++)
2137 substring
[i
] = '\0';
2139 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
2140 //len = strlen(mask_flags[i].mask_name);
2141 //if (strncmp(buf + pos, mask_flags[i].mask_name, len) == 0) {
2142 if(strcmp(substring
,mask_flags
[i
].mask_name
) == 0){
2143 mask_name
= mask_flags
[i
].mask_name
;
2144 mask_bitfield
= mask_flags
[i
].mask_bitfield
;
2151 if (mask_name
!= NULL
) {
2156 rg
&= ~mask_bitfield
;
2159 rg
|= mask_bitfield
;
2165 rg
|= mask_bitfield
;
2171 yaffs_traceMask
= rg
| YAFFS_TRACE_ALWAYS
;
2173 printk("new trace = 0x%08X\n",yaffs_traceMask
);
2175 if (rg
& YAFFS_TRACE_ALWAYS
) {
2176 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
2178 flag
= ((rg
& mask_flags
[i
].mask_bitfield
) == mask_flags
[i
].mask_bitfield
) ? '+' : '-';
2179 printk("%c%s\n", flag
, mask_flags
[i
].mask_name
);
2186 /* Stuff to handle installation of file systems */
2187 struct file_system_to_install
{
2188 struct file_system_type
*fst
;
2192 static struct file_system_to_install fs_to_install
[] = {
2193 //#ifdef CONFIG_YAFFS_YAFFS1
2194 {&yaffs_fs_type
, 0},
2196 //#ifdef CONFIG_YAFFS_YAFFS2
2197 {&yaffs2_fs_type
, 0},
2202 static int __init
init_yaffs_fs(void)
2205 struct file_system_to_install
*fsinst
;
2207 T(YAFFS_TRACE_ALWAYS
,
2208 ("yaffs " __DATE__
" " __TIME__
" Installing. \n"));
2210 /* Install the proc_fs entry */
2211 my_proc_entry
= create_proc_entry("yaffs",
2215 if (my_proc_entry
) {
2216 my_proc_entry
->write_proc
= yaffs_proc_write
;
2217 my_proc_entry
->read_proc
= yaffs_proc_read
;
2218 my_proc_entry
->data
= NULL
;
2223 /* Now add the file system entries */
2225 fsinst
= fs_to_install
;
2227 while (fsinst
->fst
&& !error
) {
2228 error
= register_filesystem(fsinst
->fst
);
2230 fsinst
->installed
= 1;
2235 /* Any errors? uninstall */
2237 fsinst
= fs_to_install
;
2239 while (fsinst
->fst
) {
2240 if (fsinst
->installed
) {
2241 unregister_filesystem(fsinst
->fst
);
2242 fsinst
->installed
= 0;
2251 static void __exit
exit_yaffs_fs(void)
2254 struct file_system_to_install
*fsinst
;
2256 T(YAFFS_TRACE_ALWAYS
, ("yaffs " __DATE__
" " __TIME__
2259 remove_proc_entry("yaffs", &proc_root
);
2261 fsinst
= fs_to_install
;
2263 while (fsinst
->fst
) {
2264 if (fsinst
->installed
) {
2265 unregister_filesystem(fsinst
->fst
);
2266 fsinst
->installed
= 0;
2273 module_init(init_yaffs_fs
)
2274 module_exit(exit_yaffs_fs
)
2276 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
2277 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2006");
2278 MODULE_LICENSE("GPL");