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
=
35 "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $";
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 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
217 static struct file_operations yaffs_file_operations
= {
218 .read
= do_sync_read
,
219 .write
= do_sync_write
,
220 .aio_read
= generic_file_aio_read
,
221 .aio_write
= generic_file_aio_write
,
222 .mmap
= generic_file_mmap
,
223 .flush
= yaffs_file_flush
,
224 .fsync
= yaffs_sync_object
,
225 .splice_read
= generic_file_splice_read
,
226 .splice_write
= generic_file_splice_write
,
229 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
231 static struct file_operations yaffs_file_operations
= {
232 .read
= do_sync_read
,
233 .write
= do_sync_write
,
234 .aio_read
= generic_file_aio_read
,
235 .aio_write
= generic_file_aio_write
,
236 .mmap
= generic_file_mmap
,
237 .flush
= yaffs_file_flush
,
238 .fsync
= yaffs_sync_object
,
239 .sendfile
= generic_file_sendfile
,
244 static struct file_operations yaffs_file_operations
= {
245 .read
= generic_file_read
,
246 .write
= generic_file_write
,
247 .mmap
= generic_file_mmap
,
248 .flush
= yaffs_file_flush
,
249 .fsync
= yaffs_sync_object
,
250 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
251 .sendfile
= generic_file_sendfile
,
256 static struct inode_operations yaffs_file_inode_operations
= {
257 .setattr
= yaffs_setattr
,
260 static struct inode_operations yaffs_symlink_inode_operations
= {
261 .readlink
= yaffs_readlink
,
262 .follow_link
= yaffs_follow_link
,
263 .setattr
= yaffs_setattr
,
266 static struct inode_operations yaffs_dir_inode_operations
= {
267 .create
= yaffs_create
,
268 .lookup
= yaffs_lookup
,
270 .unlink
= yaffs_unlink
,
271 .symlink
= yaffs_symlink
,
272 .mkdir
= yaffs_mkdir
,
273 .rmdir
= yaffs_unlink
,
274 .mknod
= yaffs_mknod
,
275 .rename
= yaffs_rename
,
276 .setattr
= yaffs_setattr
,
279 static struct file_operations yaffs_dir_operations
= {
280 .read
= generic_read_dir
,
281 .readdir
= yaffs_readdir
,
282 .fsync
= yaffs_sync_object
,
285 static struct super_operations yaffs_super_ops
= {
286 .statfs
= yaffs_statfs
,
287 .read_inode
= yaffs_read_inode
,
288 .put_inode
= yaffs_put_inode
,
289 .put_super
= yaffs_put_super
,
290 .delete_inode
= yaffs_delete_inode
,
291 .clear_inode
= yaffs_clear_inode
,
292 .sync_fs
= yaffs_sync_fs
,
293 .write_super
= yaffs_write_super
,
296 static void yaffs_GrossLock(yaffs_Device
* dev
)
298 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs locking\n"));
300 down(&dev
->grossLock
);
303 static void yaffs_GrossUnlock(yaffs_Device
* dev
)
305 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs unlocking\n"));
310 static int yaffs_readlink(struct dentry
*dentry
, char __user
* buffer
,
313 unsigned char *alias
;
316 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
318 yaffs_GrossLock(dev
);
320 alias
= yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry
));
322 yaffs_GrossUnlock(dev
);
327 ret
= vfs_readlink(dentry
, buffer
, buflen
, alias
);
332 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
333 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
335 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
338 unsigned char *alias
;
340 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
342 yaffs_GrossLock(dev
);
344 alias
= yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry
));
346 yaffs_GrossUnlock(dev
);
354 ret
= vfs_follow_link(nd
, alias
);
357 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
358 return ERR_PTR (ret
);
364 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
368 * Lookup is used to find objects in the fs
370 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
372 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
375 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
)
379 struct inode
*inode
= NULL
; /* NCB 2.5/2.6 needs NULL here */
381 yaffs_Device
*dev
= yaffs_InodeToObject(dir
)->myDev
;
383 yaffs_GrossLock(dev
);
386 (KERN_DEBUG
"yaffs_lookup for %d:%s\n",
387 yaffs_InodeToObject(dir
)->objectId
, dentry
->d_name
.name
));
390 yaffs_FindObjectByName(yaffs_InodeToObject(dir
),
391 dentry
->d_name
.name
);
393 obj
= yaffs_GetEquivalentObject(obj
); /* in case it was a hardlink */
395 /* Can't hold gross lock when calling yaffs_get_inode() */
396 yaffs_GrossUnlock(dev
);
400 (KERN_DEBUG
"yaffs_lookup found %d\n", obj
->objectId
));
402 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
406 (KERN_DEBUG
"yaffs_loookup dentry \n"));
407 /* #if 0 asserted by NCB for 2.5/6 compatability - falls through to
408 * d_add even if NULL inode */
410 /*dget(dentry); // try to solve directory bug */
411 d_add(dentry
, inode
);
419 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_lookup not found\n"));
423 /* added NCB for 2.5/6 compatability - forces add even if inode is
424 * NULL which creates dentry hash */
425 d_add(dentry
, inode
);
428 /* return (ERR_PTR(-EIO)); */
432 /* For now put inode is just for debugging
433 * Put inode is called when the inode **structure** is put.
435 static void yaffs_put_inode(struct inode
*inode
)
438 ("yaffs_put_inode: ino %d, count %d\n", (int)inode
->i_ino
,
439 atomic_read(&inode
->i_count
)));
443 /* clear is called to tell the fs to release any per-inode data it holds */
444 static void yaffs_clear_inode(struct inode
*inode
)
449 obj
= yaffs_InodeToObject(inode
);
452 ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode
->i_ino
,
453 atomic_read(&inode
->i_count
),
454 obj
? "object exists" : "null object"));
458 yaffs_GrossLock(dev
);
460 /* Clear the association between the inode and
464 yaffs_InodeToObjectLV(inode
) = NULL
;
466 /* If the object freeing was deferred, then the real
468 * This should fix the inode inconsistency problem.
471 yaffs_HandleDeferedFree(obj
);
473 yaffs_GrossUnlock(dev
);
478 /* delete is called when the link count is zero and the inode
479 * is put (ie. nobody wants to know about it anymore, time to
481 * NB Must call clear_inode()
483 static void yaffs_delete_inode(struct inode
*inode
)
485 yaffs_Object
*obj
= yaffs_InodeToObject(inode
);
489 ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode
->i_ino
,
490 atomic_read(&inode
->i_count
),
491 obj
? "object exists" : "null object"));
495 yaffs_GrossLock(dev
);
496 yaffs_DeleteFile(obj
);
497 yaffs_GrossUnlock(dev
);
499 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
500 truncate_inode_pages (&inode
->i_data
, 0);
505 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
506 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
)
508 static int yaffs_file_flush(struct file
*file
)
511 yaffs_Object
*obj
= yaffs_DentryToObject(file
->f_dentry
);
513 yaffs_Device
*dev
= obj
->myDev
;
516 (KERN_DEBUG
"yaffs_file_flush object %d (%s)\n", obj
->objectId
,
517 obj
->dirty
? "dirty" : "clean"));
519 yaffs_GrossLock(dev
);
521 yaffs_FlushFile(obj
, 1);
523 yaffs_GrossUnlock(dev
);
528 static int yaffs_readpage_nolock(struct file
*f
, struct page
*pg
)
530 /* Lifted from jffs2 */
533 unsigned char *pg_buf
;
538 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_readpage at %08x, size %08x\n",
539 (unsigned)(pg
->index
<< PAGE_CACHE_SHIFT
),
540 (unsigned)PAGE_CACHE_SIZE
));
542 obj
= yaffs_DentryToObject(f
->f_dentry
);
546 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
547 BUG_ON(!PageLocked(pg
));
554 /* FIXME: Can kmap fail? */
556 yaffs_GrossLock(dev
);
559 yaffs_ReadDataFromFile(obj
, pg_buf
, pg
->index
<< PAGE_CACHE_SHIFT
,
562 yaffs_GrossUnlock(dev
);
568 ClearPageUptodate(pg
);
575 flush_dcache_page(pg
);
578 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_readpage done\n"));
582 static int yaffs_readpage_unlock(struct file
*f
, struct page
*pg
)
584 int ret
= yaffs_readpage_nolock(f
, pg
);
589 static int yaffs_readpage(struct file
*f
, struct page
*pg
)
591 return yaffs_readpage_unlock(f
, pg
);
594 /* writepage inspired by/stolen from smbfs */
596 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
597 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
)
599 static int yaffs_writepage(struct page
*page
)
602 struct address_space
*mapping
= page
->mapping
;
603 loff_t offset
= (loff_t
) page
->index
<< PAGE_CACHE_SHIFT
;
605 unsigned long end_index
;
613 inode
= mapping
->host
;
617 if (offset
> inode
->i_size
) {
620 "yaffs_writepage at %08x, inode size = %08x!!!\n",
621 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
),
622 (unsigned)inode
->i_size
));
624 (KERN_DEBUG
" -> don't care!!\n"));
629 end_index
= inode
->i_size
>> PAGE_CACHE_SHIFT
;
632 if (page
->index
< end_index
) {
633 nBytes
= PAGE_CACHE_SIZE
;
635 nBytes
= inode
->i_size
& (PAGE_CACHE_SIZE
- 1);
642 obj
= yaffs_InodeToObject(inode
);
643 yaffs_GrossLock(obj
->myDev
);
646 (KERN_DEBUG
"yaffs_writepage at %08x, size %08x\n",
647 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
), nBytes
));
649 (KERN_DEBUG
"writepag0: obj = %05x, ino = %05x\n",
650 (int)obj
->variant
.fileVariant
.fileSize
, (int)inode
->i_size
));
653 yaffs_WriteDataToFile(obj
, buffer
, page
->index
<< PAGE_CACHE_SHIFT
,
657 (KERN_DEBUG
"writepag1: obj = %05x, ino = %05x\n",
658 (int)obj
->variant
.fileVariant
.fileSize
, (int)inode
->i_size
));
660 yaffs_GrossUnlock(obj
->myDev
);
663 SetPageUptodate(page
);
667 return (nWritten
== nBytes
) ? 0 : -ENOSPC
;
670 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
671 unsigned offset
, unsigned to
)
674 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_prepair_write\n"));
675 if (!Page_Uptodate(pg
) && (offset
|| to
< PAGE_CACHE_SIZE
))
676 return yaffs_readpage_nolock(f
, pg
);
682 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
686 void *addr
= page_address(pg
) + offset
;
687 loff_t pos
= (((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
) + offset
;
688 int nBytes
= to
- offset
;
692 unsigned saddr
= (unsigned)addr
;
695 (KERN_DEBUG
"yaffs_commit_write addr %x pos %x nBytes %d\n", saddr
,
698 nWritten
= yaffs_file_write(f
, addr
, nBytes
, &pos
);
700 if (nWritten
!= nBytes
) {
703 "yaffs_commit_write not same size nWritten %d nBytes %d\n",
706 ClearPageUptodate(pg
);
712 (KERN_DEBUG
"yaffs_commit_write returning %d\n",
713 nWritten
== nBytes
? 0 : nWritten
));
715 return nWritten
== nBytes
? 0 : nWritten
;
719 static void yaffs_FillInodeFromObject(struct inode
*inode
, yaffs_Object
* obj
)
724 /* Check mode against the variant type and attempt to repair if broken. */
725 __u32 mode
= obj
->yst_mode
;
726 switch( obj
->variantType
){
727 case YAFFS_OBJECT_TYPE_FILE
:
728 if( ! S_ISREG(mode
) ){
729 obj
->yst_mode
&= ~S_IFMT
;
730 obj
->yst_mode
|= S_IFREG
;
734 case YAFFS_OBJECT_TYPE_SYMLINK
:
735 if( ! S_ISLNK(mode
) ){
736 obj
->yst_mode
&= ~S_IFMT
;
737 obj
->yst_mode
|= S_IFLNK
;
741 case YAFFS_OBJECT_TYPE_DIRECTORY
:
742 if( ! S_ISDIR(mode
) ){
743 obj
->yst_mode
&= ~S_IFMT
;
744 obj
->yst_mode
|= S_IFDIR
;
748 case YAFFS_OBJECT_TYPE_UNKNOWN
:
749 case YAFFS_OBJECT_TYPE_HARDLINK
:
750 case YAFFS_OBJECT_TYPE_SPECIAL
:
756 inode
->i_ino
= obj
->objectId
;
757 inode
->i_mode
= obj
->yst_mode
;
758 inode
->i_uid
= obj
->yst_uid
;
759 inode
->i_gid
= obj
->yst_gid
;
760 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
761 inode
->i_blksize
= inode
->i_sb
->s_blocksize
;
763 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
765 inode
->i_rdev
= old_decode_dev(obj
->yst_rdev
);
766 inode
->i_atime
.tv_sec
= (time_t) (obj
->yst_atime
);
767 inode
->i_atime
.tv_nsec
= 0;
768 inode
->i_mtime
.tv_sec
= (time_t) obj
->yst_mtime
;
769 inode
->i_mtime
.tv_nsec
= 0;
770 inode
->i_ctime
.tv_sec
= (time_t) obj
->yst_ctime
;
771 inode
->i_ctime
.tv_nsec
= 0;
773 inode
->i_rdev
= obj
->yst_rdev
;
774 inode
->i_atime
= obj
->yst_atime
;
775 inode
->i_mtime
= obj
->yst_mtime
;
776 inode
->i_ctime
= obj
->yst_ctime
;
778 inode
->i_size
= yaffs_GetObjectFileLength(obj
);
779 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
781 inode
->i_nlink
= yaffs_GetObjectLinkCount(obj
);
785 "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
786 inode
->i_mode
, inode
->i_uid
, inode
->i_gid
,
787 (int)inode
->i_size
, atomic_read(&inode
->i_count
)));
789 switch (obj
->yst_mode
& S_IFMT
) {
790 default: /* fifo, device or socket */
791 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
792 init_special_inode(inode
, obj
->yst_mode
,
793 old_decode_dev(obj
->yst_rdev
));
795 init_special_inode(inode
, obj
->yst_mode
,
796 (dev_t
) (obj
->yst_rdev
));
799 case S_IFREG
: /* file */
800 inode
->i_op
= &yaffs_file_inode_operations
;
801 inode
->i_fop
= &yaffs_file_operations
;
802 inode
->i_mapping
->a_ops
=
803 &yaffs_file_address_operations
;
805 case S_IFDIR
: /* directory */
806 inode
->i_op
= &yaffs_dir_inode_operations
;
807 inode
->i_fop
= &yaffs_dir_operations
;
809 case S_IFLNK
: /* symlink */
810 inode
->i_op
= &yaffs_symlink_inode_operations
;
814 yaffs_InodeToObjectLV(inode
) = obj
;
816 obj
->myInode
= inode
;
820 (KERN_DEBUG
"yaffs_FileInode invalid parameters\n"));
825 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
832 (KERN_DEBUG
"yaffs_get_inode for NULL super_block!!\n"));
839 (KERN_DEBUG
"yaffs_get_inode for NULL object!!\n"));
845 (KERN_DEBUG
"yaffs_get_inode for object %d\n", obj
->objectId
));
847 inode
= iget(sb
, obj
->objectId
);
849 /* NB Side effect: iget calls back to yaffs_read_inode(). */
850 /* iget also increments the inode's i_count */
851 /* NB You can't be holding grossLock or deadlock will happen! */
856 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
864 obj
= yaffs_DentryToObject(f
->f_dentry
);
868 yaffs_GrossLock(dev
);
870 inode
= f
->f_dentry
->d_inode
;
872 if (!S_ISBLK(inode
->i_mode
) && f
->f_flags
& O_APPEND
) {
873 ipos
= inode
->i_size
;
880 (KERN_DEBUG
"yaffs_file_write: hey obj is null!\n"));
884 "yaffs_file_write about to write writing %d bytes"
885 "to object %d at %d\n",
886 n
, obj
->objectId
, ipos
));
889 nWritten
= yaffs_WriteDataToFile(obj
, buf
, ipos
, n
, 0);
892 (KERN_DEBUG
"yaffs_file_write writing %d bytes, %d written at %d\n",
897 if (ipos
> inode
->i_size
) {
898 inode
->i_size
= ipos
;
899 inode
->i_blocks
= (ipos
+ 511) >> 9;
903 "yaffs_file_write size updated to %d bytes, "
905 ipos
, (int)(inode
->i_blocks
)));
909 yaffs_GrossUnlock(dev
);
910 return nWritten
== 0 ? -ENOSPC
: nWritten
;
913 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
)
917 struct inode
*inode
= f
->f_dentry
->d_inode
;
918 unsigned long offset
, curoffs
;
922 char name
[YAFFS_MAX_NAME_LENGTH
+ 1];
924 obj
= yaffs_DentryToObject(f
->f_dentry
);
927 yaffs_GrossLock(dev
);
931 T(YAFFS_TRACE_OS
, ("yaffs_readdir: starting at %d\n", (int)offset
));
935 (KERN_DEBUG
"yaffs_readdir: entry . ino %d \n",
937 if (filldir(dirent
, ".", 1, offset
, inode
->i_ino
, DT_DIR
)
946 (KERN_DEBUG
"yaffs_readdir: entry .. ino %d \n",
947 (int)f
->f_dentry
->d_parent
->d_inode
->i_ino
));
949 (dirent
, "..", 2, offset
,
950 f
->f_dentry
->d_parent
->d_inode
->i_ino
, DT_DIR
) < 0) {
959 /* If the directory has changed since the open or last call to
960 readdir, rewind to after the 2 canned entries. */
962 if (f
->f_version
!= inode
->i_version
) {
965 f
->f_version
= inode
->i_version
;
968 list_for_each(i
, &obj
->variant
.directoryVariant
.children
) {
970 if (curoffs
>= offset
) {
971 l
= list_entry(i
, yaffs_Object
, siblings
);
973 yaffs_GetObjectName(l
, name
,
974 YAFFS_MAX_NAME_LENGTH
+ 1);
976 (KERN_DEBUG
"yaffs_readdir: %s inode %d\n", name
,
977 yaffs_GetObjectInode(l
)));
983 yaffs_GetObjectInode(l
),
984 yaffs_GetObjectType(l
))
997 yaffs_GrossUnlock(dev
);
1003 * File creation. Allocate an inode, and we're done..
1005 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1006 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1009 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1013 struct inode
*inode
;
1015 yaffs_Object
*obj
= NULL
;
1018 yaffs_Object
*parent
= yaffs_InodeToObject(dir
);
1020 int error
= -ENOSPC
;
1021 uid_t uid
= current
->fsuid
;
1022 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: current
->fsgid
;
1024 if((dir
->i_mode
& S_ISGID
) && S_ISDIR(mode
))
1029 (KERN_DEBUG
"yaffs_mknod: parent object %d type %d\n",
1030 parent
->objectId
, parent
->variantType
));
1033 (KERN_DEBUG
"yaffs_mknod: could not get parent object\n"));
1037 T(YAFFS_TRACE_OS
, ("yaffs_mknod: making oject for %s, "
1039 dentry
->d_name
.name
, mode
, rdev
));
1041 dev
= parent
->myDev
;
1043 yaffs_GrossLock(dev
);
1045 switch (mode
& S_IFMT
) {
1047 /* Special (socket, fifo, device...) */
1048 T(YAFFS_TRACE_OS
, (KERN_DEBUG
1049 "yaffs_mknod: making special\n"));
1050 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1052 yaffs_MknodSpecial(parent
, dentry
->d_name
.name
, mode
, uid
,
1053 gid
, old_encode_dev(rdev
));
1056 yaffs_MknodSpecial(parent
, dentry
->d_name
.name
, mode
, uid
,
1060 case S_IFREG
: /* file */
1061 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_mknod: making file\n"));
1063 yaffs_MknodFile(parent
, dentry
->d_name
.name
, mode
, uid
,
1066 case S_IFDIR
: /* directory */
1068 (KERN_DEBUG
"yaffs_mknod: making directory\n"));
1070 yaffs_MknodDirectory(parent
, dentry
->d_name
.name
, mode
,
1073 case S_IFLNK
: /* symlink */
1074 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_mknod: making file\n"));
1075 obj
= NULL
; /* Do we ever get here? */
1079 /* Can not call yaffs_get_inode() with gross lock held */
1080 yaffs_GrossUnlock(dev
);
1083 inode
= yaffs_get_inode(dir
->i_sb
, mode
, rdev
, obj
);
1084 d_instantiate(dentry
, inode
);
1086 (KERN_DEBUG
"yaffs_mknod created object %d count = %d\n",
1087 obj
->objectId
, atomic_read(&inode
->i_count
)));
1091 (KERN_DEBUG
"yaffs_mknod failed making object\n"));
1098 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1101 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_mkdir\n"));
1102 retVal
= yaffs_mknod(dir
, dentry
, mode
| S_IFDIR
, 0);
1104 /* attempt to fix dir bug - didn't work */
1112 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1113 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1114 struct nameidata
*n
)
1116 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1119 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_create\n"));
1120 return yaffs_mknod(dir
, dentry
, mode
| S_IFREG
, 0);
1123 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
)
1130 (KERN_DEBUG
"yaffs_unlink %d:%s\n", (int)(dir
->i_ino
),
1131 dentry
->d_name
.name
));
1133 dev
= yaffs_InodeToObject(dir
)->myDev
;
1135 yaffs_GrossLock(dev
);
1137 retVal
= yaffs_Unlink(yaffs_InodeToObject(dir
), dentry
->d_name
.name
);
1139 if (retVal
== YAFFS_OK
) {
1140 dentry
->d_inode
->i_nlink
--;
1142 yaffs_GrossUnlock(dev
);
1143 mark_inode_dirty(dentry
->d_inode
);
1146 yaffs_GrossUnlock(dev
);
1153 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
1154 struct dentry
*dentry
)
1156 struct inode
*inode
= old_dentry
->d_inode
;
1157 yaffs_Object
*obj
= NULL
;
1158 yaffs_Object
*link
= NULL
;
1161 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_link\n"));
1163 obj
= yaffs_InodeToObject(inode
);
1166 yaffs_GrossLock(dev
);
1168 if (!S_ISDIR(inode
->i_mode
)) /* Don't link directories */
1171 yaffs_Link(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1176 old_dentry
->d_inode
->i_nlink
= yaffs_GetObjectLinkCount(obj
);
1177 d_instantiate(dentry
, old_dentry
->d_inode
);
1178 atomic_inc(&old_dentry
->d_inode
->i_count
);
1180 (KERN_DEBUG
"yaffs_link link count %d i_count %d\n",
1181 old_dentry
->d_inode
->i_nlink
,
1182 atomic_read(&old_dentry
->d_inode
->i_count
)));
1186 yaffs_GrossUnlock(dev
);
1196 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
1197 const char *symname
)
1201 uid_t uid
= current
->fsuid
;
1202 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: current
->fsgid
;
1204 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_symlink\n"));
1206 dev
= yaffs_InodeToObject(dir
)->myDev
;
1207 yaffs_GrossLock(dev
);
1208 obj
= yaffs_MknodSymLink(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1209 S_IFLNK
| S_IRWXUGO
, uid
, gid
, symname
);
1210 yaffs_GrossUnlock(dev
);
1214 struct inode
*inode
;
1216 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1217 d_instantiate(dentry
, inode
);
1218 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"symlink created OK\n"));
1221 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"symlink not created\n"));
1228 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
1235 obj
= yaffs_DentryToObject(dentry
);
1239 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_sync_object\n"));
1240 yaffs_GrossLock(dev
);
1241 yaffs_FlushFile(obj
, 1);
1242 yaffs_GrossUnlock(dev
);
1247 * The VFS layer already does all the dentry stuff for rename.
1249 * NB: POSIX says you can rename an object over an old object of the same name
1251 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1252 struct inode
*new_dir
, struct dentry
*new_dentry
)
1255 int retVal
= YAFFS_FAIL
;
1256 yaffs_Object
*target
;
1258 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_rename\n"));
1259 dev
= yaffs_InodeToObject(old_dir
)->myDev
;
1261 yaffs_GrossLock(dev
);
1263 /* Check if the target is an existing directory that is not empty. */
1265 yaffs_FindObjectByName(yaffs_InodeToObject(new_dir
),
1266 new_dentry
->d_name
.name
);
1271 target
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
&&
1272 !list_empty(&target
->variant
.directoryVariant
.children
)) {
1274 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"target is non-empty dir\n"));
1276 retVal
= YAFFS_FAIL
;
1279 /* Now does unlinking internally using shadowing mechanism */
1280 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"calling yaffs_RenameObject\n"));
1283 yaffs_RenameObject(yaffs_InodeToObject(old_dir
),
1284 old_dentry
->d_name
.name
,
1285 yaffs_InodeToObject(new_dir
),
1286 new_dentry
->d_name
.name
);
1289 yaffs_GrossUnlock(dev
);
1291 if (retVal
== YAFFS_OK
) {
1293 new_dentry
->d_inode
->i_nlink
--;
1294 mark_inode_dirty(new_dentry
->d_inode
);
1304 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
)
1306 struct inode
*inode
= dentry
->d_inode
;
1311 (KERN_DEBUG
"yaffs_setattr of object %d\n",
1312 yaffs_InodeToObject(inode
)->objectId
));
1314 if ((error
= inode_change_ok(inode
, attr
)) == 0) {
1316 dev
= yaffs_InodeToObject(inode
)->myDev
;
1317 yaffs_GrossLock(dev
);
1318 if (yaffs_SetAttributes(yaffs_InodeToObject(inode
), attr
) ==
1324 yaffs_GrossUnlock(dev
);
1326 error
= inode_setattr(inode
, attr
);
1331 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1332 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
1334 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
1335 struct super_block
*sb
= dentry
->d_sb
;
1336 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1337 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
)
1339 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1341 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
)
1343 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1346 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_statfs\n"));
1348 yaffs_GrossLock(dev
);
1350 buf
->f_type
= YAFFS_MAGIC
;
1351 buf
->f_bsize
= sb
->s_blocksize
;
1352 buf
->f_namelen
= 255;
1353 if (sb
->s_blocksize
> dev
->nDataBytesPerChunk
) {
1356 (dev
->endBlock
- dev
->startBlock
+
1357 1) * dev
->nChunksPerBlock
/ (sb
->s_blocksize
/
1358 dev
->nDataBytesPerChunk
);
1360 yaffs_GetNumberOfFreeChunks(dev
) / (sb
->s_blocksize
/
1361 dev
->nDataBytesPerChunk
);
1365 (dev
->endBlock
- dev
->startBlock
+
1366 1) * dev
->nChunksPerBlock
* (dev
->nDataBytesPerChunk
/
1369 yaffs_GetNumberOfFreeChunks(dev
) * (dev
->nDataBytesPerChunk
/
1374 buf
->f_bavail
= buf
->f_bfree
;
1376 yaffs_GrossUnlock(dev
);
1382 static int yaffs_do_sync_fs(struct super_block *sb)
1385 yaffs_Device *dev = yaffs_SuperToDevice(sb);
1386 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n"));
1389 yaffs_GrossLock(dev);
1392 yaffs_CheckpointSave(dev);
1394 yaffs_GrossUnlock(dev);
1402 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1403 static void yaffs_write_super(struct super_block
*sb
)
1405 static int yaffs_write_super(struct super_block
*sb
)
1409 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_write_super\n"));
1410 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
1411 return 0; /* yaffs_do_sync_fs(sb);*/
1416 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1417 static int yaffs_sync_fs(struct super_block
*sb
, int wait
)
1419 static int yaffs_sync_fs(struct super_block
*sb
)
1423 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_sync_fs\n"));
1425 return 0; /* yaffs_do_sync_fs(sb);*/
1430 static void yaffs_read_inode(struct inode
*inode
)
1432 /* NB This is called as a side effect of other functions, but
1433 * we had to release the lock to prevent deadlocks, so
1434 * need to lock again.
1438 yaffs_Device
*dev
= yaffs_SuperToDevice(inode
->i_sb
);
1441 (KERN_DEBUG
"yaffs_read_inode for %d\n", (int)inode
->i_ino
));
1443 yaffs_GrossLock(dev
);
1445 obj
= yaffs_FindObjectByNumber(dev
, inode
->i_ino
);
1447 yaffs_FillInodeFromObject(inode
, obj
);
1449 yaffs_GrossUnlock(dev
);
1452 static LIST_HEAD(yaffs_dev_list
);
1455 static int yaffs_remount_fs(struct super_block
*sb
, int *flags
, char *data
)
1457 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1459 if( *flags
& MS_RDONLY
) {
1460 struct mtd_info
*mtd
= yaffs_SuperToDevice(sb
)->genericDevice
;
1463 (KERN_DEBUG
"yaffs_remount_fs: %s: RO\n", dev
->name
));
1465 yaffs_GrossLock(dev
);
1467 yaffs_FlushEntireDeviceCache(dev
);
1469 yaffs_CheckpointSave(dev
);
1474 yaffs_GrossUnlock(dev
);
1478 (KERN_DEBUG
"yaffs_remount_fs: %s: RW\n", dev
->name
));
1485 static void yaffs_put_super(struct super_block
*sb
)
1487 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1489 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_put_super\n"));
1491 yaffs_GrossLock(dev
);
1493 yaffs_FlushEntireDeviceCache(dev
);
1495 yaffs_CheckpointSave(dev
);
1497 if (dev
->putSuperFunc
) {
1498 dev
->putSuperFunc(sb
);
1501 yaffs_Deinitialise(dev
);
1503 yaffs_GrossUnlock(dev
);
1505 /* we assume this is protected by lock_kernel() in mount/umount */
1506 list_del(&dev
->devList
);
1508 if(dev
->spareBuffer
){
1509 YFREE(dev
->spareBuffer
);
1510 dev
->spareBuffer
= NULL
;
1517 static void yaffs_MTDPutSuper(struct super_block
*sb
)
1520 struct mtd_info
*mtd
= yaffs_SuperToDevice(sb
)->genericDevice
;
1526 put_mtd_device(mtd
);
1530 static void yaffs_MarkSuperBlockDirty(void *vsb
)
1532 struct super_block
*sb
= (struct super_block
*)vsb
;
1534 T(YAFFS_TRACE_OS
, (KERN_DEBUG
"yaffs_MarkSuperBlockDirty() sb = %p\n",sb
));
1541 int skip_checkpoint_read
;
1542 int skip_checkpoint_write
;
1546 #define MAX_OPT_LEN 20
1547 static int yaffs_parse_options(yaffs_options
*options
, const char *options_str
)
1549 char cur_opt
[MAX_OPT_LEN
+1];
1553 /* Parse through the options which is a comma seperated list */
1555 while(options_str
&& *options_str
&& !error
){
1556 memset(cur_opt
,0,MAX_OPT_LEN
+1);
1559 while(*options_str
&& *options_str
!= ','){
1560 if(p
< MAX_OPT_LEN
){
1561 cur_opt
[p
] = *options_str
;
1567 if(!strcmp(cur_opt
,"inband-tags"))
1568 options
->inband_tags
= 1;
1569 else if(!strcmp(cur_opt
,"no-cache"))
1570 options
->no_cache
= 1;
1571 else if(!strcmp(cur_opt
,"no-checkpoint-read"))
1572 options
->skip_checkpoint_read
= 1;
1573 else if(!strcmp(cur_opt
,"no-checkpoint-write"))
1574 options
->skip_checkpoint_write
= 1;
1575 else if(!strcmp(cur_opt
,"no-checkpoint")){
1576 options
->skip_checkpoint_read
= 1;
1577 options
->skip_checkpoint_write
= 1;
1579 printk(KERN_INFO
"yaffs: Bad mount option \"%s\"\n",cur_opt
);
1588 static struct super_block
*yaffs_internal_read_super(int yaffsVersion
,
1589 struct super_block
*sb
,
1590 void *data
, int silent
)
1593 struct inode
*inode
= NULL
;
1594 struct dentry
*root
;
1595 yaffs_Device
*dev
= 0;
1596 char devname_buf
[BDEVNAME_SIZE
+ 1];
1597 struct mtd_info
*mtd
;
1599 char *data_str
= (char *)data
;
1601 yaffs_options options
;
1603 sb
->s_magic
= YAFFS_MAGIC
;
1604 sb
->s_op
= &yaffs_super_ops
;
1607 printk(KERN_INFO
"yaffs: sb is NULL\n");
1608 else if (!sb
->s_dev
)
1609 printk(KERN_INFO
"yaffs: sb->s_dev is NULL\n");
1610 else if (!yaffs_devname(sb
, devname_buf
))
1611 printk(KERN_INFO
"yaffs: devname is NULL\n");
1613 printk(KERN_INFO
"yaffs: dev is %d name is \"%s\"\n",
1615 yaffs_devname(sb
, devname_buf
));
1620 printk(KERN_INFO
"yaffs: passed flags \"%s\"\n",data_str
);
1622 memset(&options
,0,sizeof(options
));
1624 if(yaffs_parse_options(&options
,data_str
)){
1625 /* Option parsing failed */
1630 sb
->s_blocksize
= PAGE_CACHE_SIZE
;
1631 sb
->s_blocksize_bits
= PAGE_CACHE_SHIFT
;
1632 T(YAFFS_TRACE_OS
, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion
));
1634 ("yaffs_read_super: block size %d\n", (int)(sb
->s_blocksize
)));
1636 #ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
1638 ("yaffs: Write verification disabled. All guarantees "
1639 "null and void\n"));
1642 T(YAFFS_TRACE_ALWAYS
, ("yaffs: Attempting MTD mount on %u.%u, "
1644 MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
),
1645 yaffs_devname(sb
, devname_buf
)));
1647 /* Check it's an mtd device..... */
1648 if (MAJOR(sb
->s_dev
) != MTD_BLOCK_MAJOR
) {
1649 return NULL
; /* This isn't an mtd device */
1651 /* Get the device */
1652 mtd
= get_mtd_device(NULL
, MINOR(sb
->s_dev
));
1654 T(YAFFS_TRACE_ALWAYS
,
1655 ("yaffs: MTD device #%u doesn't appear to exist\n",
1659 /* Check it's NAND */
1660 if (mtd
->type
!= MTD_NANDFLASH
) {
1661 T(YAFFS_TRACE_ALWAYS
,
1662 ("yaffs: MTD device is not NAND it's type %d\n", mtd
->type
));
1666 T(YAFFS_TRACE_OS
, (" erase %p\n", mtd
->erase
));
1667 T(YAFFS_TRACE_OS
, (" read %p\n", mtd
->read
));
1668 T(YAFFS_TRACE_OS
, (" write %p\n", mtd
->write
));
1669 T(YAFFS_TRACE_OS
, (" readoob %p\n", mtd
->read_oob
));
1670 T(YAFFS_TRACE_OS
, (" writeoob %p\n", mtd
->write_oob
));
1671 T(YAFFS_TRACE_OS
, (" block_isbad %p\n", mtd
->block_isbad
));
1672 T(YAFFS_TRACE_OS
, (" block_markbad %p\n", mtd
->block_markbad
));
1673 T(YAFFS_TRACE_OS
, (" %s %d\n", WRITE_SIZE_STR
, WRITE_SIZE(mtd
)));
1674 T(YAFFS_TRACE_OS
, (" oobsize %d\n", mtd
->oobsize
));
1675 T(YAFFS_TRACE_OS
, (" erasesize %d\n", mtd
->erasesize
));
1676 T(YAFFS_TRACE_OS
, (" size %d\n", mtd
->size
));
1678 #ifdef CONFIG_YAFFS_AUTO_YAFFS2
1680 if (yaffsVersion
== 1 &&
1681 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1682 mtd
->writesize
>= 2048) {
1684 mtd
->oobblock
>= 2048) {
1686 T(YAFFS_TRACE_ALWAYS
,("yaffs: auto selecting yaffs2\n"));
1690 /* Added NCB 26/5/2006 for completeness */
1691 if (yaffsVersion
== 2 &&
1692 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1693 mtd
->writesize
== 512) {
1695 mtd
->oobblock
== 512) {
1697 T(YAFFS_TRACE_ALWAYS
,("yaffs: auto selecting yaffs1\n"));
1703 if (yaffsVersion
== 2) {
1704 /* Check for version 2 style functions */
1706 !mtd
->block_isbad
||
1707 !mtd
->block_markbad
||
1710 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1711 !mtd
->read_oob
|| !mtd
->write_oob
) {
1714 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
1716 T(YAFFS_TRACE_ALWAYS
,
1717 ("yaffs: MTD device does not support required "
1722 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1723 if (mtd
->writesize
< YAFFS_MIN_YAFFS2_CHUNK_SIZE
||
1725 if (mtd
->oobblock
< YAFFS_MIN_YAFFS2_CHUNK_SIZE
||
1727 mtd
->oobsize
< YAFFS_MIN_YAFFS2_SPARE_SIZE
) {
1728 T(YAFFS_TRACE_ALWAYS
,
1729 ("yaffs: MTD device does not have the "
1730 "right page sizes\n"));
1734 /* Check for V1 style functions */
1738 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1739 !mtd
->read_oob
|| !mtd
->write_oob
) {
1742 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
1744 T(YAFFS_TRACE_ALWAYS
,
1745 ("yaffs: MTD device does not support required "
1750 if (WRITE_SIZE(mtd
) < YAFFS_BYTES_PER_CHUNK
||
1751 mtd
->oobsize
!= YAFFS_BYTES_PER_SPARE
) {
1752 T(YAFFS_TRACE_ALWAYS
,
1753 ("yaffs: MTD device does not support have the "
1754 "right page sizes\n"));
1759 /* OK, so if we got here, we have an MTD that's NAND and looks
1760 * like it has the right capabilities
1761 * Set the yaffs_Device up for mtd
1764 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1765 sb
->s_fs_info
= dev
= kmalloc(sizeof(yaffs_Device
), GFP_KERNEL
);
1767 sb
->u
.generic_sbp
= dev
= kmalloc(sizeof(yaffs_Device
), GFP_KERNEL
);
1770 /* Deep shit could not allocate device structure */
1771 T(YAFFS_TRACE_ALWAYS
,
1772 ("yaffs_read_super: Failed trying to allocate "
1773 "yaffs_Device. \n"));
1777 memset(dev
, 0, sizeof(yaffs_Device
));
1778 dev
->genericDevice
= mtd
;
1779 dev
->name
= mtd
->name
;
1781 /* Set up the memory size parameters.... */
1783 nBlocks
= mtd
->size
/ (YAFFS_CHUNKS_PER_BLOCK
* YAFFS_BYTES_PER_CHUNK
);
1784 dev
->startBlock
= 0;
1785 dev
->endBlock
= nBlocks
- 1;
1786 dev
->nChunksPerBlock
= YAFFS_CHUNKS_PER_BLOCK
;
1787 dev
->nDataBytesPerChunk
= YAFFS_BYTES_PER_CHUNK
;
1788 dev
->nReservedBlocks
= 5;
1789 dev
->nShortOpCaches
= (options
.no_cache
) ? 0 : 10;
1791 /* ... and the functions. */
1792 if (yaffsVersion
== 2) {
1793 dev
->writeChunkWithTagsToNAND
=
1794 nandmtd2_WriteChunkWithTagsToNAND
;
1795 dev
->readChunkWithTagsFromNAND
=
1796 nandmtd2_ReadChunkWithTagsFromNAND
;
1797 dev
->markNANDBlockBad
= nandmtd2_MarkNANDBlockBad
;
1798 dev
->queryNANDBlock
= nandmtd2_QueryNANDBlock
;
1799 dev
->spareBuffer
= YMALLOC(mtd
->oobsize
);
1801 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1802 dev
->nDataBytesPerChunk
= mtd
->writesize
;
1803 dev
->nChunksPerBlock
= mtd
->erasesize
/ mtd
->writesize
;
1805 dev
->nDataBytesPerChunk
= mtd
->oobblock
;
1806 dev
->nChunksPerBlock
= mtd
->erasesize
/ mtd
->oobblock
;
1808 nBlocks
= mtd
->size
/ mtd
->erasesize
;
1810 dev
->nCheckpointReservedBlocks
= CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS
;
1811 dev
->startBlock
= 0;
1812 dev
->endBlock
= nBlocks
- 1;
1814 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1815 /* use the MTD interface in yaffs_mtdif1.c */
1816 dev
->writeChunkWithTagsToNAND
=
1817 nandmtd1_WriteChunkWithTagsToNAND
;
1818 dev
->readChunkWithTagsFromNAND
=
1819 nandmtd1_ReadChunkWithTagsFromNAND
;
1820 dev
->markNANDBlockBad
= nandmtd1_MarkNANDBlockBad
;
1821 dev
->queryNANDBlock
= nandmtd1_QueryNANDBlock
;
1823 dev
->writeChunkToNAND
= nandmtd_WriteChunkToNAND
;
1824 dev
->readChunkFromNAND
= nandmtd_ReadChunkFromNAND
;
1828 /* ... and common functions */
1829 dev
->eraseBlockInNAND
= nandmtd_EraseBlockInNAND
;
1830 dev
->initialiseNAND
= nandmtd_InitialiseNAND
;
1832 dev
->putSuperFunc
= yaffs_MTDPutSuper
;
1834 dev
->superBlock
= (void *)sb
;
1835 dev
->markSuperBlockDirty
= yaffs_MarkSuperBlockDirty
;
1838 #ifndef CONFIG_YAFFS_DOES_ECC
1839 dev
->useNANDECC
= 1;
1842 #ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
1843 dev
->wideTnodesDisabled
= 1;
1846 dev
->skipCheckpointRead
= options
.skip_checkpoint_read
;
1847 dev
->skipCheckpointWrite
= options
.skip_checkpoint_write
;
1849 /* we assume this is protected by lock_kernel() in mount/umount */
1850 list_add_tail(&dev
->devList
, &yaffs_dev_list
);
1852 init_MUTEX(&dev
->grossLock
);
1854 yaffs_GrossLock(dev
);
1856 err
= yaffs_GutsInitialise(dev
);
1859 ("yaffs_read_super: guts initialised %s\n",
1860 (err
== YAFFS_OK
) ? "OK" : "FAILED"));
1862 /* Release lock before yaffs_get_inode() */
1863 yaffs_GrossUnlock(dev
);
1865 /* Create root inode */
1866 if (err
== YAFFS_OK
)
1867 inode
= yaffs_get_inode(sb
, S_IFDIR
| 0755, 0,
1873 inode
->i_op
= &yaffs_dir_inode_operations
;
1874 inode
->i_fop
= &yaffs_dir_operations
;
1876 T(YAFFS_TRACE_OS
, ("yaffs_read_super: got root inode\n"));
1878 root
= d_alloc_root(inode
);
1880 T(YAFFS_TRACE_OS
, ("yaffs_read_super: d_alloc_root done\n"));
1888 T(YAFFS_TRACE_OS
, ("yaffs_read_super: done\n"));
1893 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1894 static int yaffs_internal_read_super_mtd(struct super_block
*sb
, void *data
,
1897 return yaffs_internal_read_super(1, sb
, data
, silent
) ? 0 : -EINVAL
;
1900 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1901 static int yaffs_read_super(struct file_system_type
*fs
,
1902 int flags
, const char *dev_name
,
1903 void *data
, struct vfsmount
*mnt
)
1906 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1907 yaffs_internal_read_super_mtd
, mnt
);
1910 static struct super_block
*yaffs_read_super(struct file_system_type
*fs
,
1911 int flags
, const char *dev_name
,
1915 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1916 yaffs_internal_read_super_mtd
);
1920 static struct file_system_type yaffs_fs_type
= {
1921 .owner
= THIS_MODULE
,
1923 .get_sb
= yaffs_read_super
,
1924 .kill_sb
= kill_block_super
,
1925 .fs_flags
= FS_REQUIRES_DEV
,
1928 static struct super_block
*yaffs_read_super(struct super_block
*sb
, void *data
,
1931 return yaffs_internal_read_super(1, sb
, data
, silent
);
1934 static DECLARE_FSTYPE(yaffs_fs_type
, "yaffs", yaffs_read_super
,
1939 #ifdef CONFIG_YAFFS_YAFFS2
1941 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1942 static int yaffs2_internal_read_super_mtd(struct super_block
*sb
, void *data
,
1945 return yaffs_internal_read_super(2, sb
, data
, silent
) ? 0 : -EINVAL
;
1948 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1949 static int yaffs2_read_super(struct file_system_type
*fs
,
1950 int flags
, const char *dev_name
, void *data
,
1951 struct vfsmount
*mnt
)
1953 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1954 yaffs2_internal_read_super_mtd
, mnt
);
1957 static struct super_block
*yaffs2_read_super(struct file_system_type
*fs
,
1958 int flags
, const char *dev_name
,
1962 return get_sb_bdev(fs
, flags
, dev_name
, data
,
1963 yaffs2_internal_read_super_mtd
);
1967 static struct file_system_type yaffs2_fs_type
= {
1968 .owner
= THIS_MODULE
,
1970 .get_sb
= yaffs2_read_super
,
1971 .kill_sb
= kill_block_super
,
1972 .fs_flags
= FS_REQUIRES_DEV
,
1975 static struct super_block
*yaffs2_read_super(struct super_block
*sb
,
1976 void *data
, int silent
)
1978 return yaffs_internal_read_super(2, sb
, data
, silent
);
1981 static DECLARE_FSTYPE(yaffs2_fs_type
, "yaffs2", yaffs2_read_super
,
1985 #endif /* CONFIG_YAFFS_YAFFS2 */
1987 static struct proc_dir_entry
*my_proc_entry
;
1989 static char *yaffs_dump_dev(char *buf
, yaffs_Device
* dev
)
1991 buf
+= sprintf(buf
, "startBlock......... %d\n", dev
->startBlock
);
1992 buf
+= sprintf(buf
, "endBlock........... %d\n", dev
->endBlock
);
1993 buf
+= sprintf(buf
, "nDataBytesPerChunk. %d\n", dev
->nDataBytesPerChunk
);
1994 buf
+= sprintf(buf
, "chunkGroupBits..... %d\n", dev
->chunkGroupBits
);
1995 buf
+= sprintf(buf
, "chunkGroupSize..... %d\n", dev
->chunkGroupSize
);
1996 buf
+= sprintf(buf
, "nErasedBlocks...... %d\n", dev
->nErasedBlocks
);
1997 buf
+= sprintf(buf
, "nReservedBlocks.... %d\n", dev
->nReservedBlocks
);
1998 buf
+= sprintf(buf
, "nCheckptResBlocks.. %d\n", dev
->nCheckpointReservedBlocks
);
1999 buf
+= sprintf(buf
, "blocksInCheckpoint. %d\n", dev
->blocksInCheckpoint
);
2000 buf
+= sprintf(buf
, "nTnodesCreated..... %d\n", dev
->nTnodesCreated
);
2001 buf
+= sprintf(buf
, "nFreeTnodes........ %d\n", dev
->nFreeTnodes
);
2002 buf
+= sprintf(buf
, "nObjectsCreated.... %d\n", dev
->nObjectsCreated
);
2003 buf
+= sprintf(buf
, "nFreeObjects....... %d\n", dev
->nFreeObjects
);
2004 buf
+= sprintf(buf
, "nFreeChunks........ %d\n", dev
->nFreeChunks
);
2005 buf
+= sprintf(buf
, "nPageWrites........ %d\n", dev
->nPageWrites
);
2006 buf
+= sprintf(buf
, "nPageReads......... %d\n", dev
->nPageReads
);
2007 buf
+= sprintf(buf
, "nBlockErasures..... %d\n", dev
->nBlockErasures
);
2008 buf
+= sprintf(buf
, "nGCCopies.......... %d\n", dev
->nGCCopies
);
2010 sprintf(buf
, "garbageCollections. %d\n", dev
->garbageCollections
);
2012 sprintf(buf
, "passiveGCs......... %d\n",
2013 dev
->passiveGarbageCollections
);
2014 buf
+= sprintf(buf
, "nRetriedWrites..... %d\n", dev
->nRetriedWrites
);
2015 buf
+= sprintf(buf
, "nShortOpCaches..... %d\n", dev
->nShortOpCaches
);
2016 buf
+= sprintf(buf
, "nRetireBlocks...... %d\n", dev
->nRetiredBlocks
);
2017 buf
+= sprintf(buf
, "eccFixed........... %d\n", dev
->eccFixed
);
2018 buf
+= sprintf(buf
, "eccUnfixed......... %d\n", dev
->eccUnfixed
);
2019 buf
+= sprintf(buf
, "tagsEccFixed....... %d\n", dev
->tagsEccFixed
);
2020 buf
+= sprintf(buf
, "tagsEccUnfixed..... %d\n", dev
->tagsEccUnfixed
);
2021 buf
+= sprintf(buf
, "cacheHits.......... %d\n", dev
->cacheHits
);
2022 buf
+= sprintf(buf
, "nDeletedFiles...... %d\n", dev
->nDeletedFiles
);
2023 buf
+= sprintf(buf
, "nUnlinkedFiles..... %d\n", dev
->nUnlinkedFiles
);
2025 sprintf(buf
, "nBackgroudDeletions %d\n", dev
->nBackgroundDeletions
);
2026 buf
+= sprintf(buf
, "useNANDECC......... %d\n", dev
->useNANDECC
);
2027 buf
+= sprintf(buf
, "isYaffs2........... %d\n", dev
->isYaffs2
);
2032 static int yaffs_proc_read(char *page
,
2034 off_t offset
, int count
, int *eof
, void *data
)
2036 struct list_head
*item
;
2041 /* Get proc_file_read() to step 'offset' by one on each sucessive call.
2042 * We use 'offset' (*ppos) to indicate where we are in devList.
2043 * This also assumes the user has posted a read buffer large
2044 * enough to hold the complete output; but that's life in /proc.
2049 /* Print header first */
2051 buf
+= sprintf(buf
, "YAFFS built:" __DATE__
" " __TIME__
2052 "\n%s\n%s\n", yaffs_fs_c_version
,
2053 yaffs_guts_c_version
);
2056 /* hold lock_kernel while traversing yaffs_dev_list */
2059 /* Locate and print the Nth entry. Order N-squared but N is small. */
2060 list_for_each(item
, &yaffs_dev_list
) {
2061 yaffs_Device
*dev
= list_entry(item
, yaffs_Device
, devList
);
2066 buf
+= sprintf(buf
, "\nDevice %d \"%s\"\n", n
, dev
->name
);
2067 buf
= yaffs_dump_dev(buf
, dev
);
2072 return buf
- page
< count
? buf
- page
: count
;
2076 * Set the verbosity of the warnings and error messages.
2078 * Note that the names can only be a..z or _ with the current code.
2083 unsigned mask_bitfield
;
2085 {"allocate", YAFFS_TRACE_ALLOCATE
},
2086 {"always", YAFFS_TRACE_ALWAYS
},
2087 {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS
},
2088 {"buffers", YAFFS_TRACE_BUFFERS
},
2089 {"bug", YAFFS_TRACE_BUG
},
2090 {"checkpt", YAFFS_TRACE_CHECKPOINT
},
2091 {"deletion", YAFFS_TRACE_DELETION
},
2092 {"erase", YAFFS_TRACE_ERASE
},
2093 {"error", YAFFS_TRACE_ERROR
},
2094 {"gc_detail", YAFFS_TRACE_GC_DETAIL
},
2095 {"gc", YAFFS_TRACE_GC
},
2096 {"mtd", YAFFS_TRACE_MTD
},
2097 {"nandaccess", YAFFS_TRACE_NANDACCESS
},
2098 {"os", YAFFS_TRACE_OS
},
2099 {"scan_debug", YAFFS_TRACE_SCAN_DEBUG
},
2100 {"scan", YAFFS_TRACE_SCAN
},
2101 {"tracing", YAFFS_TRACE_TRACING
},
2103 {"verify", YAFFS_TRACE_VERIFY
},
2104 {"verify_nand", YAFFS_TRACE_VERIFY_NAND
},
2105 {"verify_full", YAFFS_TRACE_VERIFY_FULL
},
2106 {"verify_all", YAFFS_TRACE_VERIFY_ALL
},
2108 {"write", YAFFS_TRACE_WRITE
},
2109 {"all", 0xffffffff},
2114 #define MAX_MASK_NAME_LENGTH 40
2115 static int yaffs_proc_write(struct file
*file
, const char *buf
,
2116 unsigned long count
, void *data
)
2118 unsigned rg
= 0, mask_bitfield
;
2122 char substring
[MAX_MASK_NAME_LENGTH
+1];
2128 rg
= yaffs_traceMask
;
2130 while (!done
&& (pos
< count
)) {
2132 while ((pos
< count
) && isspace(buf
[pos
])) {
2150 mask_bitfield
= simple_strtoul(buf
+ pos
, &end
, 0);
2151 if (end
> buf
+ pos
) {
2152 mask_name
= "numeral";
2153 len
= end
- (buf
+ pos
);
2157 for(x
= buf
+ pos
, i
= 0;
2158 (*x
== '_' || (*x
>='a' && *x
<= 'z')) &&
2159 i
<MAX_MASK_NAME_LENGTH
; x
++, i
++, pos
++)
2161 substring
[i
] = '\0';
2163 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
2164 if(strcmp(substring
,mask_flags
[i
].mask_name
) == 0){
2165 mask_name
= mask_flags
[i
].mask_name
;
2166 mask_bitfield
= mask_flags
[i
].mask_bitfield
;
2173 if (mask_name
!= NULL
) {
2177 rg
&= ~mask_bitfield
;
2180 rg
|= mask_bitfield
;
2186 rg
|= mask_bitfield
;
2192 yaffs_traceMask
= rg
| YAFFS_TRACE_ALWAYS
;
2194 printk("new trace = 0x%08X\n",yaffs_traceMask
);
2196 if (rg
& YAFFS_TRACE_ALWAYS
) {
2197 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
2199 flag
= ((rg
& mask_flags
[i
].mask_bitfield
) == mask_flags
[i
].mask_bitfield
) ? '+' : '-';
2200 printk("%c%s\n", flag
, mask_flags
[i
].mask_name
);
2207 /* Stuff to handle installation of file systems */
2208 struct file_system_to_install
{
2209 struct file_system_type
*fst
;
2213 static struct file_system_to_install fs_to_install
[] = {
2214 //#ifdef CONFIG_YAFFS_YAFFS1
2215 {&yaffs_fs_type
, 0},
2217 //#ifdef CONFIG_YAFFS_YAFFS2
2218 {&yaffs2_fs_type
, 0},
2223 static int __init
init_yaffs_fs(void)
2226 struct file_system_to_install
*fsinst
;
2228 T(YAFFS_TRACE_ALWAYS
,
2229 ("yaffs " __DATE__
" " __TIME__
" Installing. \n"));
2231 /* Install the proc_fs entry */
2232 my_proc_entry
= create_proc_entry("yaffs",
2236 if (my_proc_entry
) {
2237 my_proc_entry
->write_proc
= yaffs_proc_write
;
2238 my_proc_entry
->read_proc
= yaffs_proc_read
;
2239 my_proc_entry
->data
= NULL
;
2244 /* Now add the file system entries */
2246 fsinst
= fs_to_install
;
2248 while (fsinst
->fst
&& !error
) {
2249 error
= register_filesystem(fsinst
->fst
);
2251 fsinst
->installed
= 1;
2256 /* Any errors? uninstall */
2258 fsinst
= fs_to_install
;
2260 while (fsinst
->fst
) {
2261 if (fsinst
->installed
) {
2262 unregister_filesystem(fsinst
->fst
);
2263 fsinst
->installed
= 0;
2272 static void __exit
exit_yaffs_fs(void)
2275 struct file_system_to_install
*fsinst
;
2277 T(YAFFS_TRACE_ALWAYS
, ("yaffs " __DATE__
" " __TIME__
2280 remove_proc_entry("yaffs", &proc_root
);
2282 fsinst
= fs_to_install
;
2284 while (fsinst
->fst
) {
2285 if (fsinst
->installed
) {
2286 unregister_filesystem(fsinst
->fst
);
2287 fsinst
->installed
= 0;
2294 module_init(init_yaffs_fs
)
2295 module_exit(exit_yaffs_fs
)
2297 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
2298 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2006");
2299 MODULE_LICENSE("GPL");