2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2009 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.79 2009-03-17 01:12:00 wookey 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>
47 #include <linux/proc_fs.h>
48 #include <linux/smp_lock.h>
49 #include <linux/pagemap.h>
50 #include <linux/mtd/mtd.h>
51 #include <linux/interrupt.h>
52 #include <linux/string.h>
53 #include <linux/ctype.h>
55 #include "asm/div64.h"
57 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
59 #include <linux/statfs.h> /* Added NCB 15-8-2003 */
60 #include <linux/statfs.h>
61 #define UnlockPage(p) unlock_page(p)
62 #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
64 /* FIXME: use sb->s_id instead ? */
65 #define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
69 #include <linux/locks.h>
70 #define BDEVNAME_SIZE 0
71 #define yaffs_devname(sb, buf) kdevname(sb->s_dev)
73 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
74 /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
80 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
81 #define YPROC_ROOT (&proc_root)
83 #define YPROC_ROOT NULL
86 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
87 #define WRITE_SIZE_STR "writesize"
88 #define WRITE_SIZE(mtd) ((mtd)->writesize)
90 #define WRITE_SIZE_STR "oobblock"
91 #define WRITE_SIZE(mtd) ((mtd)->oobblock)
94 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
95 #define YAFFS_USE_WRITE_BEGIN_END 1
97 #define YAFFS_USE_WRITE_BEGIN_END 0
100 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
101 static uint32_t YCALCBLOCKS(uint64_t partition_size
, uint32_t block_size
)
103 uint64_t result
= partition_size
;
104 do_div(result
, block_size
);
105 return (uint32_t)result
;
108 #define YCALCBLOCKS(s, b) ((s)/(b))
111 #include <linux/uaccess.h>
113 #include "yportenv.h"
114 #include "yaffs_guts.h"
116 #include <linux/mtd/mtd.h>
117 #include "yaffs_mtdif.h"
118 #include "yaffs_mtdif1.h"
119 #include "yaffs_mtdif2.h"
121 unsigned int yaffs_traceMask
= YAFFS_TRACE_BAD_BLOCKS
;
122 unsigned int yaffs_wr_attempts
= YAFFS_WR_ATTEMPTS
;
123 unsigned int yaffs_auto_checkpoint
= 1;
125 /* Module Parameters */
126 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
127 module_param(yaffs_traceMask
, uint
, 0644);
128 module_param(yaffs_wr_attempts
, uint
, 0644);
129 module_param(yaffs_auto_checkpoint
, uint
, 0644);
131 MODULE_PARM(yaffs_traceMask
, "i");
132 MODULE_PARM(yaffs_wr_attempts
, "i");
133 MODULE_PARM(yaffs_auto_checkpoint
, "i");
136 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
137 /* use iget and read_inode */
138 #define Y_IGET(sb, inum) iget((sb), (inum))
139 static void yaffs_read_inode(struct inode
*inode
);
142 /* Call local equivalent */
143 #define YAFFS_USE_OWN_IGET
144 #define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
146 static struct inode
*yaffs_iget(struct super_block
*sb
, unsigned long ino
);
149 /*#define T(x) printk x */
151 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
152 #define yaffs_InodeToObjectLV(iptr) ((iptr)->i_private)
154 #define yaffs_InodeToObjectLV(iptr) ((iptr)->u.generic_ip)
157 #define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr)))
158 #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode)
160 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
161 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->s_fs_info)
163 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp)
166 static void yaffs_put_super(struct super_block
*sb
);
168 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
170 static ssize_t
yaffs_hold_space(struct file
*f
);
171 static void yaffs_release_space(struct file
*f
);
173 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
174 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
);
176 static int yaffs_file_flush(struct file
*file
);
179 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
182 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
);
184 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
185 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
186 struct nameidata
*n
);
187 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
188 struct nameidata
*n
);
190 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
);
191 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
);
193 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
194 struct dentry
*dentry
);
195 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
);
196 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
197 const char *symname
);
198 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
);
200 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
201 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
204 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
207 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
208 struct inode
*new_dir
, struct dentry
*new_dentry
);
209 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
);
211 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
212 static int yaffs_sync_fs(struct super_block
*sb
, int wait
);
213 static void yaffs_write_super(struct super_block
*sb
);
215 static int yaffs_sync_fs(struct super_block
*sb
);
216 static int yaffs_write_super(struct super_block
*sb
);
219 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
220 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
);
221 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
222 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
);
224 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
);
227 #ifdef YAFFS_HAS_PUT_INODE
228 static void yaffs_put_inode(struct inode
*inode
);
231 static void yaffs_delete_inode(struct inode
*);
232 static void yaffs_clear_inode(struct inode
*);
234 static int yaffs_readpage(struct file
*file
, struct page
*page
);
235 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
236 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
);
238 static int yaffs_writepage(struct page
*page
);
242 #if (YAFFS_USE_WRITE_BEGIN_END != 0)
243 static int yaffs_write_begin(struct file
*filp
, struct address_space
*mapping
,
244 loff_t pos
, unsigned len
, unsigned flags
,
245 struct page
**pagep
, void **fsdata
);
246 static int yaffs_write_end(struct file
*filp
, struct address_space
*mapping
,
247 loff_t pos
, unsigned len
, unsigned copied
,
248 struct page
*pg
, void *fsdadata
);
250 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
251 unsigned offset
, unsigned to
);
252 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
257 static int yaffs_readlink(struct dentry
*dentry
, char __user
*buffer
,
259 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
260 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
);
262 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
);
265 static struct address_space_operations yaffs_file_address_operations
= {
266 .readpage
= yaffs_readpage
,
267 .writepage
= yaffs_writepage
,
268 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
269 .write_begin
= yaffs_write_begin
,
270 .write_end
= yaffs_write_end
,
272 .prepare_write
= yaffs_prepare_write
,
273 .commit_write
= yaffs_commit_write
,
277 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
278 static const struct file_operations yaffs_file_operations
= {
279 .read
= do_sync_read
,
280 .write
= do_sync_write
,
281 .aio_read
= generic_file_aio_read
,
282 .aio_write
= generic_file_aio_write
,
283 .mmap
= generic_file_mmap
,
284 .flush
= yaffs_file_flush
,
285 .fsync
= yaffs_sync_object
,
286 .splice_read
= generic_file_splice_read
,
287 .splice_write
= generic_file_splice_write
,
288 .llseek
= generic_file_llseek
,
291 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
293 static const struct file_operations yaffs_file_operations
= {
294 .read
= do_sync_read
,
295 .write
= do_sync_write
,
296 .aio_read
= generic_file_aio_read
,
297 .aio_write
= generic_file_aio_write
,
298 .mmap
= generic_file_mmap
,
299 .flush
= yaffs_file_flush
,
300 .fsync
= yaffs_sync_object
,
301 .sendfile
= generic_file_sendfile
,
306 static const struct file_operations yaffs_file_operations
= {
307 .read
= generic_file_read
,
308 .write
= generic_file_write
,
309 .mmap
= generic_file_mmap
,
310 .flush
= yaffs_file_flush
,
311 .fsync
= yaffs_sync_object
,
312 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
313 .sendfile
= generic_file_sendfile
,
318 static const struct inode_operations yaffs_file_inode_operations
= {
319 .setattr
= yaffs_setattr
,
322 static const struct inode_operations yaffs_symlink_inode_operations
= {
323 .readlink
= yaffs_readlink
,
324 .follow_link
= yaffs_follow_link
,
325 .setattr
= yaffs_setattr
,
328 static const struct inode_operations yaffs_dir_inode_operations
= {
329 .create
= yaffs_create
,
330 .lookup
= yaffs_lookup
,
332 .unlink
= yaffs_unlink
,
333 .symlink
= yaffs_symlink
,
334 .mkdir
= yaffs_mkdir
,
335 .rmdir
= yaffs_unlink
,
336 .mknod
= yaffs_mknod
,
337 .rename
= yaffs_rename
,
338 .setattr
= yaffs_setattr
,
341 static const struct file_operations yaffs_dir_operations
= {
342 .read
= generic_read_dir
,
343 .readdir
= yaffs_readdir
,
344 .fsync
= yaffs_sync_object
,
347 static const struct super_operations yaffs_super_ops
= {
348 .statfs
= yaffs_statfs
,
350 #ifndef YAFFS_USE_OWN_IGET
351 .read_inode
= yaffs_read_inode
,
353 #ifdef YAFFS_HAS_PUT_INODE
354 .put_inode
= yaffs_put_inode
,
356 .put_super
= yaffs_put_super
,
357 .delete_inode
= yaffs_delete_inode
,
358 .clear_inode
= yaffs_clear_inode
,
359 .sync_fs
= yaffs_sync_fs
,
360 .write_super
= yaffs_write_super
,
363 static void yaffs_GrossLock(yaffs_Device
*dev
)
365 T(YAFFS_TRACE_OS
, ("yaffs locking %p\n", current
));
366 down(&dev
->grossLock
);
367 T(YAFFS_TRACE_OS
, ("yaffs locked %p\n", current
));
370 static void yaffs_GrossUnlock(yaffs_Device
*dev
)
372 T(YAFFS_TRACE_OS
, ("yaffs unlocking %p\n", current
));
376 static int yaffs_readlink(struct dentry
*dentry
, char __user
*buffer
,
379 unsigned char *alias
;
382 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
384 yaffs_GrossLock(dev
);
386 alias
= yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry
));
388 yaffs_GrossUnlock(dev
);
393 ret
= vfs_readlink(dentry
, buffer
, buflen
, alias
);
398 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
399 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
401 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
404 unsigned char *alias
;
406 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
408 yaffs_GrossLock(dev
);
410 alias
= yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry
));
412 yaffs_GrossUnlock(dev
);
419 ret
= vfs_follow_link(nd
, alias
);
422 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
429 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
433 * Lookup is used to find objects in the fs
435 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
437 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
440 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
)
444 struct inode
*inode
= NULL
; /* NCB 2.5/2.6 needs NULL here */
446 yaffs_Device
*dev
= yaffs_InodeToObject(dir
)->myDev
;
448 yaffs_GrossLock(dev
);
451 ("yaffs_lookup for %d:%s\n",
452 yaffs_InodeToObject(dir
)->objectId
, dentry
->d_name
.name
));
454 obj
= yaffs_FindObjectByName(yaffs_InodeToObject(dir
),
455 dentry
->d_name
.name
);
457 obj
= yaffs_GetEquivalentObject(obj
); /* in case it was a hardlink */
459 /* Can't hold gross lock when calling yaffs_get_inode() */
460 yaffs_GrossUnlock(dev
);
464 ("yaffs_lookup found %d\n", obj
->objectId
));
466 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
470 ("yaffs_loookup dentry \n"));
471 /* #if 0 asserted by NCB for 2.5/6 compatability - falls through to
472 * d_add even if NULL inode */
474 /*dget(dentry); // try to solve directory bug */
475 d_add(dentry
, inode
);
483 T(YAFFS_TRACE_OS
, ("yaffs_lookup not found\n"));
487 /* added NCB for 2.5/6 compatability - forces add even if inode is
488 * NULL which creates dentry hash */
489 d_add(dentry
, inode
);
495 #ifdef YAFFS_HAS_PUT_INODE
497 /* For now put inode is just for debugging
498 * Put inode is called when the inode **structure** is put.
500 static void yaffs_put_inode(struct inode
*inode
)
503 ("yaffs_put_inode: ino %d, count %d\n", (int)inode
->i_ino
,
504 atomic_read(&inode
->i_count
)));
509 /* clear is called to tell the fs to release any per-inode data it holds */
510 static void yaffs_clear_inode(struct inode
*inode
)
515 obj
= yaffs_InodeToObject(inode
);
518 ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode
->i_ino
,
519 atomic_read(&inode
->i_count
),
520 obj
? "object exists" : "null object"));
524 yaffs_GrossLock(dev
);
526 /* Clear the association between the inode and
530 yaffs_InodeToObjectLV(inode
) = NULL
;
532 /* If the object freeing was deferred, then the real
534 * This should fix the inode inconsistency problem.
537 yaffs_HandleDeferedFree(obj
);
539 yaffs_GrossUnlock(dev
);
544 /* delete is called when the link count is zero and the inode
545 * is put (ie. nobody wants to know about it anymore, time to
547 * NB Must call clear_inode()
549 static void yaffs_delete_inode(struct inode
*inode
)
551 yaffs_Object
*obj
= yaffs_InodeToObject(inode
);
555 ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode
->i_ino
,
556 atomic_read(&inode
->i_count
),
557 obj
? "object exists" : "null object"));
561 yaffs_GrossLock(dev
);
562 yaffs_DeleteObject(obj
);
563 yaffs_GrossUnlock(dev
);
565 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
566 truncate_inode_pages(&inode
->i_data
, 0);
571 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
572 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
)
574 static int yaffs_file_flush(struct file
*file
)
577 yaffs_Object
*obj
= yaffs_DentryToObject(file
->f_dentry
);
579 yaffs_Device
*dev
= obj
->myDev
;
582 ("yaffs_file_flush object %d (%s)\n", obj
->objectId
,
583 obj
->dirty
? "dirty" : "clean"));
585 yaffs_GrossLock(dev
);
587 yaffs_FlushFile(obj
, 1);
589 yaffs_GrossUnlock(dev
);
594 static int yaffs_readpage_nolock(struct file
*f
, struct page
*pg
)
596 /* Lifted from jffs2 */
599 unsigned char *pg_buf
;
604 T(YAFFS_TRACE_OS
, ("yaffs_readpage at %08x, size %08x\n",
605 (unsigned)(pg
->index
<< PAGE_CACHE_SHIFT
),
606 (unsigned)PAGE_CACHE_SIZE
));
608 obj
= yaffs_DentryToObject(f
->f_dentry
);
612 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
613 BUG_ON(!PageLocked(pg
));
620 /* FIXME: Can kmap fail? */
622 yaffs_GrossLock(dev
);
624 ret
= yaffs_ReadDataFromFile(obj
, pg_buf
,
625 pg
->index
<< PAGE_CACHE_SHIFT
,
628 yaffs_GrossUnlock(dev
);
634 ClearPageUptodate(pg
);
641 flush_dcache_page(pg
);
644 T(YAFFS_TRACE_OS
, ("yaffs_readpage done\n"));
648 static int yaffs_readpage_unlock(struct file
*f
, struct page
*pg
)
650 int ret
= yaffs_readpage_nolock(f
, pg
);
655 static int yaffs_readpage(struct file
*f
, struct page
*pg
)
657 return yaffs_readpage_unlock(f
, pg
);
660 /* writepage inspired by/stolen from smbfs */
662 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
663 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
)
665 static int yaffs_writepage(struct page
*page
)
668 struct address_space
*mapping
= page
->mapping
;
669 loff_t offset
= (loff_t
) page
->index
<< PAGE_CACHE_SHIFT
;
671 unsigned long end_index
;
679 inode
= mapping
->host
;
683 if (offset
> inode
->i_size
) {
685 ("yaffs_writepage at %08x, inode size = %08x!!!\n",
686 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
),
687 (unsigned)inode
->i_size
));
689 (" -> don't care!!\n"));
694 end_index
= inode
->i_size
>> PAGE_CACHE_SHIFT
;
697 if (page
->index
< end_index
)
698 nBytes
= PAGE_CACHE_SIZE
;
700 nBytes
= inode
->i_size
& (PAGE_CACHE_SIZE
- 1);
706 obj
= yaffs_InodeToObject(inode
);
707 yaffs_GrossLock(obj
->myDev
);
710 ("yaffs_writepage at %08x, size %08x\n",
711 (unsigned)(page
->index
<< PAGE_CACHE_SHIFT
), nBytes
));
713 ("writepag0: obj = %05x, ino = %05x\n",
714 (int)obj
->variant
.fileVariant
.fileSize
, (int)inode
->i_size
));
716 nWritten
= yaffs_WriteDataToFile(obj
, buffer
,
717 page
->index
<< PAGE_CACHE_SHIFT
, nBytes
, 0);
720 ("writepag1: obj = %05x, ino = %05x\n",
721 (int)obj
->variant
.fileVariant
.fileSize
, (int)inode
->i_size
));
723 yaffs_GrossUnlock(obj
->myDev
);
726 SetPageUptodate(page
);
730 return (nWritten
== nBytes
) ? 0 : -ENOSPC
;
734 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
735 static int yaffs_write_begin(struct file
*filp
, struct address_space
*mapping
,
736 loff_t pos
, unsigned len
, unsigned flags
,
737 struct page
**pagep
, void **fsdata
)
739 struct page
*pg
= NULL
;
740 pgoff_t index
= pos
>> PAGE_CACHE_SHIFT
;
741 uint32_t offset
= pos
& (PAGE_CACHE_SIZE
- 1);
742 uint32_t to
= offset
+ len
;
747 T(YAFFS_TRACE_OS
, ("start yaffs_write_begin\n"));
749 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)
750 pg
= grab_cache_page_write_begin(mapping
, index
, flags
);
752 pg
= __grab_cache_page(mapping
, index
);
761 space_held
= yaffs_hold_space(filp
);
768 /* Update page if required */
770 if (!Page_Uptodate(pg
) && (offset
|| to
< PAGE_CACHE_SIZE
))
771 ret
= yaffs_readpage_nolock(filp
, pg
);
776 /* Happy path return */
777 T(YAFFS_TRACE_OS
, ("end yaffs_write_begin - ok\n"));
782 T(YAFFS_TRACE_OS
, ("end yaffs_write_begin fail returning %d\n", ret
));
784 yaffs_release_space(filp
);
787 page_cache_release(pg
);
794 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
795 unsigned offset
, unsigned to
)
797 T(YAFFS_TRACE_OS
, ("yaffs_prepair_write\n"));
799 if (!Page_Uptodate(pg
) && (offset
|| to
< PAGE_CACHE_SIZE
))
800 return yaffs_readpage_nolock(f
, pg
);
805 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
806 static int yaffs_write_end(struct file
*filp
, struct address_space
*mapping
,
807 loff_t pos
, unsigned len
, unsigned copied
,
808 struct page
*pg
, void *fsdadata
)
812 uint32_t offset_into_page
= pos
& (PAGE_CACHE_SIZE
- 1);
815 addr
= kva
+ offset_into_page
;
818 ("yaffs_write_end addr %x pos %x nBytes %d\n",
822 ret
= yaffs_file_write(filp
, addr
, copied
, &pos
);
826 ("yaffs_write_end not same size ret %d copied %d\n",
829 ClearPageUptodate(pg
);
836 yaffs_release_space(filp
);
838 page_cache_release(pg
);
843 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
848 loff_t pos
= (((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
) + offset
;
849 int nBytes
= to
- offset
;
858 saddr
= (unsigned) addr
;
861 ("yaffs_commit_write addr %x pos %x nBytes %d\n",
862 saddr
, spos
, nBytes
));
864 nWritten
= yaffs_file_write(f
, addr
, nBytes
, &pos
);
866 if (nWritten
!= nBytes
) {
868 ("yaffs_commit_write not same size nWritten %d nBytes %d\n",
871 ClearPageUptodate(pg
);
879 ("yaffs_commit_write returning %d\n",
880 nWritten
== nBytes
? 0 : nWritten
));
882 return nWritten
== nBytes
? 0 : nWritten
;
887 static void yaffs_FillInodeFromObject(struct inode
*inode
, yaffs_Object
*obj
)
892 /* Check mode against the variant type and attempt to repair if broken. */
893 __u32 mode
= obj
->yst_mode
;
894 switch (obj
->variantType
) {
895 case YAFFS_OBJECT_TYPE_FILE
:
896 if (!S_ISREG(mode
)) {
897 obj
->yst_mode
&= ~S_IFMT
;
898 obj
->yst_mode
|= S_IFREG
;
902 case YAFFS_OBJECT_TYPE_SYMLINK
:
903 if (!S_ISLNK(mode
)) {
904 obj
->yst_mode
&= ~S_IFMT
;
905 obj
->yst_mode
|= S_IFLNK
;
909 case YAFFS_OBJECT_TYPE_DIRECTORY
:
910 if (!S_ISDIR(mode
)) {
911 obj
->yst_mode
&= ~S_IFMT
;
912 obj
->yst_mode
|= S_IFDIR
;
916 case YAFFS_OBJECT_TYPE_UNKNOWN
:
917 case YAFFS_OBJECT_TYPE_HARDLINK
:
918 case YAFFS_OBJECT_TYPE_SPECIAL
:
924 inode
->i_flags
|= S_NOATIME
;
926 inode
->i_ino
= obj
->objectId
;
927 inode
->i_mode
= obj
->yst_mode
;
928 inode
->i_uid
= obj
->yst_uid
;
929 inode
->i_gid
= obj
->yst_gid
;
930 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
931 inode
->i_blksize
= inode
->i_sb
->s_blocksize
;
933 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
935 inode
->i_rdev
= old_decode_dev(obj
->yst_rdev
);
936 inode
->i_atime
.tv_sec
= (time_t) (obj
->yst_atime
);
937 inode
->i_atime
.tv_nsec
= 0;
938 inode
->i_mtime
.tv_sec
= (time_t) obj
->yst_mtime
;
939 inode
->i_mtime
.tv_nsec
= 0;
940 inode
->i_ctime
.tv_sec
= (time_t) obj
->yst_ctime
;
941 inode
->i_ctime
.tv_nsec
= 0;
943 inode
->i_rdev
= obj
->yst_rdev
;
944 inode
->i_atime
= obj
->yst_atime
;
945 inode
->i_mtime
= obj
->yst_mtime
;
946 inode
->i_ctime
= obj
->yst_ctime
;
948 inode
->i_size
= yaffs_GetObjectFileLength(obj
);
949 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
951 inode
->i_nlink
= yaffs_GetObjectLinkCount(obj
);
954 ("yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
955 inode
->i_mode
, inode
->i_uid
, inode
->i_gid
,
956 (int)inode
->i_size
, atomic_read(&inode
->i_count
)));
958 switch (obj
->yst_mode
& S_IFMT
) {
959 default: /* fifo, device or socket */
960 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
961 init_special_inode(inode
, obj
->yst_mode
,
962 old_decode_dev(obj
->yst_rdev
));
964 init_special_inode(inode
, obj
->yst_mode
,
965 (dev_t
) (obj
->yst_rdev
));
968 case S_IFREG
: /* file */
969 inode
->i_op
= &yaffs_file_inode_operations
;
970 inode
->i_fop
= &yaffs_file_operations
;
971 inode
->i_mapping
->a_ops
=
972 &yaffs_file_address_operations
;
974 case S_IFDIR
: /* directory */
975 inode
->i_op
= &yaffs_dir_inode_operations
;
976 inode
->i_fop
= &yaffs_dir_operations
;
978 case S_IFLNK
: /* symlink */
979 inode
->i_op
= &yaffs_symlink_inode_operations
;
983 yaffs_InodeToObjectLV(inode
) = obj
;
985 obj
->myInode
= inode
;
989 ("yaffs_FileInode invalid parameters\n"));
994 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
1001 ("yaffs_get_inode for NULL super_block!!\n"));
1008 ("yaffs_get_inode for NULL object!!\n"));
1014 ("yaffs_get_inode for object %d\n", obj
->objectId
));
1016 inode
= Y_IGET(sb
, obj
->objectId
);
1020 /* NB Side effect: iget calls back to yaffs_read_inode(). */
1021 /* iget also increments the inode's i_count */
1022 /* NB You can't be holding grossLock or deadlock will happen! */
1027 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
1032 struct inode
*inode
;
1035 obj
= yaffs_DentryToObject(f
->f_dentry
);
1039 yaffs_GrossLock(dev
);
1041 inode
= f
->f_dentry
->d_inode
;
1043 if (!S_ISBLK(inode
->i_mode
) && f
->f_flags
& O_APPEND
)
1044 ipos
= inode
->i_size
;
1050 ("yaffs_file_write: hey obj is null!\n"));
1053 ("yaffs_file_write about to write writing %zu bytes"
1054 "to object %d at %d\n",
1055 n
, obj
->objectId
, ipos
));
1057 nWritten
= yaffs_WriteDataToFile(obj
, buf
, ipos
, n
, 0);
1060 ("yaffs_file_write writing %zu bytes, %d written at %d\n",
1061 n
, nWritten
, ipos
));
1066 if (ipos
> inode
->i_size
) {
1067 inode
->i_size
= ipos
;
1068 inode
->i_blocks
= (ipos
+ 511) >> 9;
1071 ("yaffs_file_write size updated to %d bytes, "
1073 ipos
, (int)(inode
->i_blocks
)));
1077 yaffs_GrossUnlock(dev
);
1078 return nWritten
== 0 ? -ENOSPC
: nWritten
;
1081 /* Space holding and freeing is done to ensure we have space available for write_begin/end */
1082 /* For now we just assume few parallel writes and check against a small number. */
1083 /* Todo: need to do this with a counter to handle parallel reads better */
1085 static ssize_t
yaffs_hold_space(struct file
*f
)
1093 obj
= yaffs_DentryToObject(f
->f_dentry
);
1097 yaffs_GrossLock(dev
);
1099 nFreeChunks
= yaffs_GetNumberOfFreeChunks(dev
);
1101 yaffs_GrossUnlock(dev
);
1103 return (nFreeChunks
> 20) ? 1 : 0;
1106 static void yaffs_release_space(struct file
*f
)
1112 obj
= yaffs_DentryToObject(f
->f_dentry
);
1116 yaffs_GrossLock(dev
);
1119 yaffs_GrossUnlock(dev
);
1122 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
)
1126 struct inode
*inode
= f
->f_dentry
->d_inode
;
1127 unsigned long offset
, curoffs
;
1128 struct ylist_head
*i
;
1131 char name
[YAFFS_MAX_NAME_LENGTH
+ 1];
1133 obj
= yaffs_DentryToObject(f
->f_dentry
);
1136 yaffs_GrossLock(dev
);
1140 T(YAFFS_TRACE_OS
, ("yaffs_readdir: starting at %d\n", (int)offset
));
1144 ("yaffs_readdir: entry . ino %d \n",
1145 (int)inode
->i_ino
));
1146 if (filldir(dirent
, ".", 1, offset
, inode
->i_ino
, DT_DIR
) < 0)
1153 ("yaffs_readdir: entry .. ino %d \n",
1154 (int)f
->f_dentry
->d_parent
->d_inode
->i_ino
));
1155 if (filldir(dirent
, "..", 2, offset
,
1156 f
->f_dentry
->d_parent
->d_inode
->i_ino
, DT_DIR
) < 0)
1164 /* If the directory has changed since the open or last call to
1165 readdir, rewind to after the 2 canned entries. */
1167 if (f
->f_version
!= inode
->i_version
) {
1170 f
->f_version
= inode
->i_version
;
1173 ylist_for_each(i
, &obj
->variant
.directoryVariant
.children
) {
1175 if (curoffs
>= offset
) {
1176 l
= ylist_entry(i
, yaffs_Object
, siblings
);
1178 yaffs_GetObjectName(l
, name
,
1179 YAFFS_MAX_NAME_LENGTH
+ 1);
1181 ("yaffs_readdir: %s inode %d\n", name
,
1182 yaffs_GetObjectInode(l
)));
1188 yaffs_GetObjectInode(l
),
1189 yaffs_GetObjectType(l
)) < 0)
1199 yaffs_GrossUnlock(dev
);
1205 * File creation. Allocate an inode, and we're done..
1208 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
1211 #define YCRED(x) (x->cred)
1214 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1215 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1218 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1222 struct inode
*inode
;
1224 yaffs_Object
*obj
= NULL
;
1227 yaffs_Object
*parent
= yaffs_InodeToObject(dir
);
1229 int error
= -ENOSPC
;
1230 uid_t uid
= YCRED(current
)->fsuid
;
1231 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: YCRED(current
)->fsgid
;
1233 if ((dir
->i_mode
& S_ISGID
) && S_ISDIR(mode
))
1238 ("yaffs_mknod: parent object %d type %d\n",
1239 parent
->objectId
, parent
->variantType
));
1242 ("yaffs_mknod: could not get parent object\n"));
1246 T(YAFFS_TRACE_OS
, ("yaffs_mknod: making oject for %s, "
1248 dentry
->d_name
.name
, mode
, rdev
));
1250 dev
= parent
->myDev
;
1252 yaffs_GrossLock(dev
);
1254 switch (mode
& S_IFMT
) {
1256 /* Special (socket, fifo, device...) */
1257 T(YAFFS_TRACE_OS
, ("yaffs_mknod: making special\n"));
1258 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1259 obj
= yaffs_MknodSpecial(parent
, dentry
->d_name
.name
, mode
, uid
,
1260 gid
, old_encode_dev(rdev
));
1262 obj
= yaffs_MknodSpecial(parent
, dentry
->d_name
.name
, mode
, uid
,
1266 case S_IFREG
: /* file */
1267 T(YAFFS_TRACE_OS
, ("yaffs_mknod: making file\n"));
1268 obj
= yaffs_MknodFile(parent
, dentry
->d_name
.name
, mode
, uid
,
1271 case S_IFDIR
: /* directory */
1273 ("yaffs_mknod: making directory\n"));
1274 obj
= yaffs_MknodDirectory(parent
, dentry
->d_name
.name
, mode
,
1277 case S_IFLNK
: /* symlink */
1278 T(YAFFS_TRACE_OS
, ("yaffs_mknod: making symlink\n"));
1279 obj
= NULL
; /* Do we ever get here? */
1283 /* Can not call yaffs_get_inode() with gross lock held */
1284 yaffs_GrossUnlock(dev
);
1287 inode
= yaffs_get_inode(dir
->i_sb
, mode
, rdev
, obj
);
1288 d_instantiate(dentry
, inode
);
1290 ("yaffs_mknod created object %d count = %d\n",
1291 obj
->objectId
, atomic_read(&inode
->i_count
)));
1295 ("yaffs_mknod failed making object\n"));
1302 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1305 T(YAFFS_TRACE_OS
, ("yaffs_mkdir\n"));
1306 retVal
= yaffs_mknod(dir
, dentry
, mode
| S_IFDIR
, 0);
1310 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1311 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1312 struct nameidata
*n
)
1314 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1317 T(YAFFS_TRACE_OS
, ("yaffs_create\n"));
1318 return yaffs_mknod(dir
, dentry
, mode
| S_IFREG
, 0);
1321 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
)
1328 ("yaffs_unlink %d:%s\n", (int)(dir
->i_ino
),
1329 dentry
->d_name
.name
));
1331 dev
= yaffs_InodeToObject(dir
)->myDev
;
1333 yaffs_GrossLock(dev
);
1335 retVal
= yaffs_Unlink(yaffs_InodeToObject(dir
), dentry
->d_name
.name
);
1337 if (retVal
== YAFFS_OK
) {
1338 dentry
->d_inode
->i_nlink
--;
1340 yaffs_GrossUnlock(dev
);
1341 mark_inode_dirty(dentry
->d_inode
);
1344 yaffs_GrossUnlock(dev
);
1351 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
1352 struct dentry
*dentry
)
1354 struct inode
*inode
= old_dentry
->d_inode
;
1355 yaffs_Object
*obj
= NULL
;
1356 yaffs_Object
*link
= NULL
;
1359 T(YAFFS_TRACE_OS
, ("yaffs_link\n"));
1361 obj
= yaffs_InodeToObject(inode
);
1364 yaffs_GrossLock(dev
);
1366 if (!S_ISDIR(inode
->i_mode
)) /* Don't link directories */
1367 link
= yaffs_Link(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1371 old_dentry
->d_inode
->i_nlink
= yaffs_GetObjectLinkCount(obj
);
1372 d_instantiate(dentry
, old_dentry
->d_inode
);
1373 atomic_inc(&old_dentry
->d_inode
->i_count
);
1375 ("yaffs_link link count %d i_count %d\n",
1376 old_dentry
->d_inode
->i_nlink
,
1377 atomic_read(&old_dentry
->d_inode
->i_count
)));
1380 yaffs_GrossUnlock(dev
);
1388 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
1389 const char *symname
)
1393 uid_t uid
= YCRED(current
)->fsuid
;
1394 gid_t gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: YCRED(current
)->fsgid
;
1396 T(YAFFS_TRACE_OS
, ("yaffs_symlink\n"));
1398 dev
= yaffs_InodeToObject(dir
)->myDev
;
1399 yaffs_GrossLock(dev
);
1400 obj
= yaffs_MknodSymLink(yaffs_InodeToObject(dir
), dentry
->d_name
.name
,
1401 S_IFLNK
| S_IRWXUGO
, uid
, gid
, symname
);
1402 yaffs_GrossUnlock(dev
);
1405 struct inode
*inode
;
1407 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1408 d_instantiate(dentry
, inode
);
1409 T(YAFFS_TRACE_OS
, ("symlink created OK\n"));
1412 T(YAFFS_TRACE_OS
, ("symlink not created\n"));
1418 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
1425 obj
= yaffs_DentryToObject(dentry
);
1429 T(YAFFS_TRACE_OS
, ("yaffs_sync_object\n"));
1430 yaffs_GrossLock(dev
);
1431 yaffs_FlushFile(obj
, 1);
1432 yaffs_GrossUnlock(dev
);
1437 * The VFS layer already does all the dentry stuff for rename.
1439 * NB: POSIX says you can rename an object over an old object of the same name
1441 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1442 struct inode
*new_dir
, struct dentry
*new_dentry
)
1445 int retVal
= YAFFS_FAIL
;
1446 yaffs_Object
*target
;
1448 T(YAFFS_TRACE_OS
, ("yaffs_rename\n"));
1449 dev
= yaffs_InodeToObject(old_dir
)->myDev
;
1451 yaffs_GrossLock(dev
);
1453 /* Check if the target is an existing directory that is not empty. */
1454 target
= yaffs_FindObjectByName(yaffs_InodeToObject(new_dir
),
1455 new_dentry
->d_name
.name
);
1459 if (target
&& target
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
&&
1460 !ylist_empty(&target
->variant
.directoryVariant
.children
)) {
1462 T(YAFFS_TRACE_OS
, ("target is non-empty dir\n"));
1464 retVal
= YAFFS_FAIL
;
1466 /* Now does unlinking internally using shadowing mechanism */
1467 T(YAFFS_TRACE_OS
, ("calling yaffs_RenameObject\n"));
1469 retVal
= yaffs_RenameObject(yaffs_InodeToObject(old_dir
),
1470 old_dentry
->d_name
.name
,
1471 yaffs_InodeToObject(new_dir
),
1472 new_dentry
->d_name
.name
);
1474 yaffs_GrossUnlock(dev
);
1476 if (retVal
== YAFFS_OK
) {
1478 new_dentry
->d_inode
->i_nlink
--;
1479 mark_inode_dirty(new_dentry
->d_inode
);
1488 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
)
1490 struct inode
*inode
= dentry
->d_inode
;
1495 ("yaffs_setattr of object %d\n",
1496 yaffs_InodeToObject(inode
)->objectId
));
1498 error
= inode_change_ok(inode
, attr
);
1500 dev
= yaffs_InodeToObject(inode
)->myDev
;
1501 yaffs_GrossLock(dev
);
1502 if (yaffs_SetAttributes(yaffs_InodeToObject(inode
), attr
) ==
1508 yaffs_GrossUnlock(dev
);
1510 error
= inode_setattr(inode
, attr
);
1515 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1516 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
1518 yaffs_Device
*dev
= yaffs_DentryToObject(dentry
)->myDev
;
1519 struct super_block
*sb
= dentry
->d_sb
;
1520 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1521 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
)
1523 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1525 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
)
1527 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1530 T(YAFFS_TRACE_OS
, ("yaffs_statfs\n"));
1532 yaffs_GrossLock(dev
);
1534 buf
->f_type
= YAFFS_MAGIC
;
1535 buf
->f_bsize
= sb
->s_blocksize
;
1536 buf
->f_namelen
= 255;
1538 if (dev
->nDataBytesPerChunk
& (dev
->nDataBytesPerChunk
- 1)) {
1539 /* Do this if chunk size is not a power of 2 */
1541 uint64_t bytesInDev
;
1544 bytesInDev
= ((uint64_t)((dev
->endBlock
- dev
->startBlock
+ 1))) *
1545 ((uint64_t)(dev
->nChunksPerBlock
* dev
->nDataBytesPerChunk
));
1547 do_div(bytesInDev
, sb
->s_blocksize
); /* bytesInDev becomes the number of blocks */
1548 buf
->f_blocks
= bytesInDev
;
1550 bytesFree
= ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev
))) *
1551 ((uint64_t)(dev
->nDataBytesPerChunk
));
1553 do_div(bytesFree
, sb
->s_blocksize
);
1555 buf
->f_bfree
= bytesFree
;
1557 } else if (sb
->s_blocksize
> dev
->nDataBytesPerChunk
) {
1560 (dev
->endBlock
- dev
->startBlock
+ 1) *
1561 dev
->nChunksPerBlock
/
1562 (sb
->s_blocksize
/ dev
->nDataBytesPerChunk
);
1564 yaffs_GetNumberOfFreeChunks(dev
) /
1565 (sb
->s_blocksize
/ dev
->nDataBytesPerChunk
);
1568 (dev
->endBlock
- dev
->startBlock
+ 1) *
1569 dev
->nChunksPerBlock
*
1570 (dev
->nDataBytesPerChunk
/ sb
->s_blocksize
);
1573 yaffs_GetNumberOfFreeChunks(dev
) *
1574 (dev
->nDataBytesPerChunk
/ sb
->s_blocksize
);
1579 buf
->f_bavail
= buf
->f_bfree
;
1581 yaffs_GrossUnlock(dev
);
1586 static int yaffs_do_sync_fs(struct super_block
*sb
)
1589 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1590 T(YAFFS_TRACE_OS
, ("yaffs_do_sync_fs\n"));
1593 yaffs_GrossLock(dev
);
1596 yaffs_FlushEntireDeviceCache(dev
);
1597 yaffs_CheckpointSave(dev
);
1600 yaffs_GrossUnlock(dev
);
1608 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1609 static void yaffs_write_super(struct super_block
*sb
)
1611 static int yaffs_write_super(struct super_block
*sb
)
1615 T(YAFFS_TRACE_OS
, ("yaffs_write_super\n"));
1616 if (yaffs_auto_checkpoint
>= 2)
1617 yaffs_do_sync_fs(sb
);
1618 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
1624 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1625 static int yaffs_sync_fs(struct super_block
*sb
, int wait
)
1627 static int yaffs_sync_fs(struct super_block
*sb
)
1630 T(YAFFS_TRACE_OS
, ("yaffs_sync_fs\n"));
1632 if (yaffs_auto_checkpoint
>= 1)
1633 yaffs_do_sync_fs(sb
);
1638 #ifdef YAFFS_USE_OWN_IGET
1640 static struct inode
*yaffs_iget(struct super_block
*sb
, unsigned long ino
)
1642 struct inode
*inode
;
1644 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1647 ("yaffs_iget for %lu\n", ino
));
1649 inode
= iget_locked(sb
, ino
);
1651 return ERR_PTR(-ENOMEM
);
1652 if (!(inode
->i_state
& I_NEW
))
1655 /* NB This is called as a side effect of other functions, but
1656 * we had to release the lock to prevent deadlocks, so
1657 * need to lock again.
1660 yaffs_GrossLock(dev
);
1662 obj
= yaffs_FindObjectByNumber(dev
, inode
->i_ino
);
1664 yaffs_FillInodeFromObject(inode
, obj
);
1666 yaffs_GrossUnlock(dev
);
1668 unlock_new_inode(inode
);
1674 static void yaffs_read_inode(struct inode
*inode
)
1676 /* NB This is called as a side effect of other functions, but
1677 * we had to release the lock to prevent deadlocks, so
1678 * need to lock again.
1682 yaffs_Device
*dev
= yaffs_SuperToDevice(inode
->i_sb
);
1685 ("yaffs_read_inode for %d\n", (int)inode
->i_ino
));
1687 yaffs_GrossLock(dev
);
1689 obj
= yaffs_FindObjectByNumber(dev
, inode
->i_ino
);
1691 yaffs_FillInodeFromObject(inode
, obj
);
1693 yaffs_GrossUnlock(dev
);
1698 static YLIST_HEAD(yaffs_dev_list
);
1700 #if 0 /* not used */
1701 static int yaffs_remount_fs(struct super_block
*sb
, int *flags
, char *data
)
1703 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1705 if (*flags
& MS_RDONLY
) {
1706 struct mtd_info
*mtd
= yaffs_SuperToDevice(sb
)->genericDevice
;
1709 ("yaffs_remount_fs: %s: RO\n", dev
->name
));
1711 yaffs_GrossLock(dev
);
1713 yaffs_FlushEntireDeviceCache(dev
);
1715 yaffs_CheckpointSave(dev
);
1720 yaffs_GrossUnlock(dev
);
1723 ("yaffs_remount_fs: %s: RW\n", dev
->name
));
1730 static void yaffs_put_super(struct super_block
*sb
)
1732 yaffs_Device
*dev
= yaffs_SuperToDevice(sb
);
1734 T(YAFFS_TRACE_OS
, ("yaffs_put_super\n"));
1736 yaffs_GrossLock(dev
);
1738 yaffs_FlushEntireDeviceCache(dev
);
1740 yaffs_CheckpointSave(dev
);
1742 if (dev
->putSuperFunc
)
1743 dev
->putSuperFunc(sb
);
1745 yaffs_Deinitialise(dev
);
1747 yaffs_GrossUnlock(dev
);
1749 /* we assume this is protected by lock_kernel() in mount/umount */
1750 ylist_del(&dev
->devList
);
1752 if (dev
->spareBuffer
) {
1753 YFREE(dev
->spareBuffer
);
1754 dev
->spareBuffer
= NULL
;
1761 static void yaffs_MTDPutSuper(struct super_block
*sb
)
1763 struct mtd_info
*mtd
= yaffs_SuperToDevice(sb
)->genericDevice
;
1768 put_mtd_device(mtd
);
1772 static void yaffs_MarkSuperBlockDirty(void *vsb
)
1774 struct super_block
*sb
= (struct super_block
*)vsb
;
1776 T(YAFFS_TRACE_OS
, ("yaffs_MarkSuperBlockDirty() sb = %p\n", sb
));
1783 int skip_checkpoint_read
;
1784 int skip_checkpoint_write
;
1788 #define MAX_OPT_LEN 20
1789 static int yaffs_parse_options(yaffs_options
*options
, const char *options_str
)
1791 char cur_opt
[MAX_OPT_LEN
+ 1];
1795 /* Parse through the options which is a comma seperated list */
1797 while (options_str
&& *options_str
&& !error
) {
1798 memset(cur_opt
, 0, MAX_OPT_LEN
+ 1);
1801 while (*options_str
&& *options_str
!= ',') {
1802 if (p
< MAX_OPT_LEN
) {
1803 cur_opt
[p
] = *options_str
;
1809 if (!strcmp(cur_opt
, "inband-tags"))
1810 options
->inband_tags
= 1;
1811 else if (!strcmp(cur_opt
, "no-cache"))
1812 options
->no_cache
= 1;
1813 else if (!strcmp(cur_opt
, "no-checkpoint-read"))
1814 options
->skip_checkpoint_read
= 1;
1815 else if (!strcmp(cur_opt
, "no-checkpoint-write"))
1816 options
->skip_checkpoint_write
= 1;
1817 else if (!strcmp(cur_opt
, "no-checkpoint")) {
1818 options
->skip_checkpoint_read
= 1;
1819 options
->skip_checkpoint_write
= 1;
1821 printk(KERN_INFO
"yaffs: Bad mount option \"%s\"\n",
1830 static struct super_block
*yaffs_internal_read_super(int yaffsVersion
,
1831 struct super_block
*sb
,
1832 void *data
, int silent
)
1835 struct inode
*inode
= NULL
;
1836 struct dentry
*root
;
1837 yaffs_Device
*dev
= 0;
1838 char devname_buf
[BDEVNAME_SIZE
+ 1];
1839 struct mtd_info
*mtd
;
1841 char *data_str
= (char *)data
;
1843 yaffs_options options
;
1845 sb
->s_magic
= YAFFS_MAGIC
;
1846 sb
->s_op
= &yaffs_super_ops
;
1847 sb
->s_flags
|= MS_NOATIME
;
1850 printk(KERN_INFO
"yaffs: sb is NULL\n");
1851 else if (!sb
->s_dev
)
1852 printk(KERN_INFO
"yaffs: sb->s_dev is NULL\n");
1853 else if (!yaffs_devname(sb
, devname_buf
))
1854 printk(KERN_INFO
"yaffs: devname is NULL\n");
1856 printk(KERN_INFO
"yaffs: dev is %d name is \"%s\"\n",
1858 yaffs_devname(sb
, devname_buf
));
1863 printk(KERN_INFO
"yaffs: passed flags \"%s\"\n", data_str
);
1865 memset(&options
, 0, sizeof(options
));
1867 if (yaffs_parse_options(&options
, data_str
)) {
1868 /* Option parsing failed */
1873 sb
->s_blocksize
= PAGE_CACHE_SIZE
;
1874 sb
->s_blocksize_bits
= PAGE_CACHE_SHIFT
;
1875 T(YAFFS_TRACE_OS
, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion
));
1877 ("yaffs_read_super: block size %d\n", (int)(sb
->s_blocksize
)));
1879 #ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
1881 ("yaffs: Write verification disabled. All guarantees "
1882 "null and void\n"));
1885 T(YAFFS_TRACE_ALWAYS
, ("yaffs: Attempting MTD mount on %u.%u, "
1887 MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
),
1888 yaffs_devname(sb
, devname_buf
)));
1890 /* Check it's an mtd device..... */
1891 if (MAJOR(sb
->s_dev
) != MTD_BLOCK_MAJOR
)
1892 return NULL
; /* This isn't an mtd device */
1894 /* Get the device */
1895 mtd
= get_mtd_device(NULL
, MINOR(sb
->s_dev
));
1897 T(YAFFS_TRACE_ALWAYS
,
1898 ("yaffs: MTD device #%u doesn't appear to exist\n",
1902 /* Check it's NAND */
1903 if (mtd
->type
!= MTD_NANDFLASH
) {
1904 T(YAFFS_TRACE_ALWAYS
,
1905 ("yaffs: MTD device is not NAND it's type %d\n", mtd
->type
));
1909 T(YAFFS_TRACE_OS
, (" erase %p\n", mtd
->erase
));
1910 T(YAFFS_TRACE_OS
, (" read %p\n", mtd
->read
));
1911 T(YAFFS_TRACE_OS
, (" write %p\n", mtd
->write
));
1912 T(YAFFS_TRACE_OS
, (" readoob %p\n", mtd
->read_oob
));
1913 T(YAFFS_TRACE_OS
, (" writeoob %p\n", mtd
->write_oob
));
1914 T(YAFFS_TRACE_OS
, (" block_isbad %p\n", mtd
->block_isbad
));
1915 T(YAFFS_TRACE_OS
, (" block_markbad %p\n", mtd
->block_markbad
));
1916 T(YAFFS_TRACE_OS
, (" %s %d\n", WRITE_SIZE_STR
, WRITE_SIZE(mtd
)));
1917 T(YAFFS_TRACE_OS
, (" oobsize %d\n", mtd
->oobsize
));
1918 T(YAFFS_TRACE_OS
, (" erasesize %d\n", mtd
->erasesize
));
1919 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
1920 T(YAFFS_TRACE_OS
, (" size %u\n", mtd
->size
));
1922 T(YAFFS_TRACE_OS
, (" size %lld\n", mtd
->size
));
1925 #ifdef CONFIG_YAFFS_AUTO_YAFFS2
1927 if (yaffsVersion
== 1 && WRITE_SIZE(mtd
) >= 2048) {
1928 T(YAFFS_TRACE_ALWAYS
, ("yaffs: auto selecting yaffs2\n"));
1932 /* Added NCB 26/5/2006 for completeness */
1933 if (yaffsVersion
== 2 && !options
.inband_tags
&& WRITE_SIZE(mtd
) == 512) {
1934 T(YAFFS_TRACE_ALWAYS
, ("yaffs: auto selecting yaffs1\n"));
1940 if (yaffsVersion
== 2) {
1941 /* Check for version 2 style functions */
1943 !mtd
->block_isbad
||
1944 !mtd
->block_markbad
||
1947 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1948 !mtd
->read_oob
|| !mtd
->write_oob
) {
1951 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
1953 T(YAFFS_TRACE_ALWAYS
,
1954 ("yaffs: MTD device does not support required "
1959 if ((WRITE_SIZE(mtd
) < YAFFS_MIN_YAFFS2_CHUNK_SIZE
||
1960 mtd
->oobsize
< YAFFS_MIN_YAFFS2_SPARE_SIZE
) &&
1961 !options
.inband_tags
) {
1962 T(YAFFS_TRACE_ALWAYS
,
1963 ("yaffs: MTD device does not have the "
1964 "right page sizes\n"));
1968 /* Check for V1 style functions */
1972 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1973 !mtd
->read_oob
|| !mtd
->write_oob
) {
1976 !mtd
->read_ecc
|| !mtd
->read_oob
|| !mtd
->write_oob
) {
1978 T(YAFFS_TRACE_ALWAYS
,
1979 ("yaffs: MTD device does not support required "
1984 if (WRITE_SIZE(mtd
) < YAFFS_BYTES_PER_CHUNK
||
1985 mtd
->oobsize
!= YAFFS_BYTES_PER_SPARE
) {
1986 T(YAFFS_TRACE_ALWAYS
,
1987 ("yaffs: MTD device does not support have the "
1988 "right page sizes\n"));
1993 /* OK, so if we got here, we have an MTD that's NAND and looks
1994 * like it has the right capabilities
1995 * Set the yaffs_Device up for mtd
1998 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1999 sb
->s_fs_info
= dev
= kmalloc(sizeof(yaffs_Device
), GFP_KERNEL
);
2001 sb
->u
.generic_sbp
= dev
= kmalloc(sizeof(yaffs_Device
), GFP_KERNEL
);
2004 /* Deep shit could not allocate device structure */
2005 T(YAFFS_TRACE_ALWAYS
,
2006 ("yaffs_read_super: Failed trying to allocate "
2007 "yaffs_Device. \n"));
2011 memset(dev
, 0, sizeof(yaffs_Device
));
2012 dev
->genericDevice
= mtd
;
2013 dev
->name
= mtd
->name
;
2015 /* Set up the memory size parameters.... */
2017 nBlocks
= YCALCBLOCKS(mtd
->size
, (YAFFS_CHUNKS_PER_BLOCK
* YAFFS_BYTES_PER_CHUNK
));
2019 dev
->startBlock
= 0;
2020 dev
->endBlock
= nBlocks
- 1;
2021 dev
->nChunksPerBlock
= YAFFS_CHUNKS_PER_BLOCK
;
2022 dev
->totalBytesPerChunk
= YAFFS_BYTES_PER_CHUNK
;
2023 dev
->nReservedBlocks
= 5;
2024 dev
->nShortOpCaches
= (options
.no_cache
) ? 0 : 10;
2025 dev
->inbandTags
= options
.inband_tags
;
2027 /* ... and the functions. */
2028 if (yaffsVersion
== 2) {
2029 dev
->writeChunkWithTagsToNAND
=
2030 nandmtd2_WriteChunkWithTagsToNAND
;
2031 dev
->readChunkWithTagsFromNAND
=
2032 nandmtd2_ReadChunkWithTagsFromNAND
;
2033 dev
->markNANDBlockBad
= nandmtd2_MarkNANDBlockBad
;
2034 dev
->queryNANDBlock
= nandmtd2_QueryNANDBlock
;
2035 dev
->spareBuffer
= YMALLOC(mtd
->oobsize
);
2037 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2038 dev
->totalBytesPerChunk
= mtd
->writesize
;
2039 dev
->nChunksPerBlock
= mtd
->erasesize
/ mtd
->writesize
;
2041 dev
->totalBytesPerChunk
= mtd
->oobblock
;
2042 dev
->nChunksPerBlock
= mtd
->erasesize
/ mtd
->oobblock
;
2044 nBlocks
= YCALCBLOCKS(mtd
->size
, mtd
->erasesize
);
2046 dev
->startBlock
= 0;
2047 dev
->endBlock
= nBlocks
- 1;
2049 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2050 /* use the MTD interface in yaffs_mtdif1.c */
2051 dev
->writeChunkWithTagsToNAND
=
2052 nandmtd1_WriteChunkWithTagsToNAND
;
2053 dev
->readChunkWithTagsFromNAND
=
2054 nandmtd1_ReadChunkWithTagsFromNAND
;
2055 dev
->markNANDBlockBad
= nandmtd1_MarkNANDBlockBad
;
2056 dev
->queryNANDBlock
= nandmtd1_QueryNANDBlock
;
2058 dev
->writeChunkToNAND
= nandmtd_WriteChunkToNAND
;
2059 dev
->readChunkFromNAND
= nandmtd_ReadChunkFromNAND
;
2063 /* ... and common functions */
2064 dev
->eraseBlockInNAND
= nandmtd_EraseBlockInNAND
;
2065 dev
->initialiseNAND
= nandmtd_InitialiseNAND
;
2067 dev
->putSuperFunc
= yaffs_MTDPutSuper
;
2069 dev
->superBlock
= (void *)sb
;
2070 dev
->markSuperBlockDirty
= yaffs_MarkSuperBlockDirty
;
2073 #ifndef CONFIG_YAFFS_DOES_ECC
2074 dev
->useNANDECC
= 1;
2077 #ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
2078 dev
->wideTnodesDisabled
= 1;
2081 dev
->skipCheckpointRead
= options
.skip_checkpoint_read
;
2082 dev
->skipCheckpointWrite
= options
.skip_checkpoint_write
;
2084 /* we assume this is protected by lock_kernel() in mount/umount */
2085 ylist_add_tail(&dev
->devList
, &yaffs_dev_list
);
2087 init_MUTEX(&dev
->grossLock
);
2089 yaffs_GrossLock(dev
);
2091 err
= yaffs_GutsInitialise(dev
);
2094 ("yaffs_read_super: guts initialised %s\n",
2095 (err
== YAFFS_OK
) ? "OK" : "FAILED"));
2097 /* Release lock before yaffs_get_inode() */
2098 yaffs_GrossUnlock(dev
);
2100 /* Create root inode */
2101 if (err
== YAFFS_OK
)
2102 inode
= yaffs_get_inode(sb
, S_IFDIR
| 0755, 0,
2108 inode
->i_op
= &yaffs_dir_inode_operations
;
2109 inode
->i_fop
= &yaffs_dir_operations
;
2111 T(YAFFS_TRACE_OS
, ("yaffs_read_super: got root inode\n"));
2113 root
= d_alloc_root(inode
);
2115 T(YAFFS_TRACE_OS
, ("yaffs_read_super: d_alloc_root done\n"));
2122 sb
->s_dirt
= !dev
->isCheckpointed
;
2123 T(YAFFS_TRACE_ALWAYS
,
2124 ("yaffs_read_super: isCheckpointed %d\n", dev
->isCheckpointed
));
2126 T(YAFFS_TRACE_OS
, ("yaffs_read_super: done\n"));
2131 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2132 static int yaffs_internal_read_super_mtd(struct super_block
*sb
, void *data
,
2135 return yaffs_internal_read_super(1, sb
, data
, silent
) ? 0 : -EINVAL
;
2138 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2139 static int yaffs_read_super(struct file_system_type
*fs
,
2140 int flags
, const char *dev_name
,
2141 void *data
, struct vfsmount
*mnt
)
2144 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2145 yaffs_internal_read_super_mtd
, mnt
);
2148 static struct super_block
*yaffs_read_super(struct file_system_type
*fs
,
2149 int flags
, const char *dev_name
,
2153 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2154 yaffs_internal_read_super_mtd
);
2158 static struct file_system_type yaffs_fs_type
= {
2159 .owner
= THIS_MODULE
,
2161 .get_sb
= yaffs_read_super
,
2162 .kill_sb
= kill_block_super
,
2163 .fs_flags
= FS_REQUIRES_DEV
,
2166 static struct super_block
*yaffs_read_super(struct super_block
*sb
, void *data
,
2169 return yaffs_internal_read_super(1, sb
, data
, silent
);
2172 static DECLARE_FSTYPE(yaffs_fs_type
, "yaffs", yaffs_read_super
,
2177 #ifdef CONFIG_YAFFS_YAFFS2
2179 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2180 static int yaffs2_internal_read_super_mtd(struct super_block
*sb
, void *data
,
2183 return yaffs_internal_read_super(2, sb
, data
, silent
) ? 0 : -EINVAL
;
2186 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2187 static int yaffs2_read_super(struct file_system_type
*fs
,
2188 int flags
, const char *dev_name
, void *data
,
2189 struct vfsmount
*mnt
)
2191 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2192 yaffs2_internal_read_super_mtd
, mnt
);
2195 static struct super_block
*yaffs2_read_super(struct file_system_type
*fs
,
2196 int flags
, const char *dev_name
,
2200 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2201 yaffs2_internal_read_super_mtd
);
2205 static struct file_system_type yaffs2_fs_type
= {
2206 .owner
= THIS_MODULE
,
2208 .get_sb
= yaffs2_read_super
,
2209 .kill_sb
= kill_block_super
,
2210 .fs_flags
= FS_REQUIRES_DEV
,
2213 static struct super_block
*yaffs2_read_super(struct super_block
*sb
,
2214 void *data
, int silent
)
2216 return yaffs_internal_read_super(2, sb
, data
, silent
);
2219 static DECLARE_FSTYPE(yaffs2_fs_type
, "yaffs2", yaffs2_read_super
,
2223 #endif /* CONFIG_YAFFS_YAFFS2 */
2225 static struct proc_dir_entry
*my_proc_entry
;
2227 static char *yaffs_dump_dev(char *buf
, yaffs_Device
* dev
)
2229 buf
+= sprintf(buf
, "startBlock......... %d\n", dev
->startBlock
);
2230 buf
+= sprintf(buf
, "endBlock........... %d\n", dev
->endBlock
);
2231 buf
+= sprintf(buf
, "totalBytesPerChunk. %d\n", dev
->totalBytesPerChunk
);
2232 buf
+= sprintf(buf
, "nDataBytesPerChunk. %d\n", dev
->nDataBytesPerChunk
);
2233 buf
+= sprintf(buf
, "chunkGroupBits..... %d\n", dev
->chunkGroupBits
);
2234 buf
+= sprintf(buf
, "chunkGroupSize..... %d\n", dev
->chunkGroupSize
);
2235 buf
+= sprintf(buf
, "nErasedBlocks...... %d\n", dev
->nErasedBlocks
);
2236 buf
+= sprintf(buf
, "nReservedBlocks.... %d\n", dev
->nReservedBlocks
);
2237 buf
+= sprintf(buf
, "blocksInCheckpoint. %d\n", dev
->blocksInCheckpoint
);
2238 buf
+= sprintf(buf
, "nTnodesCreated..... %d\n", dev
->nTnodesCreated
);
2239 buf
+= sprintf(buf
, "nFreeTnodes........ %d\n", dev
->nFreeTnodes
);
2240 buf
+= sprintf(buf
, "nObjectsCreated.... %d\n", dev
->nObjectsCreated
);
2241 buf
+= sprintf(buf
, "nFreeObjects....... %d\n", dev
->nFreeObjects
);
2242 buf
+= sprintf(buf
, "nFreeChunks........ %d\n", dev
->nFreeChunks
);
2243 buf
+= sprintf(buf
, "nPageWrites........ %d\n", dev
->nPageWrites
);
2244 buf
+= sprintf(buf
, "nPageReads......... %d\n", dev
->nPageReads
);
2245 buf
+= sprintf(buf
, "nBlockErasures..... %d\n", dev
->nBlockErasures
);
2246 buf
+= sprintf(buf
, "nGCCopies.......... %d\n", dev
->nGCCopies
);
2247 buf
+= sprintf(buf
, "garbageCollections. %d\n", dev
->garbageCollections
);
2248 buf
+= sprintf(buf
, "passiveGCs......... %d\n",
2249 dev
->passiveGarbageCollections
);
2250 buf
+= sprintf(buf
, "nRetriedWrites..... %d\n", dev
->nRetriedWrites
);
2251 buf
+= sprintf(buf
, "nShortOpCaches..... %d\n", dev
->nShortOpCaches
);
2252 buf
+= sprintf(buf
, "nRetireBlocks...... %d\n", dev
->nRetiredBlocks
);
2253 buf
+= sprintf(buf
, "eccFixed........... %d\n", dev
->eccFixed
);
2254 buf
+= sprintf(buf
, "eccUnfixed......... %d\n", dev
->eccUnfixed
);
2255 buf
+= sprintf(buf
, "tagsEccFixed....... %d\n", dev
->tagsEccFixed
);
2256 buf
+= sprintf(buf
, "tagsEccUnfixed..... %d\n", dev
->tagsEccUnfixed
);
2257 buf
+= sprintf(buf
, "cacheHits.......... %d\n", dev
->cacheHits
);
2258 buf
+= sprintf(buf
, "nDeletedFiles...... %d\n", dev
->nDeletedFiles
);
2259 buf
+= sprintf(buf
, "nUnlinkedFiles..... %d\n", dev
->nUnlinkedFiles
);
2261 sprintf(buf
, "nBackgroudDeletions %d\n", dev
->nBackgroundDeletions
);
2262 buf
+= sprintf(buf
, "useNANDECC......... %d\n", dev
->useNANDECC
);
2263 buf
+= sprintf(buf
, "isYaffs2........... %d\n", dev
->isYaffs2
);
2264 buf
+= sprintf(buf
, "inbandTags......... %d\n", dev
->inbandTags
);
2269 static int yaffs_proc_read(char *page
,
2271 off_t offset
, int count
, int *eof
, void *data
)
2273 struct ylist_head
*item
;
2278 /* Get proc_file_read() to step 'offset' by one on each sucessive call.
2279 * We use 'offset' (*ppos) to indicate where we are in devList.
2280 * This also assumes the user has posted a read buffer large
2281 * enough to hold the complete output; but that's life in /proc.
2286 /* Print header first */
2288 buf
+= sprintf(buf
, "YAFFS built:" __DATE__
" " __TIME__
2289 "\n%s\n%s\n", yaffs_fs_c_version
,
2290 yaffs_guts_c_version
);
2293 /* hold lock_kernel while traversing yaffs_dev_list */
2296 /* Locate and print the Nth entry. Order N-squared but N is small. */
2297 ylist_for_each(item
, &yaffs_dev_list
) {
2298 yaffs_Device
*dev
= ylist_entry(item
, yaffs_Device
, devList
);
2303 buf
+= sprintf(buf
, "\nDevice %d \"%s\"\n", n
, dev
->name
);
2304 buf
= yaffs_dump_dev(buf
, dev
);
2309 return buf
- page
< count
? buf
- page
: count
;
2313 * Set the verbosity of the warnings and error messages.
2315 * Note that the names can only be a..z or _ with the current code.
2320 unsigned mask_bitfield
;
2322 {"allocate", YAFFS_TRACE_ALLOCATE
},
2323 {"always", YAFFS_TRACE_ALWAYS
},
2324 {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS
},
2325 {"buffers", YAFFS_TRACE_BUFFERS
},
2326 {"bug", YAFFS_TRACE_BUG
},
2327 {"checkpt", YAFFS_TRACE_CHECKPOINT
},
2328 {"deletion", YAFFS_TRACE_DELETION
},
2329 {"erase", YAFFS_TRACE_ERASE
},
2330 {"error", YAFFS_TRACE_ERROR
},
2331 {"gc_detail", YAFFS_TRACE_GC_DETAIL
},
2332 {"gc", YAFFS_TRACE_GC
},
2333 {"mtd", YAFFS_TRACE_MTD
},
2334 {"nandaccess", YAFFS_TRACE_NANDACCESS
},
2335 {"os", YAFFS_TRACE_OS
},
2336 {"scan_debug", YAFFS_TRACE_SCAN_DEBUG
},
2337 {"scan", YAFFS_TRACE_SCAN
},
2338 {"tracing", YAFFS_TRACE_TRACING
},
2340 {"verify", YAFFS_TRACE_VERIFY
},
2341 {"verify_nand", YAFFS_TRACE_VERIFY_NAND
},
2342 {"verify_full", YAFFS_TRACE_VERIFY_FULL
},
2343 {"verify_all", YAFFS_TRACE_VERIFY_ALL
},
2345 {"write", YAFFS_TRACE_WRITE
},
2346 {"all", 0xffffffff},
2351 #define MAX_MASK_NAME_LENGTH 40
2352 static int yaffs_proc_write(struct file
*file
, const char *buf
,
2353 unsigned long count
, void *data
)
2355 unsigned rg
= 0, mask_bitfield
;
2359 char substring
[MAX_MASK_NAME_LENGTH
+ 1];
2365 rg
= yaffs_traceMask
;
2367 while (!done
&& (pos
< count
)) {
2369 while ((pos
< count
) && isspace(buf
[pos
]))
2386 mask_bitfield
= simple_strtoul(buf
+ pos
, &end
, 0);
2388 if (end
> buf
+ pos
) {
2389 mask_name
= "numeral";
2390 len
= end
- (buf
+ pos
);
2394 for (x
= buf
+ pos
, i
= 0;
2395 (*x
== '_' || (*x
>= 'a' && *x
<= 'z')) &&
2396 i
< MAX_MASK_NAME_LENGTH
; x
++, i
++, pos
++)
2398 substring
[i
] = '\0';
2400 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
2401 if (strcmp(substring
, mask_flags
[i
].mask_name
) == 0) {
2402 mask_name
= mask_flags
[i
].mask_name
;
2403 mask_bitfield
= mask_flags
[i
].mask_bitfield
;
2410 if (mask_name
!= NULL
) {
2414 rg
&= ~mask_bitfield
;
2417 rg
|= mask_bitfield
;
2423 rg
|= mask_bitfield
;
2429 yaffs_traceMask
= rg
| YAFFS_TRACE_ALWAYS
;
2431 printk(KERN_DEBUG
"new trace = 0x%08X\n", yaffs_traceMask
);
2433 if (rg
& YAFFS_TRACE_ALWAYS
) {
2434 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
2436 flag
= ((rg
& mask_flags
[i
].mask_bitfield
) == mask_flags
[i
].mask_bitfield
) ? '+' : '-';
2437 printk(KERN_DEBUG
"%c%s\n", flag
, mask_flags
[i
].mask_name
);
2444 /* Stuff to handle installation of file systems */
2445 struct file_system_to_install
{
2446 struct file_system_type
*fst
;
2450 static struct file_system_to_install fs_to_install
[] = {
2451 {&yaffs_fs_type
, 0},
2452 {&yaffs2_fs_type
, 0},
2456 static int __init
init_yaffs_fs(void)
2459 struct file_system_to_install
*fsinst
;
2461 T(YAFFS_TRACE_ALWAYS
,
2462 ("yaffs " __DATE__
" " __TIME__
" Installing. \n"));
2464 /* Install the proc_fs entry */
2465 my_proc_entry
= create_proc_entry("yaffs",
2469 if (my_proc_entry
) {
2470 my_proc_entry
->write_proc
= yaffs_proc_write
;
2471 my_proc_entry
->read_proc
= yaffs_proc_read
;
2472 my_proc_entry
->data
= NULL
;
2476 /* Now add the file system entries */
2478 fsinst
= fs_to_install
;
2480 while (fsinst
->fst
&& !error
) {
2481 error
= register_filesystem(fsinst
->fst
);
2483 fsinst
->installed
= 1;
2487 /* Any errors? uninstall */
2489 fsinst
= fs_to_install
;
2491 while (fsinst
->fst
) {
2492 if (fsinst
->installed
) {
2493 unregister_filesystem(fsinst
->fst
);
2494 fsinst
->installed
= 0;
2503 static void __exit
exit_yaffs_fs(void)
2506 struct file_system_to_install
*fsinst
;
2508 T(YAFFS_TRACE_ALWAYS
, ("yaffs " __DATE__
" " __TIME__
2511 remove_proc_entry("yaffs", YPROC_ROOT
);
2513 fsinst
= fs_to_install
;
2515 while (fsinst
->fst
) {
2516 if (fsinst
->installed
) {
2517 unregister_filesystem(fsinst
->fst
);
2518 fsinst
->installed
= 0;
2524 module_init(init_yaffs_fs
)
2525 module_exit(exit_yaffs_fs
)
2527 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
2528 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2006");
2529 MODULE_LICENSE("GPL");