2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2011 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 struct yaffs_dev associated with
29 * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this
31 * >> inode->u.generic_ip points to the associated struct yaffs_obj.
35 * There are two variants of the VFS glue code. This variant should compile
36 * for any version of Linux.
38 #include <linux/version.h>
40 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
41 #define YAFFS_COMPILE_BACKGROUND
42 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23))
43 #define YAFFS_COMPILE_FREEZER
47 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
48 #define YAFFS_COMPILE_EXPORTFS
51 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
52 #define YAFFS_USE_SETATTR_COPY
53 #define YAFFS_USE_TRUNCATE_SETSIZE
55 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
56 #define YAFFS_HAS_EVICT_INODE
59 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
60 #define YAFFS_NEW_FOLLOW_LINK 1
62 #define YAFFS_NEW_FOLLOW_LINK 0
65 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
66 #define YAFFS_HAS_WRITE_SUPER
70 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
71 #include <linux/config.h>
74 #include <linux/kernel.h>
75 #include <linux/module.h>
76 #include <linux/slab.h>
77 #include <linux/init.h>
79 #include <linux/proc_fs.h>
80 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
81 #include <linux/smp_lock.h>
83 #include <linux/pagemap.h>
84 #include <linux/mtd/mtd.h>
85 #include <linux/interrupt.h>
86 #include <linux/string.h>
87 #include <linux/ctype.h>
89 #if (YAFFS_NEW_FOLLOW_LINK == 1)
90 #include <linux/namei.h>
93 #ifdef YAFFS_COMPILE_EXPORTFS
94 #include <linux/exportfs.h>
97 #ifdef YAFFS_COMPILE_BACKGROUND
98 #include <linux/kthread.h>
99 #include <linux/delay.h>
101 #ifdef YAFFS_COMPILE_FREEZER
102 #include <linux/freezer.h>
105 #include <asm/div64.h>
107 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
109 #include <linux/statfs.h>
111 #define UnlockPage(p) unlock_page(p)
112 #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
114 /* FIXME: use sb->s_id instead ? */
115 #define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
119 #include <linux/locks.h>
120 #define BDEVNAME_SIZE 0
121 #define yaffs_devname(sb, buf) kdevname(sb->s_dev)
123 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
124 /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
130 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
131 #define YPROC_ROOT (&proc_root)
133 #define YPROC_ROOT NULL
136 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
137 #define Y_INIT_TIMER(a) init_timer(a)
139 #define Y_INIT_TIMER(a) init_timer_on_stack(a)
142 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
143 #define YAFFS_USE_WRITE_BEGIN_END 1
145 #define YAFFS_USE_WRITE_BEGIN_END 0
148 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
149 #define YAFFS_SUPER_HAS_DIRTY
153 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
154 #define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0)
157 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
158 static uint32_t YCALCBLOCKS(uint64_t partition_size
, uint32_t block_size
)
160 uint64_t result
= partition_size
;
161 do_div(result
, block_size
);
162 return (uint32_t) result
;
165 #define YCALCBLOCKS(s, b) ((s)/(b))
168 #include <linux/uaccess.h>
169 #include <linux/mtd/mtd.h>
171 #include "yportenv.h"
172 #include "yaffs_trace.h"
173 #include "yaffs_guts.h"
174 #include "yaffs_attribs.h"
176 #include "yaffs_linux.h"
178 #include "yaffs_mtdif.h"
179 #include "yaffs_packedtags2.h"
180 #include "yaffs_getblockinfo.h"
182 unsigned int yaffs_trace_mask
=
183 YAFFS_TRACE_BAD_BLOCKS
|
187 unsigned int yaffs_wr_attempts
= YAFFS_WR_ATTEMPTS
;
188 unsigned int yaffs_auto_checkpoint
= 1;
189 unsigned int yaffs_gc_control
= 1;
190 unsigned int yaffs_bg_enable
= 1;
191 unsigned int yaffs_auto_select
= 1;
192 /* Module Parameters */
193 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
194 module_param(yaffs_trace_mask
, uint
, 0644);
195 module_param(yaffs_wr_attempts
, uint
, 0644);
196 module_param(yaffs_auto_checkpoint
, uint
, 0644);
197 module_param(yaffs_gc_control
, uint
, 0644);
198 module_param(yaffs_bg_enable
, uint
, 0644);
200 MODULE_PARM(yaffs_trace_mask
, "i");
201 MODULE_PARM(yaffs_wr_attempts
, "i");
202 MODULE_PARM(yaffs_auto_checkpoint
, "i");
203 MODULE_PARM(yaffs_gc_control
, "i");
206 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
207 /* use iget and read_inode */
208 #define Y_IGET(sb, inum) iget((sb), (inum))
211 /* Call local equivalent */
212 #define YAFFS_USE_OWN_IGET
213 #define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
217 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
218 #define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private)
220 #define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
223 #define yaffs_inode_to_obj(iptr) \
224 ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
225 #define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode)
227 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
228 #define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info)
230 #define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp)
233 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
234 #define Y_CLEAR_INODE(i) clear_inode(i)
236 #define Y_CLEAR_INODE(i) end_writeback(i)
240 #define update_dir_time(dir) do {\
241 (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
244 static void yaffs_fill_inode_from_obj(struct inode
*inode
,
245 struct yaffs_obj
*obj
);
248 static void yaffs_gross_lock(struct yaffs_dev
*dev
)
250 yaffs_trace(YAFFS_TRACE_LOCK
, "yaffs locking %p", current
);
251 mutex_lock(&(yaffs_dev_to_lc(dev
)->gross_lock
));
252 yaffs_trace(YAFFS_TRACE_LOCK
, "yaffs locked %p", current
);
255 static void yaffs_gross_unlock(struct yaffs_dev
*dev
)
257 yaffs_trace(YAFFS_TRACE_LOCK
, "yaffs unlocking %p", current
);
258 mutex_unlock(&(yaffs_dev_to_lc(dev
)->gross_lock
));
262 static int yaffs_readpage_nolock(struct file
*f
, struct page
*pg
)
264 /* Lifted from jffs2 */
266 struct yaffs_obj
*obj
;
267 unsigned char *pg_buf
;
269 loff_t pos
= ((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
;
270 struct yaffs_dev
*dev
;
272 yaffs_trace(YAFFS_TRACE_OS
,
273 "yaffs_readpage_nolock at %lld, size %08x",
275 (unsigned)PAGE_CACHE_SIZE
);
277 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
281 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
282 BUG_ON(!PageLocked(pg
));
289 /* FIXME: Can kmap fail? */
291 yaffs_gross_lock(dev
);
293 ret
= yaffs_file_rd(obj
, pg_buf
, pos
, PAGE_CACHE_SIZE
);
295 yaffs_gross_unlock(dev
);
301 ClearPageUptodate(pg
);
308 flush_dcache_page(pg
);
311 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_readpage_nolock done");
315 static int yaffs_readpage_unlock(struct file
*f
, struct page
*pg
)
317 int ret
= yaffs_readpage_nolock(f
, pg
);
322 static int yaffs_readpage(struct file
*f
, struct page
*pg
)
326 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_readpage");
327 ret
= yaffs_readpage_unlock(f
, pg
);
328 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_readpage done");
333 static void yaffs_set_super_dirty_val(struct yaffs_dev
*dev
, int val
)
335 struct yaffs_linux_context
*lc
= yaffs_dev_to_lc(dev
);
340 # ifdef YAFFS_SUPER_HAS_DIRTY
342 struct super_block
*sb
= lc
->super
;
351 static void yaffs_set_super_dirty(struct yaffs_dev
*dev
)
353 yaffs_set_super_dirty_val(dev
, 1);
356 static void yaffs_clear_super_dirty(struct yaffs_dev
*dev
)
358 yaffs_set_super_dirty_val(dev
, 0);
361 static int yaffs_check_super_dirty(struct yaffs_dev
*dev
)
363 struct yaffs_linux_context
*lc
= yaffs_dev_to_lc(dev
);
368 # ifdef YAFFS_SUPER_HAS_DIRTY
370 struct super_block
*sb
= lc
->super
;
372 if (sb
&& sb
->s_dirt
)
380 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
381 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
)
383 static int yaffs_writepage(struct page
*page
)
386 struct yaffs_dev
*dev
;
387 struct address_space
*mapping
= page
->mapping
;
389 unsigned long end_index
;
391 struct yaffs_obj
*obj
;
398 inode
= mapping
->host
;
401 i_size
= i_size_read(inode
);
403 end_index
= i_size
>> PAGE_CACHE_SHIFT
;
405 if (page
->index
< end_index
)
406 n_bytes
= PAGE_CACHE_SIZE
;
408 n_bytes
= i_size
& (PAGE_CACHE_SIZE
- 1);
410 if (page
->index
> end_index
|| !n_bytes
) {
411 yaffs_trace(YAFFS_TRACE_OS
,
412 "yaffs_writepage at %lld, inode size = %lld!!",
413 ((loff_t
)page
->index
) << PAGE_CACHE_SHIFT
,
415 yaffs_trace(YAFFS_TRACE_OS
,
418 zero_user_segment(page
, 0, PAGE_CACHE_SIZE
);
419 set_page_writeback(page
);
421 end_page_writeback(page
);
426 if (n_bytes
!= PAGE_CACHE_SIZE
)
427 zero_user_segment(page
, n_bytes
, PAGE_CACHE_SIZE
);
433 obj
= yaffs_inode_to_obj(inode
);
435 yaffs_gross_lock(dev
);
437 yaffs_trace(YAFFS_TRACE_OS
,
438 "yaffs_writepage at %lld, size %08x",
439 ((loff_t
)page
->index
) << PAGE_CACHE_SHIFT
, n_bytes
);
440 yaffs_trace(YAFFS_TRACE_OS
,
441 "writepag0: obj = %lld, ino = %lld",
442 obj
->variant
.file_variant
.file_size
, inode
->i_size
);
444 n_written
= yaffs_wr_file(obj
, buffer
,
445 ((loff_t
)page
->index
) << PAGE_CACHE_SHIFT
, n_bytes
, 0);
447 yaffs_set_super_dirty(dev
);
449 yaffs_trace(YAFFS_TRACE_OS
,
450 "writepag1: obj = %lld, ino = %lld",
451 obj
->variant
.file_variant
.file_size
, inode
->i_size
);
453 yaffs_gross_unlock(dev
);
456 set_page_writeback(page
);
458 end_page_writeback(page
);
461 return (n_written
== n_bytes
) ? 0 : -ENOSPC
;
464 /* Space holding and freeing is done to ensure we have space available for write_begin/end */
465 /* For now we just assume few parallel writes and check against a small number. */
466 /* Todo: need to do this with a counter to handle parallel reads better */
468 static ssize_t
yaffs_hold_space(struct file
*f
)
470 struct yaffs_obj
*obj
;
471 struct yaffs_dev
*dev
;
475 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
479 yaffs_gross_lock(dev
);
481 n_free_chunks
= yaffs_get_n_free_chunks(dev
);
483 yaffs_gross_unlock(dev
);
485 return (n_free_chunks
> 20) ? 1 : 0;
488 static void yaffs_release_space(struct file
*f
)
490 struct yaffs_obj
*obj
;
491 struct yaffs_dev
*dev
;
493 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
497 yaffs_gross_lock(dev
);
499 yaffs_gross_unlock(dev
);
502 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
503 static int yaffs_write_begin(struct file
*filp
, struct address_space
*mapping
,
504 loff_t pos
, unsigned len
, unsigned flags
,
505 struct page
**pagep
, void **fsdata
)
507 struct page
*pg
= NULL
;
508 pgoff_t index
= pos
>> PAGE_CACHE_SHIFT
;
514 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
515 pg
= grab_cache_page_write_begin(mapping
, index
, flags
);
517 pg
= __grab_cache_page(mapping
, index
);
525 yaffs_trace(YAFFS_TRACE_OS
,
526 "start yaffs_write_begin index %d(%x) uptodate %d",
527 (int)index
, (int)index
, Page_Uptodate(pg
) ? 1 : 0);
530 space_held
= yaffs_hold_space(filp
);
537 /* Update page if required */
539 if (!Page_Uptodate(pg
))
540 ret
= yaffs_readpage_nolock(filp
, pg
);
545 /* Happy path return */
546 yaffs_trace(YAFFS_TRACE_OS
, "end yaffs_write_begin - ok");
551 yaffs_trace(YAFFS_TRACE_OS
,
552 "end yaffs_write_begin fail returning %d", ret
);
554 yaffs_release_space(filp
);
557 page_cache_release(pg
);
564 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
565 unsigned offset
, unsigned to
)
567 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_prepair_write");
569 if (!Page_Uptodate(pg
))
570 return yaffs_readpage_nolock(f
, pg
);
576 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
579 struct yaffs_obj
*obj
;
583 struct yaffs_dev
*dev
;
585 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
588 yaffs_trace(YAFFS_TRACE_OS
,
589 "yaffs_file_write: hey obj is null!");
595 yaffs_gross_lock(dev
);
597 inode
= f
->f_dentry
->d_inode
;
599 if (!S_ISBLK(inode
->i_mode
) && f
->f_flags
& O_APPEND
)
600 ipos
= inode
->i_size
;
604 yaffs_trace(YAFFS_TRACE_OS
,
605 "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
606 (unsigned)n
, (unsigned)n
, obj
->obj_id
, ipos
);
608 n_written
= yaffs_wr_file(obj
, buf
, ipos
, n
, 0);
610 yaffs_set_super_dirty(dev
);
612 yaffs_trace(YAFFS_TRACE_OS
,
613 "yaffs_file_write: %d(%x) bytes written",
614 (unsigned)n
, (unsigned)n
);
619 if (ipos
> inode
->i_size
) {
620 inode
->i_size
= ipos
;
621 inode
->i_blocks
= (ipos
+ 511) >> 9;
623 yaffs_trace(YAFFS_TRACE_OS
,
624 "yaffs_file_write size updated to %lld bytes, %d blocks",
625 ipos
, (int)(inode
->i_blocks
));
629 yaffs_gross_unlock(dev
);
630 return (n_written
== 0) && (n
> 0) ? -ENOSPC
: n_written
;
634 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
635 static int yaffs_write_end(struct file
*filp
, struct address_space
*mapping
,
636 loff_t pos
, unsigned len
, unsigned copied
,
637 struct page
*pg
, void *fsdadata
)
641 uint32_t offset_into_page
= pos
& (PAGE_CACHE_SIZE
- 1);
644 addr
= kva
+ offset_into_page
;
646 yaffs_trace(YAFFS_TRACE_OS
,
647 "yaffs_write_end addr %p pos %lld n_bytes %d",
650 ret
= yaffs_file_write(filp
, addr
, copied
, &pos
);
653 yaffs_trace(YAFFS_TRACE_OS
,
654 "yaffs_write_end not same size ret %d copied %d",
661 yaffs_release_space(filp
);
663 page_cache_release(pg
);
668 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
673 loff_t pos
= (((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
) + offset
;
674 int n_bytes
= to
- offset
;
680 yaffs_trace(YAFFS_TRACE_OS
,
681 "yaffs_commit_write addr %p pos %lld n_bytes %d",
684 n_written
= yaffs_file_write(f
, addr
, n_bytes
, &pos
);
686 if (n_written
!= n_bytes
) {
687 yaffs_trace(YAFFS_TRACE_OS
,
688 "yaffs_commit_write not same size n_written %d n_bytes %d",
694 yaffs_trace(YAFFS_TRACE_OS
,
695 "yaffs_commit_write returning %d",
696 n_written
== n_bytes
? 0 : n_written
);
698 return n_written
== n_bytes
? 0 : n_written
;
702 static struct address_space_operations yaffs_file_address_operations
= {
703 .readpage
= yaffs_readpage
,
704 .writepage
= yaffs_writepage
,
705 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
706 .write_begin
= yaffs_write_begin
,
707 .write_end
= yaffs_write_end
,
709 .prepare_write
= yaffs_prepare_write
,
710 .commit_write
= yaffs_commit_write
,
715 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
716 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
)
718 static int yaffs_file_flush(struct file
*file
)
721 struct yaffs_obj
*obj
= yaffs_dentry_to_obj(file
->f_dentry
);
723 struct yaffs_dev
*dev
= obj
->my_dev
;
725 yaffs_trace(YAFFS_TRACE_OS
,
726 "yaffs_file_flush object %d (%s)",
728 obj
->dirty
? "dirty" : "clean");
730 yaffs_gross_lock(dev
);
732 yaffs_flush_file(obj
, 1, 0);
734 yaffs_gross_unlock(dev
);
740 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
741 static int yaffs_sync_object(struct file
*file
, loff_t start
, loff_t end
, int datasync
)
742 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
743 static int yaffs_sync_object(struct file
*file
, int datasync
)
745 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
749 struct yaffs_obj
*obj
;
750 struct yaffs_dev
*dev
;
751 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
752 struct dentry
*dentry
= file
->f_path
.dentry
;
755 obj
= yaffs_dentry_to_obj(dentry
);
759 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
,
760 "yaffs_sync_object");
761 yaffs_gross_lock(dev
);
762 yaffs_flush_file(obj
, 1, datasync
);
763 yaffs_gross_unlock(dev
);
768 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
769 static const struct file_operations yaffs_file_operations
= {
770 .read
= do_sync_read
,
771 .write
= do_sync_write
,
772 .aio_read
= generic_file_aio_read
,
773 .aio_write
= generic_file_aio_write
,
774 .mmap
= generic_file_mmap
,
775 .flush
= yaffs_file_flush
,
776 .fsync
= yaffs_sync_object
,
777 .splice_read
= generic_file_splice_read
,
778 .splice_write
= generic_file_splice_write
,
779 .llseek
= generic_file_llseek
,
782 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
784 static const struct file_operations yaffs_file_operations
= {
785 .read
= do_sync_read
,
786 .write
= do_sync_write
,
787 .aio_read
= generic_file_aio_read
,
788 .aio_write
= generic_file_aio_write
,
789 .mmap
= generic_file_mmap
,
790 .flush
= yaffs_file_flush
,
791 .fsync
= yaffs_sync_object
,
792 .sendfile
= generic_file_sendfile
,
797 static const struct file_operations yaffs_file_operations
= {
798 .read
= generic_file_read
,
799 .write
= generic_file_write
,
800 .mmap
= generic_file_mmap
,
801 .flush
= yaffs_file_flush
,
802 .fsync
= yaffs_sync_object
,
803 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
804 .sendfile
= generic_file_sendfile
,
812 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
813 static void zero_user_segment(struct page
*page
, unsigned start
, unsigned end
)
815 void *kaddr
= kmap_atomic(page
, KM_USER0
);
816 memset(kaddr
+ start
, 0, end
- start
);
817 kunmap_atomic(kaddr
, KM_USER0
);
818 flush_dcache_page(page
);
823 static int yaffs_vfs_setsize(struct inode
*inode
, loff_t newsize
)
825 #ifdef YAFFS_USE_TRUNCATE_SETSIZE
826 truncate_setsize(inode
, newsize
);
829 truncate_inode_pages(&inode
->i_data
, newsize
);
836 static int yaffs_vfs_setattr(struct inode
*inode
, struct iattr
*attr
)
838 #ifdef YAFFS_USE_SETATTR_COPY
839 setattr_copy(inode
, attr
);
842 return inode_setattr(inode
, attr
);
847 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
)
849 struct inode
*inode
= dentry
->d_inode
;
851 struct yaffs_dev
*dev
;
853 yaffs_trace(YAFFS_TRACE_OS
,
854 "yaffs_setattr of object %d",
855 yaffs_inode_to_obj(inode
)->obj_id
);
857 /* Fail if a requested resize >= 2GB */
858 if (attr
->ia_valid
& ATTR_SIZE
&& (attr
->ia_size
>> 31))
863 error
= inode_change_ok(inode
, attr
);
867 error
= yaffs_vfs_setattr(inode
, attr
);
868 yaffs_trace(YAFFS_TRACE_OS
, "inode_setattr called");
869 if (attr
->ia_valid
& ATTR_SIZE
) {
870 yaffs_vfs_setsize(inode
, attr
->ia_size
);
871 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
874 dev
= yaffs_inode_to_obj(inode
)->my_dev
;
875 if (attr
->ia_valid
& ATTR_SIZE
) {
876 yaffs_trace(YAFFS_TRACE_OS
,
878 (int)(attr
->ia_size
),
879 (int)(attr
->ia_size
));
881 yaffs_gross_lock(dev
);
882 result
= yaffs_set_attribs(yaffs_inode_to_obj(inode
), attr
);
883 if (result
== YAFFS_OK
) {
888 yaffs_gross_unlock(dev
);
892 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_setattr done returning %d", error
);
897 static int yaffs_setxattr(struct dentry
*dentry
, const char *name
,
898 const void *value
, size_t size
, int flags
)
900 struct inode
*inode
= dentry
->d_inode
;
902 struct yaffs_dev
*dev
;
903 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
905 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_setxattr of object %d", obj
->obj_id
);
910 yaffs_gross_lock(dev
);
911 result
= yaffs_set_xattrib(obj
, name
, value
, size
, flags
);
912 if (result
== YAFFS_OK
)
916 yaffs_gross_unlock(dev
);
919 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_setxattr done returning %d", error
);
924 static ssize_t
yaffs_getxattr(struct dentry
* dentry
, const char *name
,
925 void *buff
, size_t size
)
927 struct inode
*inode
= dentry
->d_inode
;
929 struct yaffs_dev
*dev
;
930 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
932 yaffs_trace(YAFFS_TRACE_OS
,
933 "yaffs_getxattr \"%s\" from object %d",
938 yaffs_gross_lock(dev
);
939 error
= yaffs_get_xattrib(obj
, name
, buff
, size
);
940 yaffs_gross_unlock(dev
);
943 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_getxattr done returning %d", error
);
948 static int yaffs_removexattr(struct dentry
*dentry
, const char *name
)
950 struct inode
*inode
= dentry
->d_inode
;
952 struct yaffs_dev
*dev
;
953 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
955 yaffs_trace(YAFFS_TRACE_OS
,
956 "yaffs_removexattr of object %d", obj
->obj_id
);
961 yaffs_gross_lock(dev
);
962 result
= yaffs_remove_xattrib(obj
, name
);
963 if (result
== YAFFS_OK
)
967 yaffs_gross_unlock(dev
);
970 yaffs_trace(YAFFS_TRACE_OS
,
971 "yaffs_removexattr done returning %d", error
);
976 static ssize_t
yaffs_listxattr(struct dentry
* dentry
, char *buff
, size_t size
)
978 struct inode
*inode
= dentry
->d_inode
;
980 struct yaffs_dev
*dev
;
981 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
983 yaffs_trace(YAFFS_TRACE_OS
,
984 "yaffs_listxattr of object %d", obj
->obj_id
);
988 yaffs_gross_lock(dev
);
989 error
= yaffs_list_xattrib(obj
, buff
, size
);
990 yaffs_gross_unlock(dev
);
993 yaffs_trace(YAFFS_TRACE_OS
,
994 "yaffs_listxattr done returning %d", error
);
1000 static const struct inode_operations yaffs_file_inode_operations
= {
1001 .setattr
= yaffs_setattr
,
1002 .setxattr
= yaffs_setxattr
,
1003 .getxattr
= yaffs_getxattr
,
1004 .listxattr
= yaffs_listxattr
,
1005 .removexattr
= yaffs_removexattr
,
1009 static int yaffs_readlink(struct dentry
*dentry
, char __user
* buffer
,
1012 unsigned char *alias
;
1015 struct yaffs_dev
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
1017 yaffs_gross_lock(dev
);
1019 alias
= yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry
));
1021 yaffs_gross_unlock(dev
);
1026 ret
= vfs_readlink(dentry
, buffer
, buflen
, alias
);
1031 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1032 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
1036 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
1040 unsigned char *alias
;
1042 struct yaffs_dev
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
1044 yaffs_gross_lock(dev
);
1046 alias
= yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry
));
1047 yaffs_gross_unlock(dev
);
1053 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1054 nd_set_link(nd
, alias
);
1058 ret
= ERR_PTR(ret_int
);
1061 ret
= vfs_follow_link(nd
, alias
);
1071 #ifdef YAFFS_HAS_PUT_INODE
1073 /* For now put inode is just for debugging
1074 * Put inode is called when the inode **structure** is put.
1076 static void yaffs_put_inode(struct inode
*inode
)
1078 yaffs_trace(YAFFS_TRACE_OS
,
1079 "yaffs_put_inode: ino %d, count %d"),
1080 (int)inode
->i_ino
, atomic_read(&inode
->i_count
);
1085 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1086 void yaffs_put_link(struct dentry
*dentry
, struct nameidata
*nd
, void *alias
)
1092 static const struct inode_operations yaffs_symlink_inode_operations
= {
1093 .readlink
= yaffs_readlink
,
1094 .follow_link
= yaffs_follow_link
,
1095 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1096 .put_link
= yaffs_put_link
,
1098 .setattr
= yaffs_setattr
,
1099 .setxattr
= yaffs_setxattr
,
1100 .getxattr
= yaffs_getxattr
,
1101 .listxattr
= yaffs_listxattr
,
1102 .removexattr
= yaffs_removexattr
,
1105 #ifdef YAFFS_USE_OWN_IGET
1107 static struct inode
*yaffs_iget(struct super_block
*sb
, unsigned long ino
)
1109 struct inode
*inode
;
1110 struct yaffs_obj
*obj
;
1111 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
1113 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_iget for %lu", ino
);
1115 inode
= iget_locked(sb
, ino
);
1117 return ERR_PTR(-ENOMEM
);
1118 if (!(inode
->i_state
& I_NEW
))
1121 /* NB This is called as a side effect of other functions, but
1122 * we had to release the lock to prevent deadlocks, so
1123 * need to lock again.
1126 yaffs_gross_lock(dev
);
1128 obj
= yaffs_find_by_number(dev
, inode
->i_ino
);
1130 yaffs_fill_inode_from_obj(inode
, obj
);
1132 yaffs_gross_unlock(dev
);
1134 unlock_new_inode(inode
);
1140 static void yaffs_read_inode(struct inode
*inode
)
1142 /* NB This is called as a side effect of other functions, but
1143 * we had to release the lock to prevent deadlocks, so
1144 * need to lock again.
1147 struct yaffs_obj
*obj
;
1148 struct yaffs_dev
*dev
= yaffs_super_to_dev(inode
->i_sb
);
1150 yaffs_trace(YAFFS_TRACE_OS
,
1151 "yaffs_read_inode for %d", (int)inode
->i_ino
);
1153 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1154 yaffs_gross_lock(dev
);
1156 obj
= yaffs_find_by_number(dev
, inode
->i_ino
);
1158 yaffs_fill_inode_from_obj(inode
, obj
);
1160 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1161 yaffs_gross_unlock(dev
);
1168 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
1169 struct yaffs_obj
*obj
)
1171 struct inode
*inode
;
1174 yaffs_trace(YAFFS_TRACE_OS
,
1175 "yaffs_get_inode for NULL super_block!!");
1181 yaffs_trace(YAFFS_TRACE_OS
,
1182 "yaffs_get_inode for NULL object!!");
1187 yaffs_trace(YAFFS_TRACE_OS
,
1188 "yaffs_get_inode for object %d", obj
->obj_id
);
1190 inode
= Y_IGET(sb
, obj
->obj_id
);
1194 /* NB Side effect: iget calls back to yaffs_read_inode(). */
1195 /* iget also increments the inode's i_count */
1196 /* NB You can't be holding gross_lock or deadlock will happen! */
1203 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
1206 #define YCRED(x) (x->cred)
1209 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1210 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
1212 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1213 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1216 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1220 struct inode
*inode
;
1222 struct yaffs_obj
*obj
= NULL
;
1223 struct yaffs_dev
*dev
;
1225 struct yaffs_obj
*parent
= yaffs_inode_to_obj(dir
);
1227 int error
= -ENOSPC
;
1228 uid_t uid
= YCRED(current
)->fsuid
;
1230 (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: YCRED(current
)->fsgid
;
1232 if ((dir
->i_mode
& S_ISGID
) && S_ISDIR(mode
))
1236 yaffs_trace(YAFFS_TRACE_OS
,
1237 "yaffs_mknod: parent object %d type %d",
1238 parent
->obj_id
, parent
->variant_type
);
1240 yaffs_trace(YAFFS_TRACE_OS
,
1241 "yaffs_mknod: could not get parent object");
1245 yaffs_trace(YAFFS_TRACE_OS
,
1246 "yaffs_mknod: making oject for %s, mode %x dev %x",
1247 dentry
->d_name
.name
, mode
, rdev
);
1249 dev
= parent
->my_dev
;
1251 yaffs_gross_lock(dev
);
1253 switch (mode
& S_IFMT
) {
1255 /* Special (socket, fifo, device...) */
1256 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making special");
1257 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1259 yaffs_create_special(parent
, dentry
->d_name
.name
, mode
, uid
,
1260 gid
, old_encode_dev(rdev
));
1263 yaffs_create_special(parent
, dentry
->d_name
.name
, mode
, uid
,
1267 case S_IFREG
: /* file */
1268 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making file");
1269 obj
= yaffs_create_file(parent
, dentry
->d_name
.name
, mode
, uid
,
1272 case S_IFDIR
: /* directory */
1273 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making directory");
1274 obj
= yaffs_create_dir(parent
, dentry
->d_name
.name
, mode
,
1277 case S_IFLNK
: /* symlink */
1278 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making symlink");
1279 obj
= NULL
; /* Do we ever get here? */
1283 /* Can not call yaffs_get_inode() with gross lock held */
1284 yaffs_gross_unlock(dev
);
1287 inode
= yaffs_get_inode(dir
->i_sb
, mode
, rdev
, obj
);
1288 d_instantiate(dentry
, inode
);
1289 update_dir_time(dir
);
1290 yaffs_trace(YAFFS_TRACE_OS
,
1291 "yaffs_mknod created object %d count = %d",
1292 obj
->obj_id
, atomic_read(&inode
->i_count
));
1294 yaffs_fill_inode_from_obj(dir
, parent
);
1296 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod failed making object");
1303 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1304 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
)
1306 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1310 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mkdir");
1311 ret_val
= yaffs_mknod(dir
, dentry
, mode
| S_IFDIR
, 0);
1316 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1317 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
1319 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1320 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
1321 struct nameidata
*n
)
1322 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1323 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1324 struct nameidata
*n
)
1326 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1329 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_create");
1330 return yaffs_mknod(dir
, dentry
, mode
| S_IFREG
, 0);
1333 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1334 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
1336 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1337 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
1338 struct nameidata
*n
)
1340 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
)
1343 struct yaffs_obj
*obj
;
1344 struct inode
*inode
= NULL
; /* NCB 2.5/2.6 needs NULL here */
1346 struct yaffs_dev
*dev
= yaffs_inode_to_obj(dir
)->my_dev
;
1348 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1349 yaffs_gross_lock(dev
);
1351 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_lookup for %d:%s",
1352 yaffs_inode_to_obj(dir
)->obj_id
, dentry
->d_name
.name
);
1354 obj
= yaffs_find_by_name(yaffs_inode_to_obj(dir
), dentry
->d_name
.name
);
1356 obj
= yaffs_get_equivalent_obj(obj
); /* in case it was a hardlink */
1358 /* Can't hold gross lock when calling yaffs_get_inode() */
1359 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1360 yaffs_gross_unlock(dev
);
1363 yaffs_trace(YAFFS_TRACE_OS
,
1364 "yaffs_lookup found %d", obj
->obj_id
);
1366 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1368 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_lookup not found");
1372 /* added NCB for 2.5/6 compatability - forces add even if inode is
1373 * NULL which creates dentry hash */
1374 d_add(dentry
, inode
);
1382 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
1383 struct dentry
*dentry
)
1385 struct inode
*inode
= old_dentry
->d_inode
;
1386 struct yaffs_obj
*obj
= NULL
;
1387 struct yaffs_obj
*link
= NULL
;
1388 struct yaffs_dev
*dev
;
1390 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_link");
1392 obj
= yaffs_inode_to_obj(inode
);
1395 yaffs_gross_lock(dev
);
1397 if (!S_ISDIR(inode
->i_mode
)) /* Don't link directories */
1399 yaffs_link_obj(yaffs_inode_to_obj(dir
), dentry
->d_name
.name
,
1403 set_nlink(old_dentry
->d_inode
, yaffs_get_obj_link_count(obj
));
1404 d_instantiate(dentry
, old_dentry
->d_inode
);
1405 atomic_inc(&old_dentry
->d_inode
->i_count
);
1406 yaffs_trace(YAFFS_TRACE_OS
,
1407 "yaffs_link link count %d i_count %d",
1408 old_dentry
->d_inode
->i_nlink
,
1409 atomic_read(&old_dentry
->d_inode
->i_count
));
1412 yaffs_gross_unlock(dev
);
1415 update_dir_time(dir
);
1422 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
1423 const char *symname
)
1425 struct yaffs_obj
*obj
;
1426 struct yaffs_dev
*dev
;
1427 uid_t uid
= YCRED(current
)->fsuid
;
1429 (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: YCRED(current
)->fsgid
;
1431 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_symlink");
1433 if (strnlen(dentry
->d_name
.name
, YAFFS_MAX_NAME_LENGTH
+ 1) >
1434 YAFFS_MAX_NAME_LENGTH
)
1435 return -ENAMETOOLONG
;
1437 if (strnlen(symname
, YAFFS_MAX_ALIAS_LENGTH
+ 1) >
1438 YAFFS_MAX_ALIAS_LENGTH
)
1439 return -ENAMETOOLONG
;
1441 dev
= yaffs_inode_to_obj(dir
)->my_dev
;
1442 yaffs_gross_lock(dev
);
1443 obj
= yaffs_create_symlink(yaffs_inode_to_obj(dir
), dentry
->d_name
.name
,
1444 S_IFLNK
| S_IRWXUGO
, uid
, gid
, symname
);
1445 yaffs_gross_unlock(dev
);
1448 struct inode
*inode
;
1450 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1451 d_instantiate(dentry
, inode
);
1452 update_dir_time(dir
);
1453 yaffs_trace(YAFFS_TRACE_OS
, "symlink created OK");
1456 yaffs_trace(YAFFS_TRACE_OS
, "symlink not created");
1463 * The VFS layer already does all the dentry stuff for rename.
1465 * NB: POSIX says you can rename an object over an old object of the same name
1467 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1468 struct inode
*new_dir
, struct dentry
*new_dentry
)
1470 struct yaffs_dev
*dev
;
1471 int ret_val
= YAFFS_FAIL
;
1472 struct yaffs_obj
*target
;
1474 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_rename");
1475 dev
= yaffs_inode_to_obj(old_dir
)->my_dev
;
1477 yaffs_gross_lock(dev
);
1479 /* Check if the target is an existing directory that is not empty. */
1480 target
= yaffs_find_by_name(yaffs_inode_to_obj(new_dir
),
1481 new_dentry
->d_name
.name
);
1483 if (target
&& target
->variant_type
== YAFFS_OBJECT_TYPE_DIRECTORY
&&
1484 !list_empty(&target
->variant
.dir_variant
.children
)) {
1486 yaffs_trace(YAFFS_TRACE_OS
, "target is non-empty dir");
1488 ret_val
= YAFFS_FAIL
;
1490 /* Now does unlinking internally using shadowing mechanism */
1491 yaffs_trace(YAFFS_TRACE_OS
, "calling yaffs_rename_obj");
1493 ret_val
= yaffs_rename_obj(yaffs_inode_to_obj(old_dir
),
1494 old_dentry
->d_name
.name
,
1495 yaffs_inode_to_obj(new_dir
),
1496 new_dentry
->d_name
.name
);
1498 yaffs_gross_unlock(dev
);
1500 if (ret_val
== YAFFS_OK
) {
1502 inode_dec_link_count(new_dentry
->d_inode
);
1504 update_dir_time(old_dir
);
1505 if (old_dir
!= new_dir
)
1506 update_dir_time(new_dir
);
1516 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
)
1520 struct yaffs_dev
*dev
;
1521 struct yaffs_obj
*obj
;
1523 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_unlink %d:%s",
1524 (int)(dir
->i_ino
), dentry
->d_name
.name
);
1525 obj
= yaffs_inode_to_obj(dir
);
1528 yaffs_gross_lock(dev
);
1530 ret_val
= yaffs_unlinker(obj
, dentry
->d_name
.name
);
1532 if (ret_val
== YAFFS_OK
) {
1533 inode_dec_link_count(dentry
->d_inode
);
1535 yaffs_gross_unlock(dev
);
1536 update_dir_time(dir
);
1539 yaffs_gross_unlock(dev
);
1545 static const struct inode_operations yaffs_dir_inode_operations
= {
1546 .create
= yaffs_create
,
1547 .lookup
= yaffs_lookup
,
1549 .unlink
= yaffs_unlink
,
1550 .symlink
= yaffs_symlink
,
1551 .mkdir
= yaffs_mkdir
,
1552 .rmdir
= yaffs_unlink
,
1553 .mknod
= yaffs_mknod
,
1554 .rename
= yaffs_rename
,
1555 .setattr
= yaffs_setattr
,
1556 .setxattr
= yaffs_setxattr
,
1557 .getxattr
= yaffs_getxattr
,
1558 .listxattr
= yaffs_listxattr
,
1559 .removexattr
= yaffs_removexattr
,
1562 /*-----------------------------------------------------------------*/
1563 /* Directory search context allows us to unlock access to yaffs during
1564 * filldir without causing problems with the directory being modified.
1565 * This is similar to the tried and tested mechanism used in yaffs direct.
1567 * A search context iterates along a doubly linked list of siblings in the
1568 * directory. If the iterating object is deleted then this would corrupt
1569 * the list iteration, likely causing a crash. The search context avoids
1570 * this by using the remove_obj_fn to move the search context to the
1571 * next object before the object is deleted.
1573 * Many readdirs (and thus seach conexts) may be alive simulateously so
1574 * each struct yaffs_dev has a list of these.
1576 * A seach context lives for the duration of a readdir.
1578 * All these functions must be called while yaffs is locked.
1581 struct yaffs_search_context
{
1582 struct yaffs_dev
*dev
;
1583 struct yaffs_obj
*dir_obj
;
1584 struct yaffs_obj
*next_return
;
1585 struct list_head others
;
1589 * yaffs_new_search() creates a new search context, initialises it and
1590 * adds it to the device's search context list.
1592 * Called at start of readdir.
1594 static struct yaffs_search_context
*yaffs_new_search(struct yaffs_obj
*dir
)
1596 struct yaffs_dev
*dev
= dir
->my_dev
;
1597 struct yaffs_search_context
*sc
=
1598 kmalloc(sizeof(struct yaffs_search_context
), GFP_NOFS
);
1602 if (list_empty(&sc
->dir_obj
->variant
.dir_variant
.children
))
1603 sc
->next_return
= NULL
;
1606 list_entry(dir
->variant
.dir_variant
.children
.next
,
1607 struct yaffs_obj
, siblings
);
1608 INIT_LIST_HEAD(&sc
->others
);
1609 list_add(&sc
->others
, &(yaffs_dev_to_lc(dev
)->search_contexts
));
1615 * yaffs_search_end() disposes of a search context and cleans up.
1617 static void yaffs_search_end(struct yaffs_search_context
*sc
)
1620 list_del(&sc
->others
);
1626 * yaffs_search_advance() moves a search context to the next object.
1627 * Called when the search iterates or when an object removal causes
1628 * the search context to be moved to the next object.
1630 static void yaffs_search_advance(struct yaffs_search_context
*sc
)
1635 if (sc
->next_return
== NULL
||
1636 list_empty(&sc
->dir_obj
->variant
.dir_variant
.children
))
1637 sc
->next_return
= NULL
;
1639 struct list_head
*next
= sc
->next_return
->siblings
.next
;
1641 if (next
== &sc
->dir_obj
->variant
.dir_variant
.children
)
1642 sc
->next_return
= NULL
; /* end of list */
1645 list_entry(next
, struct yaffs_obj
, siblings
);
1650 * yaffs_remove_obj_callback() is called when an object is unlinked.
1651 * We check open search contexts and advance any which are currently
1652 * on the object being iterated.
1654 static void yaffs_remove_obj_callback(struct yaffs_obj
*obj
)
1657 struct list_head
*i
;
1658 struct yaffs_search_context
*sc
;
1659 struct list_head
*search_contexts
=
1660 &(yaffs_dev_to_lc(obj
->my_dev
)->search_contexts
);
1662 /* Iterate through the directory search contexts.
1663 * If any are currently on the object being removed, then advance
1664 * the search context to the next object to prevent a hanging pointer.
1666 list_for_each(i
, search_contexts
) {
1667 sc
= list_entry(i
, struct yaffs_search_context
, others
);
1668 if (sc
->next_return
== obj
)
1669 yaffs_search_advance(sc
);
1675 /*-----------------------------------------------------------------*/
1677 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
)
1679 struct yaffs_obj
*obj
;
1680 struct yaffs_dev
*dev
;
1681 struct yaffs_search_context
*sc
;
1682 struct inode
*inode
= f
->f_dentry
->d_inode
;
1683 unsigned long offset
, curoffs
;
1684 struct yaffs_obj
*l
;
1687 char name
[YAFFS_MAX_NAME_LENGTH
+ 1];
1689 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1692 yaffs_gross_lock(dev
);
1694 yaffs_dev_to_lc(dev
)->readdir_process
= current
;
1698 sc
= yaffs_new_search(obj
);
1704 yaffs_trace(YAFFS_TRACE_OS
,
1705 "yaffs_readdir: starting at %d", (int)offset
);
1708 yaffs_trace(YAFFS_TRACE_OS
,
1709 "yaffs_readdir: entry . ino %d",
1711 yaffs_gross_unlock(dev
);
1712 if (filldir(dirent
, ".", 1, offset
, inode
->i_ino
, DT_DIR
) < 0) {
1713 yaffs_gross_lock(dev
);
1716 yaffs_gross_lock(dev
);
1721 yaffs_trace(YAFFS_TRACE_OS
,
1722 "yaffs_readdir: entry .. ino %d",
1723 (int)f
->f_dentry
->d_parent
->d_inode
->i_ino
);
1724 yaffs_gross_unlock(dev
);
1725 if (filldir(dirent
, "..", 2, offset
,
1726 f
->f_dentry
->d_parent
->d_inode
->i_ino
,
1728 yaffs_gross_lock(dev
);
1731 yaffs_gross_lock(dev
);
1738 /* If the directory has changed since the open or last call to
1739 readdir, rewind to after the 2 canned entries. */
1740 if (f
->f_version
!= inode
->i_version
) {
1743 f
->f_version
= inode
->i_version
;
1746 while (sc
->next_return
) {
1748 l
= sc
->next_return
;
1749 if (curoffs
>= offset
) {
1750 int this_inode
= yaffs_get_obj_inode(l
);
1751 int this_type
= yaffs_get_obj_type(l
);
1753 yaffs_get_obj_name(l
, name
, YAFFS_MAX_NAME_LENGTH
+ 1);
1754 yaffs_trace(YAFFS_TRACE_OS
,
1755 "yaffs_readdir: %s inode %d",
1756 name
, yaffs_get_obj_inode(l
));
1758 yaffs_gross_unlock(dev
);
1763 offset
, this_inode
, this_type
) < 0) {
1764 yaffs_gross_lock(dev
);
1768 yaffs_gross_lock(dev
);
1773 yaffs_search_advance(sc
);
1777 yaffs_search_end(sc
);
1778 yaffs_dev_to_lc(dev
)->readdir_process
= NULL
;
1779 yaffs_gross_unlock(dev
);
1784 static const struct file_operations yaffs_dir_operations
= {
1785 .read
= generic_read_dir
,
1786 .readdir
= yaffs_readdir
,
1787 .fsync
= yaffs_sync_object
,
1788 .llseek
= generic_file_llseek
,
1791 static void yaffs_fill_inode_from_obj(struct inode
*inode
,
1792 struct yaffs_obj
*obj
)
1796 /* Check mode against the variant type and attempt to repair if broken. */
1797 u32 mode
= obj
->yst_mode
;
1798 switch (obj
->variant_type
) {
1799 case YAFFS_OBJECT_TYPE_FILE
:
1800 if (!S_ISREG(mode
)) {
1801 obj
->yst_mode
&= ~S_IFMT
;
1802 obj
->yst_mode
|= S_IFREG
;
1806 case YAFFS_OBJECT_TYPE_SYMLINK
:
1807 if (!S_ISLNK(mode
)) {
1808 obj
->yst_mode
&= ~S_IFMT
;
1809 obj
->yst_mode
|= S_IFLNK
;
1813 case YAFFS_OBJECT_TYPE_DIRECTORY
:
1814 if (!S_ISDIR(mode
)) {
1815 obj
->yst_mode
&= ~S_IFMT
;
1816 obj
->yst_mode
|= S_IFDIR
;
1820 case YAFFS_OBJECT_TYPE_UNKNOWN
:
1821 case YAFFS_OBJECT_TYPE_HARDLINK
:
1822 case YAFFS_OBJECT_TYPE_SPECIAL
:
1828 inode
->i_flags
|= S_NOATIME
;
1830 inode
->i_ino
= obj
->obj_id
;
1831 inode
->i_mode
= obj
->yst_mode
;
1832 inode
->i_uid
= obj
->yst_uid
;
1833 inode
->i_gid
= obj
->yst_gid
;
1834 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
1835 inode
->i_blksize
= inode
->i_sb
->s_blocksize
;
1837 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1839 inode
->i_rdev
= old_decode_dev(obj
->yst_rdev
);
1840 inode
->i_atime
.tv_sec
= (time_t) (obj
->yst_atime
);
1841 inode
->i_atime
.tv_nsec
= 0;
1842 inode
->i_mtime
.tv_sec
= (time_t) obj
->yst_mtime
;
1843 inode
->i_mtime
.tv_nsec
= 0;
1844 inode
->i_ctime
.tv_sec
= (time_t) obj
->yst_ctime
;
1845 inode
->i_ctime
.tv_nsec
= 0;
1847 inode
->i_rdev
= obj
->yst_rdev
;
1848 inode
->i_atime
= obj
->yst_atime
;
1849 inode
->i_mtime
= obj
->yst_mtime
;
1850 inode
->i_ctime
= obj
->yst_ctime
;
1852 inode
->i_size
= yaffs_get_obj_length(obj
);
1853 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
1855 set_nlink(inode
, yaffs_get_obj_link_count(obj
));
1857 yaffs_trace(YAFFS_TRACE_OS
,
1858 "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
1859 inode
->i_mode
, inode
->i_uid
, inode
->i_gid
,
1860 inode
->i_size
, atomic_read(&inode
->i_count
));
1862 switch (obj
->yst_mode
& S_IFMT
) {
1863 default: /* fifo, device or socket */
1864 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1865 init_special_inode(inode
, obj
->yst_mode
,
1866 old_decode_dev(obj
->yst_rdev
));
1868 init_special_inode(inode
, obj
->yst_mode
,
1869 (dev_t
) (obj
->yst_rdev
));
1872 case S_IFREG
: /* file */
1873 inode
->i_op
= &yaffs_file_inode_operations
;
1874 inode
->i_fop
= &yaffs_file_operations
;
1875 inode
->i_mapping
->a_ops
=
1876 &yaffs_file_address_operations
;
1878 case S_IFDIR
: /* directory */
1879 inode
->i_op
= &yaffs_dir_inode_operations
;
1880 inode
->i_fop
= &yaffs_dir_operations
;
1882 case S_IFLNK
: /* symlink */
1883 inode
->i_op
= &yaffs_symlink_inode_operations
;
1887 yaffs_inode_to_obj_lv(inode
) = obj
;
1889 obj
->my_inode
= inode
;
1892 yaffs_trace(YAFFS_TRACE_OS
,
1893 "yaffs_fill_inode invalid parameters");
1901 * yaffs background thread functions .
1902 * yaffs_bg_thread_fn() the thread function
1903 * yaffs_bg_start() launches the background thread.
1904 * yaffs_bg_stop() cleans up the background thread.
1907 * The thread should only run after the yaffs is initialised
1908 * The thread should be stopped before yaffs is unmounted.
1909 * The thread should not do any writing while the fs is in read only.
1912 static unsigned yaffs_bg_gc_urgency(struct yaffs_dev
*dev
)
1914 unsigned erased_chunks
=
1915 dev
->n_erased_blocks
* dev
->param
.chunks_per_block
;
1916 struct yaffs_linux_context
*context
= yaffs_dev_to_lc(dev
);
1917 unsigned scattered
= 0; /* Free chunks not in an erased block */
1919 if (erased_chunks
< dev
->n_free_chunks
)
1920 scattered
= (dev
->n_free_chunks
- erased_chunks
);
1922 if (!context
->bg_running
)
1924 else if (scattered
< (dev
->param
.chunks_per_block
* 2))
1926 else if (erased_chunks
> dev
->n_free_chunks
/ 2)
1928 else if (erased_chunks
> dev
->n_free_chunks
/ 4)
1934 #ifdef YAFFS_COMPILE_BACKGROUND
1936 void yaffs_background_waker(unsigned long data
)
1938 wake_up_process((struct task_struct
*)data
);
1941 static int yaffs_bg_thread_fn(void *data
)
1943 struct yaffs_dev
*dev
= (struct yaffs_dev
*)data
;
1944 struct yaffs_linux_context
*context
= yaffs_dev_to_lc(dev
);
1945 unsigned long now
= jiffies
;
1946 unsigned long next_dir_update
= now
;
1947 unsigned long next_gc
= now
;
1948 unsigned long expires
;
1949 unsigned int urgency
;
1952 struct timer_list timer
;
1954 yaffs_trace(YAFFS_TRACE_BACKGROUND
,
1955 "yaffs_background starting for dev %p", (void *)dev
);
1957 #ifdef YAFFS_COMPILE_FREEZER
1960 while (context
->bg_running
) {
1961 yaffs_trace(YAFFS_TRACE_BACKGROUND
, "yaffs_background");
1963 if (kthread_should_stop())
1966 #ifdef YAFFS_COMPILE_FREEZER
1967 if (try_to_freeze())
1970 yaffs_gross_lock(dev
);
1974 if (time_after(now
, next_dir_update
) && yaffs_bg_enable
) {
1975 yaffs_update_dirty_dirs(dev
);
1976 next_dir_update
= now
+ HZ
;
1979 if (time_after(now
, next_gc
) && yaffs_bg_enable
) {
1980 if (!dev
->is_checkpointed
) {
1981 urgency
= yaffs_bg_gc_urgency(dev
);
1982 gc_result
= yaffs_bg_gc(dev
, urgency
);
1984 next_gc
= now
+ HZ
/ 20 + 1;
1985 else if (urgency
> 0)
1986 next_gc
= now
+ HZ
/ 10 + 1;
1988 next_gc
= now
+ HZ
* 2;
1991 * gc not running so set to next_dir_update
1992 * to cut down on wake ups
1994 next_gc
= next_dir_update
;
1997 yaffs_gross_unlock(dev
);
1999 expires
= next_dir_update
;
2000 if (time_before(next_gc
, expires
))
2002 if (time_before(expires
, now
))
2005 Y_INIT_TIMER(&timer
);
2006 timer
.expires
= expires
+ 1;
2007 timer
.data
= (unsigned long)current
;
2008 timer
.function
= yaffs_background_waker
;
2010 set_current_state(TASK_INTERRUPTIBLE
);
2013 del_timer_sync(&timer
);
2022 static int yaffs_bg_start(struct yaffs_dev
*dev
)
2025 struct yaffs_linux_context
*context
= yaffs_dev_to_lc(dev
);
2030 context
->bg_running
= 1;
2032 context
->bg_thread
= kthread_run(yaffs_bg_thread_fn
,
2033 (void *)dev
, "yaffs-bg-%d",
2036 if (IS_ERR(context
->bg_thread
)) {
2037 retval
= PTR_ERR(context
->bg_thread
);
2038 context
->bg_thread
= NULL
;
2039 context
->bg_running
= 0;
2044 static void yaffs_bg_stop(struct yaffs_dev
*dev
)
2046 struct yaffs_linux_context
*ctxt
= yaffs_dev_to_lc(dev
);
2048 ctxt
->bg_running
= 0;
2050 if (ctxt
->bg_thread
) {
2051 kthread_stop(ctxt
->bg_thread
);
2052 ctxt
->bg_thread
= NULL
;
2056 static int yaffs_bg_thread_fn(void *data
)
2061 static int yaffs_bg_start(struct yaffs_dev
*dev
)
2066 static void yaffs_bg_stop(struct yaffs_dev
*dev
)
2072 static void yaffs_flush_inodes(struct super_block
*sb
)
2075 struct yaffs_obj
*obj
;
2077 list_for_each_entry(iptr
, &sb
->s_inodes
, i_sb_list
) {
2078 obj
= yaffs_inode_to_obj(iptr
);
2080 yaffs_trace(YAFFS_TRACE_OS
,
2083 yaffs_flush_file(obj
, 1, 0);
2088 static void yaffs_flush_super(struct super_block
*sb
, int do_checkpoint
)
2090 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2094 yaffs_flush_inodes(sb
);
2095 yaffs_update_dirty_dirs(dev
);
2096 yaffs_flush_whole_cache(dev
);
2098 yaffs_checkpoint_save(dev
);
2101 static LIST_HEAD(yaffs_context_list
);
2102 struct mutex yaffs_context_lock
;
2104 static void yaffs_put_super(struct super_block
*sb
)
2106 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2107 struct mtd_info
*mtd
= yaffs_dev_to_mtd(dev
);
2109 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_ALWAYS
,
2112 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_BACKGROUND
,
2113 "Shutting down yaffs background thread");
2115 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_BACKGROUND
,
2116 "yaffs background thread shut down");
2118 yaffs_gross_lock(dev
);
2120 yaffs_flush_super(sb
, 1);
2122 yaffs_deinitialise(dev
);
2124 yaffs_gross_unlock(dev
);
2126 mutex_lock(&yaffs_context_lock
);
2127 list_del_init(&(yaffs_dev_to_lc(dev
)->context_list
));
2128 mutex_unlock(&yaffs_context_lock
);
2130 if (yaffs_dev_to_lc(dev
)->spare_buffer
) {
2131 kfree(yaffs_dev_to_lc(dev
)->spare_buffer
);
2132 yaffs_dev_to_lc(dev
)->spare_buffer
= NULL
;
2137 yaffs_put_mtd_device(mtd
);
2139 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_ALWAYS
,
2140 "yaffs_put_super done");
2144 static unsigned yaffs_gc_control_callback(struct yaffs_dev
*dev
)
2146 return yaffs_gc_control
;
2150 #ifdef YAFFS_COMPILE_EXPORTFS
2152 static struct inode
*yaffs2_nfs_get_inode(struct super_block
*sb
, uint64_t ino
,
2153 uint32_t generation
)
2155 return Y_IGET(sb
, ino
);
2158 static struct dentry
*yaffs2_fh_to_dentry(struct super_block
*sb
,
2159 struct fid
*fid
, int fh_len
,
2162 return generic_fh_to_dentry(sb
, fid
, fh_len
, fh_type
,
2163 yaffs2_nfs_get_inode
);
2166 static struct dentry
*yaffs2_fh_to_parent(struct super_block
*sb
,
2167 struct fid
*fid
, int fh_len
,
2170 return generic_fh_to_parent(sb
, fid
, fh_len
, fh_type
,
2171 yaffs2_nfs_get_inode
);
2174 struct dentry
*yaffs2_get_parent(struct dentry
*dentry
)
2177 struct super_block
*sb
= dentry
->d_inode
->i_sb
;
2178 struct dentry
*parent
= ERR_PTR(-ENOENT
);
2179 struct inode
*inode
;
2180 unsigned long parent_ino
;
2181 struct yaffs_obj
*d_obj
;
2182 struct yaffs_obj
*parent_obj
;
2184 d_obj
= yaffs_inode_to_obj(dentry
->d_inode
);
2187 parent_obj
= d_obj
->parent
;
2189 parent_ino
= yaffs_get_obj_inode(parent_obj
);
2190 inode
= Y_IGET(sb
, parent_ino
);
2192 if (IS_ERR(inode
)) {
2193 parent
= ERR_CAST(inode
);
2195 parent
= d_obtain_alias(inode
);
2196 if (!IS_ERR(parent
)) {
2197 parent
= ERR_PTR(-ENOMEM
);
2207 /* Just declare a zero structure as a NULL value implies
2208 * using the default functions of exportfs.
2211 static struct export_operations yaffs_export_ops
= {
2212 .fh_to_dentry
= yaffs2_fh_to_dentry
,
2213 .fh_to_parent
= yaffs2_fh_to_parent
,
2214 .get_parent
= yaffs2_get_parent
,
2219 static void yaffs_unstitch_obj(struct inode
*inode
, struct yaffs_obj
*obj
)
2221 /* Clear the association between the inode and
2222 * the struct yaffs_obj.
2224 obj
->my_inode
= NULL
;
2225 yaffs_inode_to_obj_lv(inode
) = NULL
;
2227 /* If the object freeing was deferred, then the real
2229 * This should fix the inode inconsistency problem.
2231 yaffs_handle_defered_free(obj
);
2234 #ifdef YAFFS_HAS_EVICT_INODE
2235 /* yaffs_evict_inode combines into one operation what was previously done in
2236 * yaffs_clear_inode() and yaffs_delete_inode()
2239 static void yaffs_evict_inode(struct inode
*inode
)
2241 struct yaffs_obj
*obj
;
2242 struct yaffs_dev
*dev
;
2245 obj
= yaffs_inode_to_obj(inode
);
2247 yaffs_trace(YAFFS_TRACE_OS
,
2248 "yaffs_evict_inode: ino %d, count %d %s",
2249 (int)inode
->i_ino
, atomic_read(&inode
->i_count
),
2250 obj
? "object exists" : "null object");
2252 if (!inode
->i_nlink
&& !is_bad_inode(inode
))
2254 truncate_inode_pages(&inode
->i_data
, 0);
2255 Y_CLEAR_INODE(inode
);
2257 if (deleteme
&& obj
) {
2259 yaffs_gross_lock(dev
);
2261 yaffs_gross_unlock(dev
);
2265 yaffs_gross_lock(dev
);
2266 yaffs_unstitch_obj(inode
, obj
);
2267 yaffs_gross_unlock(dev
);
2272 /* clear is called to tell the fs to release any per-inode data it holds.
2273 * The object might still exist on disk and is just being thrown out of the cache
2274 * or else the object has actually been deleted and we're being called via
2276 * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
2279 static void yaffs_clear_inode(struct inode
*inode
)
2281 struct yaffs_obj
*obj
;
2282 struct yaffs_dev
*dev
;
2284 obj
= yaffs_inode_to_obj(inode
);
2286 yaffs_trace(YAFFS_TRACE_OS
,
2287 "yaffs_clear_inode: ino %d, count %d %s",
2288 (int)inode
->i_ino
, atomic_read(&inode
->i_count
),
2289 obj
? "object exists" : "null object");
2293 yaffs_gross_lock(dev
);
2294 yaffs_unstitch_obj(inode
, obj
);
2295 yaffs_gross_unlock(dev
);
2300 /* delete is called when the link count is zero and the inode
2301 * is put (ie. nobody wants to know about it anymore, time to
2303 * NB Must call clear_inode()
2305 static void yaffs_delete_inode(struct inode
*inode
)
2307 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
2308 struct yaffs_dev
*dev
;
2310 yaffs_trace(YAFFS_TRACE_OS
,
2311 "yaffs_delete_inode: ino %d, count %d %s",
2312 (int)inode
->i_ino
, atomic_read(&inode
->i_count
),
2313 obj
? "object exists" : "null object");
2317 yaffs_gross_lock(dev
);
2319 yaffs_gross_unlock(dev
);
2321 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
2322 truncate_inode_pages(&inode
->i_data
, 0);
2331 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2332 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
2334 struct yaffs_dev
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
2335 struct super_block
*sb
= dentry
->d_sb
;
2336 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2337 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
)
2339 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2341 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
)
2343 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2346 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_statfs");
2348 yaffs_gross_lock(dev
);
2350 buf
->f_type
= YAFFS_MAGIC
;
2351 buf
->f_bsize
= sb
->s_blocksize
;
2352 buf
->f_namelen
= 255;
2354 if (dev
->data_bytes_per_chunk
& (dev
->data_bytes_per_chunk
- 1)) {
2355 /* Do this if chunk size is not a power of 2 */
2357 uint64_t bytes_in_dev
;
2358 uint64_t bytes_free
;
2362 ((dev
->param
.end_block
- dev
->param
.start_block
+
2363 1))) * ((uint64_t) (dev
->param
.chunks_per_block
*
2364 dev
->data_bytes_per_chunk
));
2366 do_div(bytes_in_dev
, sb
->s_blocksize
); /* bytes_in_dev becomes the number of blocks */
2367 buf
->f_blocks
= bytes_in_dev
;
2369 bytes_free
= ((uint64_t) (yaffs_get_n_free_chunks(dev
))) *
2370 ((uint64_t) (dev
->data_bytes_per_chunk
));
2372 do_div(bytes_free
, sb
->s_blocksize
);
2374 buf
->f_bfree
= bytes_free
;
2376 } else if (sb
->s_blocksize
> dev
->data_bytes_per_chunk
) {
2379 (dev
->param
.end_block
- dev
->param
.start_block
+ 1) *
2380 dev
->param
.chunks_per_block
/
2381 (sb
->s_blocksize
/ dev
->data_bytes_per_chunk
);
2383 yaffs_get_n_free_chunks(dev
) /
2384 (sb
->s_blocksize
/ dev
->data_bytes_per_chunk
);
2387 (dev
->param
.end_block
- dev
->param
.start_block
+ 1) *
2388 dev
->param
.chunks_per_block
*
2389 (dev
->data_bytes_per_chunk
/ sb
->s_blocksize
);
2392 yaffs_get_n_free_chunks(dev
) *
2393 (dev
->data_bytes_per_chunk
/ sb
->s_blocksize
);
2398 buf
->f_bavail
= buf
->f_bfree
;
2400 yaffs_gross_unlock(dev
);
2406 static int yaffs_do_sync_fs(struct super_block
*sb
, int request_checkpoint
)
2409 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2410 unsigned int oneshot_checkpoint
= (yaffs_auto_checkpoint
& 4);
2411 unsigned gc_urgent
= yaffs_bg_gc_urgency(dev
);
2413 int dirty
= yaffs_check_super_dirty(dev
);
2415 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
| YAFFS_TRACE_BACKGROUND
,
2416 "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
2418 dirty
? "dirty" : "clean",
2419 request_checkpoint
? "checkpoint requested" : "no checkpoint",
2420 oneshot_checkpoint
? " one-shot" : "");
2422 yaffs_gross_lock(dev
);
2423 do_checkpoint
= ((request_checkpoint
&& !gc_urgent
) ||
2424 oneshot_checkpoint
) && !dev
->is_checkpointed
;
2426 if (dirty
|| do_checkpoint
) {
2427 yaffs_flush_super(sb
, !dev
->is_checkpointed
&& do_checkpoint
);
2428 yaffs_clear_super_dirty(dev
);
2429 if (oneshot_checkpoint
)
2430 yaffs_auto_checkpoint
&= ~4;
2432 yaffs_gross_unlock(dev
);
2438 #ifdef YAFFS_HAS_WRITE_SUPER
2439 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2440 static void yaffs_write_super(struct super_block
*sb
)
2442 static int yaffs_write_super(struct super_block
*sb
)
2445 unsigned request_checkpoint
= (yaffs_auto_checkpoint
>= 2);
2447 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
| YAFFS_TRACE_BACKGROUND
,
2448 "yaffs_write_super %s",
2449 request_checkpoint
? " checkpt" : "");
2451 yaffs_do_sync_fs(sb
, request_checkpoint
);
2453 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
2459 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2460 static int yaffs_sync_fs(struct super_block
*sb
, int wait
)
2462 static int yaffs_sync_fs(struct super_block
*sb
)
2465 unsigned request_checkpoint
= (yaffs_auto_checkpoint
>= 1);
2467 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
,
2468 "yaffs_sync_fs%s", request_checkpoint
? " checkpt" : "");
2470 yaffs_do_sync_fs(sb
, request_checkpoint
);
2477 static const struct super_operations yaffs_super_ops
= {
2478 .statfs
= yaffs_statfs
,
2480 #ifndef YAFFS_USE_OWN_IGET
2481 .read_inode
= yaffs_read_inode
,
2483 #ifdef YAFFS_HAS_PUT_INODE
2484 .put_inode
= yaffs_put_inode
,
2486 .put_super
= yaffs_put_super
,
2487 #ifdef YAFFS_HAS_EVICT_INODE
2488 .evict_inode
= yaffs_evict_inode
,
2490 .delete_inode
= yaffs_delete_inode
,
2491 .clear_inode
= yaffs_clear_inode
,
2493 .sync_fs
= yaffs_sync_fs
,
2494 #ifdef YAFFS_HAS_WRITE_SUPER
2495 .write_super
= yaffs_write_super
,
2499 struct yaffs_options
{
2501 int skip_checkpoint_read
;
2502 int skip_checkpoint_write
;
2505 int tags_ecc_overridden
;
2506 int lazy_loading_enabled
;
2507 int lazy_loading_overridden
;
2508 int empty_lost_and_found
;
2509 int empty_lost_and_found_overridden
;
2510 int disable_summary
;
2513 #define MAX_OPT_LEN 30
2514 static int yaffs_parse_options(struct yaffs_options
*options
,
2515 const char *options_str
)
2517 char cur_opt
[MAX_OPT_LEN
+ 1];
2521 /* Parse through the options which is a comma seperated list */
2523 while (options_str
&& *options_str
&& !error
) {
2524 memset(cur_opt
, 0, MAX_OPT_LEN
+ 1);
2527 while (*options_str
== ',')
2530 while (*options_str
&& *options_str
!= ',') {
2531 if (p
< MAX_OPT_LEN
) {
2532 cur_opt
[p
] = *options_str
;
2538 if (!strcmp(cur_opt
, "inband-tags")) {
2539 options
->inband_tags
= 1;
2540 } else if (!strcmp(cur_opt
, "tags-ecc-off")) {
2541 options
->tags_ecc_on
= 0;
2542 options
->tags_ecc_overridden
= 1;
2543 } else if (!strcmp(cur_opt
, "tags-ecc-on")) {
2544 options
->tags_ecc_on
= 1;
2545 options
->tags_ecc_overridden
= 1;
2546 } else if (!strcmp(cur_opt
, "lazy-loading-off")) {
2547 options
->lazy_loading_enabled
= 0;
2548 options
->lazy_loading_overridden
= 1;
2549 } else if (!strcmp(cur_opt
, "lazy-loading-on")) {
2550 options
->lazy_loading_enabled
= 1;
2551 options
->lazy_loading_overridden
= 1;
2552 } else if (!strcmp(cur_opt
, "disable-summary")) {
2553 options
->disable_summary
= 1;
2554 } else if (!strcmp(cur_opt
, "empty-lost-and-found-off")) {
2555 options
->empty_lost_and_found
= 0;
2556 options
->empty_lost_and_found_overridden
= 1;
2557 } else if (!strcmp(cur_opt
, "empty-lost-and-found-on")) {
2558 options
->empty_lost_and_found
= 1;
2559 options
->empty_lost_and_found_overridden
= 1;
2560 } else if (!strcmp(cur_opt
, "no-cache")) {
2561 options
->no_cache
= 1;
2562 } else if (!strcmp(cur_opt
, "no-checkpoint-read")) {
2563 options
->skip_checkpoint_read
= 1;
2564 } else if (!strcmp(cur_opt
, "no-checkpoint-write")) {
2565 options
->skip_checkpoint_write
= 1;
2566 } else if (!strcmp(cur_opt
, "no-checkpoint")) {
2567 options
->skip_checkpoint_read
= 1;
2568 options
->skip_checkpoint_write
= 1;
2570 printk(KERN_INFO
"yaffs: Bad mount option \"%s\"\n",
2580 static struct dentry
*yaffs_make_root(struct inode
*inode
)
2582 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
2583 struct dentry
*root
= d_alloc_root(inode
);
2590 return d_make_root(inode
);
2597 static struct super_block
*yaffs_internal_read_super(int yaffs_version
,
2598 struct super_block
*sb
,
2599 void *data
, int silent
)
2602 struct inode
*inode
= NULL
;
2603 struct dentry
*root
;
2604 struct yaffs_dev
*dev
= 0;
2605 char devname_buf
[BDEVNAME_SIZE
+ 1];
2606 struct mtd_info
*mtd
;
2608 char *data_str
= (char *)data
;
2609 struct yaffs_linux_context
*context
= NULL
;
2610 struct yaffs_param
*param
;
2613 int inband_tags
= 0;
2615 struct yaffs_options options
;
2619 struct yaffs_linux_context
*context_iterator
;
2620 struct list_head
*l
;
2623 printk(KERN_INFO
"yaffs: sb is NULL\n");
2627 sb
->s_magic
= YAFFS_MAGIC
;
2628 sb
->s_op
= &yaffs_super_ops
;
2629 sb
->s_flags
|= MS_NOATIME
;
2631 read_only
= ((sb
->s_flags
& MS_RDONLY
) != 0);
2633 #ifdef YAFFS_COMPILE_EXPORTFS
2634 sb
->s_export_op
= &yaffs_export_ops
;
2638 printk(KERN_INFO
"yaffs: sb->s_dev is NULL\n");
2639 else if (!yaffs_devname(sb
, devname_buf
))
2640 printk(KERN_INFO
"yaffs: devname is NULL\n");
2642 printk(KERN_INFO
"yaffs: dev is %d name is \"%s\" %s\n",
2644 yaffs_devname(sb
, devname_buf
), read_only
? "ro" : "rw");
2649 printk(KERN_INFO
"yaffs: passed flags \"%s\"\n", data_str
);
2651 memset(&options
, 0, sizeof(options
));
2653 if (yaffs_parse_options(&options
, data_str
)) {
2654 /* Option parsing failed */
2658 sb
->s_blocksize
= PAGE_CACHE_SIZE
;
2659 sb
->s_blocksize_bits
= PAGE_CACHE_SHIFT
;
2661 yaffs_trace(YAFFS_TRACE_OS
,
2662 "yaffs_read_super: Using yaffs%d", yaffs_version
);
2663 yaffs_trace(YAFFS_TRACE_OS
,
2664 "yaffs_read_super: block size %d", (int)(sb
->s_blocksize
));
2666 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2667 "yaffs: Attempting MTD mount of %u.%u,\"%s\"",
2668 MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
),
2669 yaffs_devname(sb
, devname_buf
));
2671 /* Get the device */
2672 mtd
= get_mtd_device(NULL
, MINOR(sb
->s_dev
));
2674 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2675 "yaffs: MTD device %u either not valid or unavailable",
2680 if (yaffs_auto_select
&& yaffs_version
== 1 && WRITE_SIZE(mtd
) >= 2048) {
2681 yaffs_trace(YAFFS_TRACE_ALWAYS
, "auto selecting yaffs2");
2685 /* Added NCB 26/5/2006 for completeness */
2686 if (yaffs_version
== 2 && !options
.inband_tags
2687 && WRITE_SIZE(mtd
) == 512) {
2688 yaffs_trace(YAFFS_TRACE_ALWAYS
, "auto selecting yaffs1");
2692 if (mtd
->oobavail
< sizeof(struct yaffs_packed_tags2
) ||
2693 options
.inband_tags
)
2696 if(yaffs_verify_mtd(mtd
, yaffs_version
, inband_tags
) < 0)
2699 /* OK, so if we got here, we have an MTD that's NAND and looks
2700 * like it has the right capabilities
2701 * Set the struct yaffs_dev up for mtd
2704 if (!read_only
&& !(mtd
->flags
& MTD_WRITEABLE
)) {
2707 "yaffs: mtd is read only, setting superblock read only\n"
2709 sb
->s_flags
|= MS_RDONLY
;
2712 dev
= kmalloc(sizeof(struct yaffs_dev
), GFP_KERNEL
);
2713 context
= kmalloc(sizeof(struct yaffs_linux_context
), GFP_KERNEL
);
2715 if (!dev
|| !context
) {
2725 /* Deep shit could not allocate device structure */
2726 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2727 "yaffs_read_super: Failed trying to allocate struct yaffs_dev."
2731 memset(dev
, 0, sizeof(struct yaffs_dev
));
2732 param
= &(dev
->param
);
2734 memset(context
, 0, sizeof(struct yaffs_linux_context
));
2735 dev
->os_context
= context
;
2736 INIT_LIST_HEAD(&(context
->context_list
));
2738 context
->super
= sb
;
2740 dev
->read_only
= read_only
;
2742 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2743 sb
->s_fs_info
= dev
;
2745 sb
->u
.generic_sbp
= dev
;
2749 dev
->driver_context
= mtd
;
2750 param
->name
= mtd
->name
;
2752 /* Set up the memory size parameters.... */
2755 param
->n_reserved_blocks
= 5;
2756 param
->n_caches
= (options
.no_cache
) ? 0 : 10;
2757 param
->inband_tags
= inband_tags
;
2759 param
->enable_xattr
= 1;
2760 if (options
.lazy_loading_overridden
)
2761 param
->disable_lazy_load
= !options
.lazy_loading_enabled
;
2763 param
->defered_dir_update
= 1;
2765 if (options
.tags_ecc_overridden
)
2766 param
->no_tags_ecc
= !options
.tags_ecc_on
;
2768 param
->empty_lost_n_found
= 1;
2769 param
->refresh_period
= 500;
2770 param
->disable_summary
= options
.disable_summary
;
2773 #ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING
2774 param
->disable_bad_block_marking
= 1;
2776 if (options
.empty_lost_and_found_overridden
)
2777 param
->empty_lost_n_found
= options
.empty_lost_and_found
;
2779 /* ... and the functions. */
2780 if (yaffs_version
== 2) {
2781 param
->is_yaffs2
= 1;
2782 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2783 param
->total_bytes_per_chunk
= mtd
->writesize
;
2784 param
->chunks_per_block
= mtd
->erasesize
/ mtd
->writesize
;
2786 param
->total_bytes_per_chunk
= mtd
->oobblock
;
2787 param
->chunks_per_block
= mtd
->erasesize
/ mtd
->oobblock
;
2789 n_blocks
= YCALCBLOCKS(mtd
->size
, mtd
->erasesize
);
2791 param
->start_block
= 0;
2792 param
->end_block
= n_blocks
- 1;
2794 param
->is_yaffs2
= 0;
2795 n_blocks
= YCALCBLOCKS(mtd
->size
,
2796 YAFFS_CHUNKS_PER_BLOCK
* YAFFS_BYTES_PER_CHUNK
);
2798 param
->chunks_per_block
= YAFFS_CHUNKS_PER_BLOCK
;
2799 param
->total_bytes_per_chunk
= YAFFS_BYTES_PER_CHUNK
;
2802 param
->start_block
= 0;
2803 param
->end_block
= n_blocks
- 1;
2805 yaffs_mtd_drv_install(dev
);
2807 param
->sb_dirty_fn
= yaffs_set_super_dirty
;
2808 param
->gc_control_fn
= yaffs_gc_control_callback
;
2810 yaffs_dev_to_lc(dev
)->super
= sb
;
2812 param
->use_nand_ecc
= 1;
2814 param
->skip_checkpt_rd
= options
.skip_checkpoint_read
;
2815 param
->skip_checkpt_wr
= options
.skip_checkpoint_write
;
2817 mutex_lock(&yaffs_context_lock
);
2818 /* Get a mount id */
2820 for (mount_id
= 0; !found
; mount_id
++) {
2822 list_for_each(l
, &yaffs_context_list
) {
2824 list_entry(l
, struct yaffs_linux_context
,
2826 if (context_iterator
->mount_id
== mount_id
)
2830 context
->mount_id
= mount_id
;
2832 list_add_tail(&(yaffs_dev_to_lc(dev
)->context_list
),
2833 &yaffs_context_list
);
2834 mutex_unlock(&yaffs_context_lock
);
2836 /* Directory search handling... */
2837 INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev
)->search_contexts
));
2838 param
->remove_obj_fn
= yaffs_remove_obj_callback
;
2840 mutex_init(&(yaffs_dev_to_lc(dev
)->gross_lock
));
2842 yaffs_gross_lock(dev
);
2844 err
= yaffs_guts_initialise(dev
);
2846 yaffs_trace(YAFFS_TRACE_OS
,
2847 "yaffs_read_super: guts initialised %s",
2848 (err
== YAFFS_OK
) ? "OK" : "FAILED");
2850 if (err
== YAFFS_OK
)
2851 yaffs_bg_start(dev
);
2853 if (!context
->bg_thread
)
2854 param
->defered_dir_update
= 0;
2856 sb
->s_maxbytes
= yaffs_max_file_size(dev
);
2858 /* Release lock before yaffs_get_inode() */
2859 yaffs_gross_unlock(dev
);
2861 /* Create root inode */
2862 if (err
== YAFFS_OK
)
2863 inode
= yaffs_get_inode(sb
, S_IFDIR
| 0755, 0, yaffs_root(dev
));
2868 inode
->i_op
= &yaffs_dir_inode_operations
;
2869 inode
->i_fop
= &yaffs_dir_operations
;
2871 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_read_super: got root inode");
2873 root
= yaffs_make_root(inode
);
2879 if(!dev
->is_checkpointed
)
2880 yaffs_set_super_dirty(dev
);
2882 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2883 "yaffs_read_super: is_checkpointed %d",
2884 dev
->is_checkpointed
);
2886 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_read_super: done");
2890 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2891 static int yaffs_internal_read_super_mtd(struct super_block
*sb
, void *data
,
2894 return yaffs_internal_read_super(1, sb
, data
, silent
) ? 0 : -EINVAL
;
2897 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2898 static struct dentry
*yaffs_mount(struct file_system_type
*fs_type
, int flags
,
2899 const char *dev_name
, void *data
)
2901 return mount_bdev(fs_type
, flags
, dev_name
, data
, yaffs_internal_read_super_mtd
);
2903 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2904 static int yaffs_read_super(struct file_system_type
*fs
,
2905 int flags
, const char *dev_name
,
2906 void *data
, struct vfsmount
*mnt
)
2909 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2910 yaffs_internal_read_super_mtd
, mnt
);
2913 static struct super_block
*yaffs_read_super(struct file_system_type
*fs
,
2914 int flags
, const char *dev_name
,
2918 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2919 yaffs_internal_read_super_mtd
);
2923 static struct file_system_type yaffs_fs_type
= {
2924 .owner
= THIS_MODULE
,
2926 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2927 .mount
= yaffs_mount
,
2929 .get_sb
= yaffs_read_super
,
2931 .kill_sb
= kill_block_super
,
2932 .fs_flags
= FS_REQUIRES_DEV
,
2935 static struct super_block
*yaffs_read_super(struct super_block
*sb
, void *data
,
2938 return yaffs_internal_read_super(1, sb
, data
, silent
);
2941 static DECLARE_FSTYPE(yaffs_fs_type
, "yaffs", yaffs_read_super
,
2946 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2947 static int yaffs2_internal_read_super_mtd(struct super_block
*sb
, void *data
,
2950 return yaffs_internal_read_super(2, sb
, data
, silent
) ? 0 : -EINVAL
;
2953 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2954 static struct dentry
*yaffs2_mount(struct file_system_type
*fs_type
, int flags
,
2955 const char *dev_name
, void *data
)
2957 return mount_bdev(fs_type
, flags
, dev_name
, data
, yaffs2_internal_read_super_mtd
);
2959 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2960 static int yaffs2_read_super(struct file_system_type
*fs
,
2961 int flags
, const char *dev_name
, void *data
,
2962 struct vfsmount
*mnt
)
2964 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2965 yaffs2_internal_read_super_mtd
, mnt
);
2968 static struct super_block
*yaffs2_read_super(struct file_system_type
*fs
,
2969 int flags
, const char *dev_name
,
2973 return get_sb_bdev(fs
, flags
, dev_name
, data
,
2974 yaffs2_internal_read_super_mtd
);
2978 static struct file_system_type yaffs2_fs_type
= {
2979 .owner
= THIS_MODULE
,
2981 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2982 .mount
= yaffs2_mount
,
2984 .get_sb
= yaffs2_read_super
,
2986 .kill_sb
= kill_block_super
,
2987 .fs_flags
= FS_REQUIRES_DEV
,
2990 static struct super_block
*yaffs2_read_super(struct super_block
*sb
,
2991 void *data
, int silent
)
2993 return yaffs_internal_read_super(2, sb
, data
, silent
);
2996 static DECLARE_FSTYPE(yaffs2_fs_type
, "yaffs2", yaffs2_read_super
,
3001 static struct proc_dir_entry
*my_proc_entry
;
3003 static char *yaffs_dump_dev_part0(char *buf
, struct yaffs_dev
*dev
)
3005 struct yaffs_param
*param
= &dev
->param
;
3008 yaffs_count_blocks_by_state(dev
,bs
);
3010 buf
+= sprintf(buf
, "start_block.......... %d\n", param
->start_block
);
3011 buf
+= sprintf(buf
, "end_block............ %d\n", param
->end_block
);
3012 buf
+= sprintf(buf
, "total_bytes_per_chunk %d\n",
3013 param
->total_bytes_per_chunk
);
3014 buf
+= sprintf(buf
, "use_nand_ecc......... %d\n", param
->use_nand_ecc
);
3015 buf
+= sprintf(buf
, "no_tags_ecc.......... %d\n", param
->no_tags_ecc
);
3016 buf
+= sprintf(buf
, "is_yaffs2............ %d\n", param
->is_yaffs2
);
3017 buf
+= sprintf(buf
, "inband_tags.......... %d\n", param
->inband_tags
);
3018 buf
+= sprintf(buf
, "empty_lost_n_found... %d\n",
3019 param
->empty_lost_n_found
);
3020 buf
+= sprintf(buf
, "disable_lazy_load.... %d\n",
3021 param
->disable_lazy_load
);
3022 buf
+= sprintf(buf
, "disable_bad_block_mrk %d\n",
3023 param
->disable_bad_block_marking
);
3024 buf
+= sprintf(buf
, "refresh_period....... %d\n",
3025 param
->refresh_period
);
3026 buf
+= sprintf(buf
, "n_caches............. %d\n", param
->n_caches
);
3027 buf
+= sprintf(buf
, "n_reserved_blocks.... %d\n",
3028 param
->n_reserved_blocks
);
3029 buf
+= sprintf(buf
, "always_check_erased.. %d\n",
3030 param
->always_check_erased
);
3031 buf
+= sprintf(buf
, "\n");
3032 buf
+= sprintf(buf
, "block count by state\n");
3033 buf
+= sprintf(buf
, "0:%d 1:%d 2:%d 3:%d 4:%d\n",
3034 bs
[0], bs
[1], bs
[2], bs
[3], bs
[4]);
3035 buf
+= sprintf(buf
, "5:%d 6:%d 7:%d 8:%d 9:%d\n",
3036 bs
[5], bs
[6], bs
[7], bs
[8], bs
[9]);
3041 static char *yaffs_dump_dev_part1(char *buf
, struct yaffs_dev
*dev
)
3043 buf
+= sprintf(buf
, "max file size....... %lld\n",
3044 (long long) yaffs_max_file_size(dev
));
3045 buf
+= sprintf(buf
, "data_bytes_per_chunk. %d\n",
3046 dev
->data_bytes_per_chunk
);
3047 buf
+= sprintf(buf
, "chunk_grp_bits....... %d\n", dev
->chunk_grp_bits
);
3048 buf
+= sprintf(buf
, "chunk_grp_size....... %d\n", dev
->chunk_grp_size
);
3049 buf
+= sprintf(buf
, "n_erased_blocks...... %d\n", dev
->n_erased_blocks
);
3050 buf
+= sprintf(buf
, "blocks_in_checkpt.... %d\n",
3051 dev
->blocks_in_checkpt
);
3052 buf
+= sprintf(buf
, "\n");
3053 buf
+= sprintf(buf
, "n_tnodes............. %d\n", dev
->n_tnodes
);
3054 buf
+= sprintf(buf
, "n_obj................ %d\n", dev
->n_obj
);
3055 buf
+= sprintf(buf
, "n_free_chunks........ %d\n", dev
->n_free_chunks
);
3056 buf
+= sprintf(buf
, "\n");
3057 buf
+= sprintf(buf
, "n_page_writes........ %u\n", dev
->n_page_writes
);
3058 buf
+= sprintf(buf
, "n_page_reads......... %u\n", dev
->n_page_reads
);
3059 buf
+= sprintf(buf
, "n_erasures........... %u\n", dev
->n_erasures
);
3060 buf
+= sprintf(buf
, "n_gc_copies.......... %u\n", dev
->n_gc_copies
);
3061 buf
+= sprintf(buf
, "all_gcs.............. %u\n", dev
->all_gcs
);
3062 buf
+= sprintf(buf
, "passive_gc_count..... %u\n",
3063 dev
->passive_gc_count
);
3064 buf
+= sprintf(buf
, "oldest_dirty_gc_count %u\n",
3065 dev
->oldest_dirty_gc_count
);
3066 buf
+= sprintf(buf
, "n_gc_blocks.......... %u\n", dev
->n_gc_blocks
);
3067 buf
+= sprintf(buf
, "bg_gcs............... %u\n", dev
->bg_gcs
);
3068 buf
+= sprintf(buf
, "n_retried_writes..... %u\n",
3069 dev
->n_retried_writes
);
3070 buf
+= sprintf(buf
, "n_retired_blocks..... %u\n",
3071 dev
->n_retired_blocks
);
3072 buf
+= sprintf(buf
, "n_ecc_fixed.......... %u\n", dev
->n_ecc_fixed
);
3073 buf
+= sprintf(buf
, "n_ecc_unfixed........ %u\n", dev
->n_ecc_unfixed
);
3074 buf
+= sprintf(buf
, "n_tags_ecc_fixed..... %u\n",
3075 dev
->n_tags_ecc_fixed
);
3076 buf
+= sprintf(buf
, "n_tags_ecc_unfixed... %u\n",
3077 dev
->n_tags_ecc_unfixed
);
3078 buf
+= sprintf(buf
, "cache_hits........... %u\n", dev
->cache_hits
);
3079 buf
+= sprintf(buf
, "n_deleted_files...... %u\n", dev
->n_deleted_files
);
3080 buf
+= sprintf(buf
, "n_unlinked_files..... %u\n",
3081 dev
->n_unlinked_files
);
3082 buf
+= sprintf(buf
, "refresh_count........ %u\n", dev
->refresh_count
);
3083 buf
+= sprintf(buf
, "n_bg_deletions....... %u\n", dev
->n_bg_deletions
);
3084 buf
+= sprintf(buf
, "tags_used............ %u\n", dev
->tags_used
);
3085 buf
+= sprintf(buf
, "summary_used......... %u\n", dev
->summary_used
);
3090 static int yaffs_proc_read(char *page
,
3092 off_t offset
, int count
, int *eof
, void *data
)
3094 struct list_head
*item
;
3099 /* Get proc_file_read() to step 'offset' by one on each sucessive call.
3100 * We use 'offset' (*ppos) to indicate where we are in dev_list.
3101 * This also assumes the user has posted a read buffer large
3102 * enough to hold the complete output; but that's life in /proc.
3107 /* Print header first */
3111 "Multi-version YAFFS built:" __DATE__
" " __TIME__
3114 buf
+= sprintf(buf
, "\n");
3118 mutex_lock(&yaffs_context_lock
);
3120 /* Locate and print the Nth entry. Order N-squared but N is small. */
3121 list_for_each(item
, &yaffs_context_list
) {
3122 struct yaffs_linux_context
*dc
=
3123 list_entry(item
, struct yaffs_linux_context
,
3125 struct yaffs_dev
*dev
= dc
->dev
;
3127 if (n
< (step
& ~1)) {
3131 if ((step
& 1) == 0) {
3133 sprintf(buf
, "\nDevice %d \"%s\"\n", n
,
3135 buf
= yaffs_dump_dev_part0(buf
, dev
);
3137 buf
= yaffs_dump_dev_part1(buf
, dev
);
3142 mutex_unlock(&yaffs_context_lock
);
3145 return buf
- page
< count
? buf
- page
: count
;
3149 * Set the verbosity of the warnings and error messages.
3151 * Note that the names can only be a..z or _ with the current code.
3156 unsigned mask_bitfield
;
3158 {"allocate", YAFFS_TRACE_ALLOCATE
},
3159 {"always", YAFFS_TRACE_ALWAYS
},
3160 {"background", YAFFS_TRACE_BACKGROUND
},
3161 {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS
},
3162 {"buffers", YAFFS_TRACE_BUFFERS
},
3163 {"bug", YAFFS_TRACE_BUG
},
3164 {"checkpt", YAFFS_TRACE_CHECKPOINT
},
3165 {"deletion", YAFFS_TRACE_DELETION
},
3166 {"erase", YAFFS_TRACE_ERASE
},
3167 {"error", YAFFS_TRACE_ERROR
},
3168 {"gc_detail", YAFFS_TRACE_GC_DETAIL
},
3169 {"gc", YAFFS_TRACE_GC
},
3170 {"lock", YAFFS_TRACE_LOCK
},
3171 {"mtd", YAFFS_TRACE_MTD
},
3172 {"nandaccess", YAFFS_TRACE_NANDACCESS
},
3173 {"os", YAFFS_TRACE_OS
},
3174 {"scan_debug", YAFFS_TRACE_SCAN_DEBUG
},
3175 {"scan", YAFFS_TRACE_SCAN
},
3176 {"mount", YAFFS_TRACE_MOUNT
},
3177 {"tracing", YAFFS_TRACE_TRACING
},
3178 {"sync", YAFFS_TRACE_SYNC
},
3179 {"write", YAFFS_TRACE_WRITE
},
3180 {"verify", YAFFS_TRACE_VERIFY
},
3181 {"verify_nand", YAFFS_TRACE_VERIFY_NAND
},
3182 {"verify_full", YAFFS_TRACE_VERIFY_FULL
},
3183 {"verify_all", YAFFS_TRACE_VERIFY_ALL
},
3184 {"all", 0xffffffff},
3189 #define MAX_MASK_NAME_LENGTH 40
3190 static int yaffs_proc_write_trace_options(struct file
*file
, const char *buf
,
3191 unsigned long count
, void *data
)
3193 unsigned rg
= 0, mask_bitfield
;
3197 char substring
[MAX_MASK_NAME_LENGTH
+ 1];
3203 rg
= yaffs_trace_mask
;
3205 while (!done
&& (pos
< count
)) {
3207 while ((pos
< count
) && isspace(buf
[pos
]))
3224 mask_bitfield
= simple_strtoul(buf
+ pos
, &end
, 0);
3226 if (end
> buf
+ pos
) {
3227 mask_name
= "numeral";
3228 len
= end
- (buf
+ pos
);
3232 for (x
= buf
+ pos
, i
= 0;
3233 (*x
== '_' || (*x
>= 'a' && *x
<= 'z')) &&
3234 i
< MAX_MASK_NAME_LENGTH
; x
++, i
++, pos
++)
3236 substring
[i
] = '\0';
3238 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
3239 if (strcmp(substring
, mask_flags
[i
].mask_name
)
3241 mask_name
= mask_flags
[i
].mask_name
;
3243 mask_flags
[i
].mask_bitfield
;
3250 if (mask_name
!= NULL
) {
3254 rg
&= ~mask_bitfield
;
3257 rg
|= mask_bitfield
;
3263 rg
|= mask_bitfield
;
3269 yaffs_trace_mask
= rg
| YAFFS_TRACE_ALWAYS
;
3271 printk(KERN_DEBUG
"new trace = 0x%08X\n", yaffs_trace_mask
);
3273 if (rg
& YAFFS_TRACE_ALWAYS
) {
3274 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
3276 flag
= ((rg
& mask_flags
[i
].mask_bitfield
) ==
3277 mask_flags
[i
].mask_bitfield
) ? '+' : '-';
3278 printk(KERN_DEBUG
"%c%s\n", flag
,
3279 mask_flags
[i
].mask_name
);
3286 /* Debug strings are of the form:
3287 * .bnnn print info on block n
3288 * .cobjn,chunkn print nand chunk id for objn:chunkn
3291 static int yaffs_proc_debug_write(struct file
*file
, const char *buf
,
3292 unsigned long count
, void *data
)
3301 struct list_head
*item
;
3303 memset(str
, 0, sizeof(str
));
3304 memcpy(str
, buf
, min(count
, sizeof(str
) -1));
3312 while (*p1
&& *p1
!= ',') {
3318 p0_val
= simple_strtol(p0
, NULL
, 0);
3319 p1_val
= simple_strtol(p1
, NULL
, 0);
3322 mutex_lock(&yaffs_context_lock
);
3324 /* Locate and print the Nth entry. Order N-squared but N is small. */
3325 list_for_each(item
, &yaffs_context_list
) {
3326 struct yaffs_linux_context
*dc
=
3327 list_entry(item
, struct yaffs_linux_context
,
3329 struct yaffs_dev
*dev
= dc
->dev
;
3332 struct yaffs_block_info
*bi
;
3334 bi
= yaffs_get_block_info(dev
,p0_val
);
3337 printk("Block %d: state %d, retire %d, use %d, seq %d\n",
3338 (int)p0_val
, bi
->block_state
,
3339 bi
->needs_retiring
, bi
->pages_in_use
,
3342 } else if (cmd
== 'c') {
3343 struct yaffs_obj
*obj
;
3346 obj
= yaffs_find_by_number(dev
, p0_val
);
3348 printk("No obj %d\n", (int)p0_val
);
3351 nand_chunk
= obj
->hdr_chunk
;
3354 yaffs_find_chunk_in_file(obj
,
3356 printk("Nand chunk for %d:%d is %d\n",
3357 (int)p0_val
, (int)p1_val
, nand_chunk
);
3362 mutex_unlock(&yaffs_context_lock
);
3367 static int yaffs_proc_write(struct file
*file
, const char *buf
,
3368 unsigned long count
, void *data
)
3371 return yaffs_proc_debug_write(file
, buf
, count
, data
);
3372 return yaffs_proc_write_trace_options(file
, buf
, count
, data
);
3375 /* Stuff to handle installation of file systems */
3376 struct file_system_to_install
{
3377 struct file_system_type
*fst
;
3381 static struct file_system_to_install fs_to_install
[] = {
3382 {&yaffs_fs_type
, 0},
3383 {&yaffs2_fs_type
, 0},
3387 static int __init
init_yaffs_fs(void)
3390 struct file_system_to_install
*fsinst
;
3392 yaffs_trace(YAFFS_TRACE_ALWAYS
,
3393 "yaffs built " __DATE__
" " __TIME__
" Installing.");
3395 mutex_init(&yaffs_context_lock
);
3397 /* Install the proc_fs entries */
3398 my_proc_entry
= create_proc_entry("yaffs",
3399 S_IRUGO
| S_IFREG
, YPROC_ROOT
);
3401 if (my_proc_entry
) {
3402 my_proc_entry
->write_proc
= yaffs_proc_write
;
3403 my_proc_entry
->read_proc
= yaffs_proc_read
;
3404 my_proc_entry
->data
= NULL
;
3409 /* Now add the file system entries */
3411 fsinst
= fs_to_install
;
3413 while (fsinst
->fst
&& !error
) {
3414 error
= register_filesystem(fsinst
->fst
);
3416 fsinst
->installed
= 1;
3420 /* Any errors? uninstall */
3422 fsinst
= fs_to_install
;
3424 while (fsinst
->fst
) {
3425 if (fsinst
->installed
) {
3426 unregister_filesystem(fsinst
->fst
);
3427 fsinst
->installed
= 0;
3436 static void __exit
exit_yaffs_fs(void)
3439 struct file_system_to_install
*fsinst
;
3441 yaffs_trace(YAFFS_TRACE_ALWAYS
,
3442 "yaffs built " __DATE__
" " __TIME__
" removing.");
3444 remove_proc_entry("yaffs", YPROC_ROOT
);
3446 fsinst
= fs_to_install
;
3448 while (fsinst
->fst
) {
3449 if (fsinst
->installed
) {
3450 unregister_filesystem(fsinst
->fst
);
3451 fsinst
->installed
= 0;
3457 module_init(init_yaffs_fs
)
3458 module_exit(exit_yaffs_fs
)
3460 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
3461 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
3462 MODULE_LICENSE("GPL");