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)
239 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
240 #define YAFFS_USE_DIR_ITERATE
243 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
244 #define YAFFS_NEW_PROCFS
245 #include <linux/seq_file.h>
249 #define update_dir_time(dir) do {\
250 (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
253 static void yaffs_fill_inode_from_obj(struct inode
*inode
,
254 struct yaffs_obj
*obj
);
257 static void yaffs_gross_lock(struct yaffs_dev
*dev
)
259 yaffs_trace(YAFFS_TRACE_LOCK
, "yaffs locking %p", current
);
260 mutex_lock(&(yaffs_dev_to_lc(dev
)->gross_lock
));
261 yaffs_trace(YAFFS_TRACE_LOCK
, "yaffs locked %p", current
);
264 static void yaffs_gross_unlock(struct yaffs_dev
*dev
)
266 yaffs_trace(YAFFS_TRACE_LOCK
, "yaffs unlocking %p", current
);
267 mutex_unlock(&(yaffs_dev_to_lc(dev
)->gross_lock
));
271 static int yaffs_readpage_nolock(struct file
*f
, struct page
*pg
)
273 /* Lifted from jffs2 */
275 struct yaffs_obj
*obj
;
276 unsigned char *pg_buf
;
278 loff_t pos
= ((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
;
279 struct yaffs_dev
*dev
;
281 yaffs_trace(YAFFS_TRACE_OS
,
282 "yaffs_readpage_nolock at %lld, size %08x",
284 (unsigned)PAGE_CACHE_SIZE
);
286 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
290 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
291 BUG_ON(!PageLocked(pg
));
298 /* FIXME: Can kmap fail? */
300 yaffs_gross_lock(dev
);
302 ret
= yaffs_file_rd(obj
, pg_buf
, pos
, PAGE_CACHE_SIZE
);
304 yaffs_gross_unlock(dev
);
310 ClearPageUptodate(pg
);
317 flush_dcache_page(pg
);
320 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_readpage_nolock done");
324 static int yaffs_readpage_unlock(struct file
*f
, struct page
*pg
)
326 int ret
= yaffs_readpage_nolock(f
, pg
);
331 static int yaffs_readpage(struct file
*f
, struct page
*pg
)
335 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_readpage");
336 ret
= yaffs_readpage_unlock(f
, pg
);
337 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_readpage done");
342 static void yaffs_set_super_dirty_val(struct yaffs_dev
*dev
, int val
)
344 struct yaffs_linux_context
*lc
= yaffs_dev_to_lc(dev
);
349 # ifdef YAFFS_SUPER_HAS_DIRTY
351 struct super_block
*sb
= lc
->super
;
360 static void yaffs_set_super_dirty(struct yaffs_dev
*dev
)
362 yaffs_set_super_dirty_val(dev
, 1);
365 static void yaffs_clear_super_dirty(struct yaffs_dev
*dev
)
367 yaffs_set_super_dirty_val(dev
, 0);
370 static int yaffs_check_super_dirty(struct yaffs_dev
*dev
)
372 struct yaffs_linux_context
*lc
= yaffs_dev_to_lc(dev
);
377 # ifdef YAFFS_SUPER_HAS_DIRTY
379 struct super_block
*sb
= lc
->super
;
381 if (sb
&& sb
->s_dirt
)
389 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
390 static int yaffs_writepage(struct page
*page
, struct writeback_control
*wbc
)
392 static int yaffs_writepage(struct page
*page
)
395 struct yaffs_dev
*dev
;
396 struct address_space
*mapping
= page
->mapping
;
398 unsigned long end_index
;
400 struct yaffs_obj
*obj
;
407 inode
= mapping
->host
;
410 i_size
= i_size_read(inode
);
412 end_index
= i_size
>> PAGE_CACHE_SHIFT
;
414 if (page
->index
< end_index
)
415 n_bytes
= PAGE_CACHE_SIZE
;
417 n_bytes
= i_size
& (PAGE_CACHE_SIZE
- 1);
419 if (page
->index
> end_index
|| !n_bytes
) {
420 yaffs_trace(YAFFS_TRACE_OS
,
421 "yaffs_writepage at %lld, inode size = %lld!!",
422 ((loff_t
)page
->index
) << PAGE_CACHE_SHIFT
,
424 yaffs_trace(YAFFS_TRACE_OS
,
427 zero_user_segment(page
, 0, PAGE_CACHE_SIZE
);
428 set_page_writeback(page
);
430 end_page_writeback(page
);
435 if (n_bytes
!= PAGE_CACHE_SIZE
)
436 zero_user_segment(page
, n_bytes
, PAGE_CACHE_SIZE
);
442 obj
= yaffs_inode_to_obj(inode
);
444 yaffs_gross_lock(dev
);
446 yaffs_trace(YAFFS_TRACE_OS
,
447 "yaffs_writepage at %lld, size %08x",
448 ((loff_t
)page
->index
) << PAGE_CACHE_SHIFT
, n_bytes
);
449 yaffs_trace(YAFFS_TRACE_OS
,
450 "writepag0: obj = %lld, ino = %lld",
451 obj
->variant
.file_variant
.file_size
, inode
->i_size
);
453 n_written
= yaffs_wr_file(obj
, buffer
,
454 ((loff_t
)page
->index
) << PAGE_CACHE_SHIFT
, n_bytes
, 0);
456 yaffs_set_super_dirty(dev
);
458 yaffs_trace(YAFFS_TRACE_OS
,
459 "writepag1: obj = %lld, ino = %lld",
460 obj
->variant
.file_variant
.file_size
, inode
->i_size
);
462 yaffs_gross_unlock(dev
);
465 set_page_writeback(page
);
467 end_page_writeback(page
);
470 return (n_written
== n_bytes
) ? 0 : -ENOSPC
;
473 /* Space holding and freeing is done to ensure we have space available for write_begin/end */
474 /* For now we just assume few parallel writes and check against a small number. */
475 /* Todo: need to do this with a counter to handle parallel reads better */
477 static ssize_t
yaffs_hold_space(struct file
*f
)
479 struct yaffs_obj
*obj
;
480 struct yaffs_dev
*dev
;
484 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
488 yaffs_gross_lock(dev
);
490 n_free_chunks
= yaffs_get_n_free_chunks(dev
);
492 yaffs_gross_unlock(dev
);
494 return (n_free_chunks
> 20) ? 1 : 0;
497 static void yaffs_release_space(struct file
*f
)
499 struct yaffs_obj
*obj
;
500 struct yaffs_dev
*dev
;
502 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
506 yaffs_gross_lock(dev
);
508 yaffs_gross_unlock(dev
);
511 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
512 static int yaffs_write_begin(struct file
*filp
, struct address_space
*mapping
,
513 loff_t pos
, unsigned len
, unsigned flags
,
514 struct page
**pagep
, void **fsdata
)
516 struct page
*pg
= NULL
;
517 pgoff_t index
= pos
>> PAGE_CACHE_SHIFT
;
523 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
524 pg
= grab_cache_page_write_begin(mapping
, index
, flags
);
526 pg
= __grab_cache_page(mapping
, index
);
534 yaffs_trace(YAFFS_TRACE_OS
,
535 "start yaffs_write_begin index %d(%x) uptodate %d",
536 (int)index
, (int)index
, Page_Uptodate(pg
) ? 1 : 0);
539 space_held
= yaffs_hold_space(filp
);
546 /* Update page if required */
548 if (!Page_Uptodate(pg
))
549 ret
= yaffs_readpage_nolock(filp
, pg
);
554 /* Happy path return */
555 yaffs_trace(YAFFS_TRACE_OS
, "end yaffs_write_begin - ok");
560 yaffs_trace(YAFFS_TRACE_OS
,
561 "end yaffs_write_begin fail returning %d", ret
);
563 yaffs_release_space(filp
);
566 page_cache_release(pg
);
573 static int yaffs_prepare_write(struct file
*f
, struct page
*pg
,
574 unsigned offset
, unsigned to
)
576 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_prepair_write");
578 if (!Page_Uptodate(pg
))
579 return yaffs_readpage_nolock(f
, pg
);
585 static ssize_t
yaffs_file_write(struct file
*f
, const char *buf
, size_t n
,
588 struct yaffs_obj
*obj
;
592 struct yaffs_dev
*dev
;
594 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
597 yaffs_trace(YAFFS_TRACE_OS
,
598 "yaffs_file_write: hey obj is null!");
604 yaffs_gross_lock(dev
);
606 inode
= f
->f_dentry
->d_inode
;
608 if (!S_ISBLK(inode
->i_mode
) && f
->f_flags
& O_APPEND
)
609 ipos
= inode
->i_size
;
613 yaffs_trace(YAFFS_TRACE_OS
,
614 "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
615 (unsigned)n
, (unsigned)n
, obj
->obj_id
, ipos
);
617 n_written
= yaffs_wr_file(obj
, buf
, ipos
, n
, 0);
619 yaffs_set_super_dirty(dev
);
621 yaffs_trace(YAFFS_TRACE_OS
,
622 "yaffs_file_write: %d(%x) bytes written",
623 (unsigned)n
, (unsigned)n
);
628 if (ipos
> inode
->i_size
) {
629 inode
->i_size
= ipos
;
630 inode
->i_blocks
= (ipos
+ 511) >> 9;
632 yaffs_trace(YAFFS_TRACE_OS
,
633 "yaffs_file_write size updated to %lld bytes, %d blocks",
634 ipos
, (int)(inode
->i_blocks
));
638 yaffs_gross_unlock(dev
);
639 return (n_written
== 0) && (n
> 0) ? -ENOSPC
: n_written
;
643 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
644 static int yaffs_write_end(struct file
*filp
, struct address_space
*mapping
,
645 loff_t pos
, unsigned len
, unsigned copied
,
646 struct page
*pg
, void *fsdadata
)
650 uint32_t offset_into_page
= pos
& (PAGE_CACHE_SIZE
- 1);
653 addr
= kva
+ offset_into_page
;
655 yaffs_trace(YAFFS_TRACE_OS
,
656 "yaffs_write_end addr %p pos %lld n_bytes %d",
659 ret
= yaffs_file_write(filp
, addr
, copied
, &pos
);
662 yaffs_trace(YAFFS_TRACE_OS
,
663 "yaffs_write_end not same size ret %d copied %d",
670 yaffs_release_space(filp
);
672 page_cache_release(pg
);
677 static int yaffs_commit_write(struct file
*f
, struct page
*pg
, unsigned offset
,
682 loff_t pos
= (((loff_t
) pg
->index
) << PAGE_CACHE_SHIFT
) + offset
;
683 int n_bytes
= to
- offset
;
689 yaffs_trace(YAFFS_TRACE_OS
,
690 "yaffs_commit_write addr %p pos %lld n_bytes %d",
693 n_written
= yaffs_file_write(f
, addr
, n_bytes
, &pos
);
695 if (n_written
!= n_bytes
) {
696 yaffs_trace(YAFFS_TRACE_OS
,
697 "yaffs_commit_write not same size n_written %d n_bytes %d",
703 yaffs_trace(YAFFS_TRACE_OS
,
704 "yaffs_commit_write returning %d",
705 n_written
== n_bytes
? 0 : n_written
);
707 return n_written
== n_bytes
? 0 : n_written
;
711 static struct address_space_operations yaffs_file_address_operations
= {
712 .readpage
= yaffs_readpage
,
713 .writepage
= yaffs_writepage
,
714 #if (YAFFS_USE_WRITE_BEGIN_END > 0)
715 .write_begin
= yaffs_write_begin
,
716 .write_end
= yaffs_write_end
,
718 .prepare_write
= yaffs_prepare_write
,
719 .commit_write
= yaffs_commit_write
,
724 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
725 static int yaffs_file_flush(struct file
*file
, fl_owner_t id
)
727 static int yaffs_file_flush(struct file
*file
)
730 struct yaffs_obj
*obj
= yaffs_dentry_to_obj(file
->f_dentry
);
732 struct yaffs_dev
*dev
= obj
->my_dev
;
734 yaffs_trace(YAFFS_TRACE_OS
,
735 "yaffs_file_flush object %d (%s)",
737 obj
->dirty
? "dirty" : "clean");
739 yaffs_gross_lock(dev
);
741 yaffs_flush_file(obj
, 1, 0);
743 yaffs_gross_unlock(dev
);
749 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
750 static int yaffs_sync_object(struct file
*file
, loff_t start
, loff_t end
, int datasync
)
751 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
752 static int yaffs_sync_object(struct file
*file
, int datasync
)
754 static int yaffs_sync_object(struct file
*file
, struct dentry
*dentry
,
758 struct yaffs_obj
*obj
;
759 struct yaffs_dev
*dev
;
760 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
761 struct dentry
*dentry
= file
->f_path
.dentry
;
764 obj
= yaffs_dentry_to_obj(dentry
);
768 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
,
769 "yaffs_sync_object");
770 yaffs_gross_lock(dev
);
771 yaffs_flush_file(obj
, 1, datasync
);
772 yaffs_gross_unlock(dev
);
777 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
778 static const struct file_operations yaffs_file_operations
= {
779 .read
= do_sync_read
,
780 .write
= do_sync_write
,
781 .aio_read
= generic_file_aio_read
,
782 .aio_write
= generic_file_aio_write
,
783 .mmap
= generic_file_mmap
,
784 .flush
= yaffs_file_flush
,
785 .fsync
= yaffs_sync_object
,
786 .splice_read
= generic_file_splice_read
,
787 .splice_write
= generic_file_splice_write
,
788 .llseek
= generic_file_llseek
,
791 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
793 static const struct file_operations yaffs_file_operations
= {
794 .read
= do_sync_read
,
795 .write
= do_sync_write
,
796 .aio_read
= generic_file_aio_read
,
797 .aio_write
= generic_file_aio_write
,
798 .mmap
= generic_file_mmap
,
799 .flush
= yaffs_file_flush
,
800 .fsync
= yaffs_sync_object
,
801 .sendfile
= generic_file_sendfile
,
806 static const struct file_operations yaffs_file_operations
= {
807 .read
= generic_file_read
,
808 .write
= generic_file_write
,
809 .mmap
= generic_file_mmap
,
810 .flush
= yaffs_file_flush
,
811 .fsync
= yaffs_sync_object
,
812 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
813 .sendfile
= generic_file_sendfile
,
821 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
822 static void zero_user_segment(struct page
*page
, unsigned start
, unsigned end
)
824 void *kaddr
= kmap_atomic(page
, KM_USER0
);
825 memset(kaddr
+ start
, 0, end
- start
);
826 kunmap_atomic(kaddr
, KM_USER0
);
827 flush_dcache_page(page
);
832 static int yaffs_vfs_setsize(struct inode
*inode
, loff_t newsize
)
834 #ifdef YAFFS_USE_TRUNCATE_SETSIZE
835 truncate_setsize(inode
, newsize
);
838 truncate_inode_pages(&inode
->i_data
, newsize
);
845 static int yaffs_vfs_setattr(struct inode
*inode
, struct iattr
*attr
)
847 #ifdef YAFFS_USE_SETATTR_COPY
848 setattr_copy(inode
, attr
);
851 return inode_setattr(inode
, attr
);
856 static int yaffs_setattr(struct dentry
*dentry
, struct iattr
*attr
)
858 struct inode
*inode
= dentry
->d_inode
;
860 struct yaffs_dev
*dev
;
862 yaffs_trace(YAFFS_TRACE_OS
,
863 "yaffs_setattr of object %d",
864 yaffs_inode_to_obj(inode
)->obj_id
);
866 /* Fail if a requested resize >= 2GB */
867 if (attr
->ia_valid
& ATTR_SIZE
&& (attr
->ia_size
>> 31))
872 error
= inode_change_ok(inode
, attr
);
876 error
= yaffs_vfs_setattr(inode
, attr
);
877 yaffs_trace(YAFFS_TRACE_OS
, "inode_setattr called");
878 if (attr
->ia_valid
& ATTR_SIZE
) {
879 yaffs_vfs_setsize(inode
, attr
->ia_size
);
880 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
883 dev
= yaffs_inode_to_obj(inode
)->my_dev
;
884 if (attr
->ia_valid
& ATTR_SIZE
) {
885 yaffs_trace(YAFFS_TRACE_OS
,
887 (int)(attr
->ia_size
),
888 (int)(attr
->ia_size
));
890 yaffs_gross_lock(dev
);
891 result
= yaffs_set_attribs(yaffs_inode_to_obj(inode
), attr
);
892 if (result
== YAFFS_OK
) {
897 yaffs_gross_unlock(dev
);
901 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_setattr done returning %d", error
);
906 static int yaffs_setxattr(struct dentry
*dentry
, const char *name
,
907 const void *value
, size_t size
, int flags
)
909 struct inode
*inode
= dentry
->d_inode
;
911 struct yaffs_dev
*dev
;
912 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
914 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_setxattr of object %d", obj
->obj_id
);
919 yaffs_gross_lock(dev
);
920 result
= yaffs_set_xattrib(obj
, name
, value
, size
, flags
);
921 if (result
== YAFFS_OK
)
925 yaffs_gross_unlock(dev
);
928 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_setxattr done returning %d", error
);
933 static ssize_t
yaffs_getxattr(struct dentry
* dentry
, const char *name
,
934 void *buff
, size_t size
)
936 struct inode
*inode
= dentry
->d_inode
;
938 struct yaffs_dev
*dev
;
939 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
941 yaffs_trace(YAFFS_TRACE_OS
,
942 "yaffs_getxattr \"%s\" from object %d",
947 yaffs_gross_lock(dev
);
948 error
= yaffs_get_xattrib(obj
, name
, buff
, size
);
949 yaffs_gross_unlock(dev
);
952 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_getxattr done returning %d", error
);
957 static int yaffs_removexattr(struct dentry
*dentry
, const char *name
)
959 struct inode
*inode
= dentry
->d_inode
;
961 struct yaffs_dev
*dev
;
962 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
964 yaffs_trace(YAFFS_TRACE_OS
,
965 "yaffs_removexattr of object %d", obj
->obj_id
);
970 yaffs_gross_lock(dev
);
971 result
= yaffs_remove_xattrib(obj
, name
);
972 if (result
== YAFFS_OK
)
976 yaffs_gross_unlock(dev
);
979 yaffs_trace(YAFFS_TRACE_OS
,
980 "yaffs_removexattr done returning %d", error
);
985 static ssize_t
yaffs_listxattr(struct dentry
* dentry
, char *buff
, size_t size
)
987 struct inode
*inode
= dentry
->d_inode
;
989 struct yaffs_dev
*dev
;
990 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
992 yaffs_trace(YAFFS_TRACE_OS
,
993 "yaffs_listxattr of object %d", obj
->obj_id
);
997 yaffs_gross_lock(dev
);
998 error
= yaffs_list_xattrib(obj
, buff
, size
);
999 yaffs_gross_unlock(dev
);
1002 yaffs_trace(YAFFS_TRACE_OS
,
1003 "yaffs_listxattr done returning %d", error
);
1009 static const struct inode_operations yaffs_file_inode_operations
= {
1010 .setattr
= yaffs_setattr
,
1011 .setxattr
= yaffs_setxattr
,
1012 .getxattr
= yaffs_getxattr
,
1013 .listxattr
= yaffs_listxattr
,
1014 .removexattr
= yaffs_removexattr
,
1018 static int yaffs_readlink(struct dentry
*dentry
, char __user
* buffer
,
1021 unsigned char *alias
;
1024 struct yaffs_dev
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
1026 yaffs_gross_lock(dev
);
1028 alias
= yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry
));
1030 yaffs_gross_unlock(dev
);
1035 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
1036 ret
= vfs_readlink(dentry
, buffer
, buflen
, alias
);
1038 ret
= readlink_copy(buffer
, buflen
, alias
);
1044 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1045 static void *yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
1049 static int yaffs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
1053 unsigned char *alias
;
1055 struct yaffs_dev
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
1057 yaffs_gross_lock(dev
);
1059 alias
= yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry
));
1060 yaffs_gross_unlock(dev
);
1066 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1067 nd_set_link(nd
, alias
);
1071 ret
= ERR_PTR(ret_int
);
1074 ret
= vfs_follow_link(nd
, alias
);
1084 #ifdef YAFFS_HAS_PUT_INODE
1086 /* For now put inode is just for debugging
1087 * Put inode is called when the inode **structure** is put.
1089 static void yaffs_put_inode(struct inode
*inode
)
1091 yaffs_trace(YAFFS_TRACE_OS
,
1092 "yaffs_put_inode: ino %d, count %d"),
1093 (int)inode
->i_ino
, atomic_read(&inode
->i_count
);
1098 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1099 void yaffs_put_link(struct dentry
*dentry
, struct nameidata
*nd
, void *alias
)
1105 static const struct inode_operations yaffs_symlink_inode_operations
= {
1106 .readlink
= yaffs_readlink
,
1107 .follow_link
= yaffs_follow_link
,
1108 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1109 .put_link
= yaffs_put_link
,
1111 .setattr
= yaffs_setattr
,
1112 .setxattr
= yaffs_setxattr
,
1113 .getxattr
= yaffs_getxattr
,
1114 .listxattr
= yaffs_listxattr
,
1115 .removexattr
= yaffs_removexattr
,
1118 #ifdef YAFFS_USE_OWN_IGET
1120 static struct inode
*yaffs_iget(struct super_block
*sb
, unsigned long ino
)
1122 struct inode
*inode
;
1123 struct yaffs_obj
*obj
;
1124 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
1126 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_iget for %lu", ino
);
1128 inode
= iget_locked(sb
, ino
);
1130 return ERR_PTR(-ENOMEM
);
1131 if (!(inode
->i_state
& I_NEW
))
1134 /* NB This is called as a side effect of other functions, but
1135 * we had to release the lock to prevent deadlocks, so
1136 * need to lock again.
1139 yaffs_gross_lock(dev
);
1141 obj
= yaffs_find_by_number(dev
, inode
->i_ino
);
1143 yaffs_fill_inode_from_obj(inode
, obj
);
1145 yaffs_gross_unlock(dev
);
1147 unlock_new_inode(inode
);
1153 static void yaffs_read_inode(struct inode
*inode
)
1155 /* NB This is called as a side effect of other functions, but
1156 * we had to release the lock to prevent deadlocks, so
1157 * need to lock again.
1160 struct yaffs_obj
*obj
;
1161 struct yaffs_dev
*dev
= yaffs_super_to_dev(inode
->i_sb
);
1163 yaffs_trace(YAFFS_TRACE_OS
,
1164 "yaffs_read_inode for %d", (int)inode
->i_ino
);
1166 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1167 yaffs_gross_lock(dev
);
1169 obj
= yaffs_find_by_number(dev
, inode
->i_ino
);
1171 yaffs_fill_inode_from_obj(inode
, obj
);
1173 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1174 yaffs_gross_unlock(dev
);
1181 struct inode
*yaffs_get_inode(struct super_block
*sb
, int mode
, int dev
,
1182 struct yaffs_obj
*obj
)
1184 struct inode
*inode
;
1187 yaffs_trace(YAFFS_TRACE_OS
,
1188 "yaffs_get_inode for NULL super_block!!");
1194 yaffs_trace(YAFFS_TRACE_OS
,
1195 "yaffs_get_inode for NULL object!!");
1200 yaffs_trace(YAFFS_TRACE_OS
,
1201 "yaffs_get_inode for object %d", obj
->obj_id
);
1203 inode
= Y_IGET(sb
, obj
->obj_id
);
1207 /* NB Side effect: iget calls back to yaffs_read_inode(). */
1208 /* iget also increments the inode's i_count */
1209 /* NB You can't be holding gross_lock or deadlock will happen! */
1216 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
1219 #define YCRED(x) (x->cred)
1222 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
1223 #define YPROC_uid(p) (YCRED(p)->fsuid)
1224 #define YPROC_gid(p) (YCRED(p)->fsgid)
1225 #define EXTRACT_gid(x) x
1226 #define EXTRACT_uid(x) x
1227 #define MAKE_gid(x) x
1228 #define MAKE_uid(x) x
1230 #define YPROC_uid(p) from_kuid(&init_user_ns, YCRED(p)->fsuid)
1231 #define YPROC_gid(p) from_kgid(&init_user_ns, YCRED(p)->fsgid)
1232 #define EXTRACT_gid(x) from_kgid(&init_user_ns, x)
1233 #define EXTRACT_uid(x) from_kuid(&init_user_ns, x)
1234 #define MAKE_gid(x) make_kgid(&init_user_ns, x)
1235 #define MAKE_uid(x) make_kuid(&init_user_ns, x)
1239 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1240 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
1242 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1243 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1246 static int yaffs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1250 struct inode
*inode
;
1252 struct yaffs_obj
*obj
= NULL
;
1253 struct yaffs_dev
*dev
;
1255 struct yaffs_obj
*parent
= yaffs_inode_to_obj(dir
);
1257 int error
= -ENOSPC
;
1258 uid_t uid
= YPROC_uid(current
);
1260 (dir
->i_mode
& S_ISGID
) ? EXTRACT_gid(dir
->i_gid
) : YPROC_gid(current
);
1262 if ((dir
->i_mode
& S_ISGID
) && S_ISDIR(mode
))
1266 yaffs_trace(YAFFS_TRACE_OS
,
1267 "yaffs_mknod: parent object %d type %d",
1268 parent
->obj_id
, parent
->variant_type
);
1270 yaffs_trace(YAFFS_TRACE_OS
,
1271 "yaffs_mknod: could not get parent object");
1275 yaffs_trace(YAFFS_TRACE_OS
,
1276 "yaffs_mknod: making oject for %s, mode %x dev %x",
1277 dentry
->d_name
.name
, mode
, rdev
);
1279 dev
= parent
->my_dev
;
1281 yaffs_gross_lock(dev
);
1283 switch (mode
& S_IFMT
) {
1285 /* Special (socket, fifo, device...) */
1286 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making special");
1287 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1289 yaffs_create_special(parent
, dentry
->d_name
.name
, mode
, uid
,
1290 gid
, old_encode_dev(rdev
));
1293 yaffs_create_special(parent
, dentry
->d_name
.name
, mode
, uid
,
1297 case S_IFREG
: /* file */
1298 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making file");
1299 obj
= yaffs_create_file(parent
, dentry
->d_name
.name
, mode
, uid
,
1302 case S_IFDIR
: /* directory */
1303 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making directory");
1304 obj
= yaffs_create_dir(parent
, dentry
->d_name
.name
, mode
,
1307 case S_IFLNK
: /* symlink */
1308 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod: making symlink");
1309 obj
= NULL
; /* Do we ever get here? */
1313 /* Can not call yaffs_get_inode() with gross lock held */
1314 yaffs_gross_unlock(dev
);
1317 inode
= yaffs_get_inode(dir
->i_sb
, mode
, rdev
, obj
);
1318 d_instantiate(dentry
, inode
);
1319 update_dir_time(dir
);
1320 yaffs_trace(YAFFS_TRACE_OS
,
1321 "yaffs_mknod created object %d count = %d",
1322 obj
->obj_id
, atomic_read(&inode
->i_count
));
1324 yaffs_fill_inode_from_obj(dir
, parent
);
1326 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mknod failed making object");
1333 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1334 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
)
1336 static int yaffs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1340 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_mkdir");
1341 ret_val
= yaffs_mknod(dir
, dentry
, mode
| S_IFDIR
, 0);
1346 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1347 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
1349 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1350 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
1351 struct nameidata
*n
)
1352 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1353 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
1354 struct nameidata
*n
)
1356 static int yaffs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
1359 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_create");
1360 return yaffs_mknod(dir
, dentry
, mode
| S_IFREG
, 0);
1363 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1364 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
1366 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1367 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
,
1368 struct nameidata
*n
)
1370 static struct dentry
*yaffs_lookup(struct inode
*dir
, struct dentry
*dentry
)
1373 struct yaffs_obj
*obj
;
1374 struct inode
*inode
= NULL
; /* NCB 2.5/2.6 needs NULL here */
1376 struct yaffs_dev
*dev
= yaffs_inode_to_obj(dir
)->my_dev
;
1378 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1379 yaffs_gross_lock(dev
);
1381 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_lookup for %d:%s",
1382 yaffs_inode_to_obj(dir
)->obj_id
, dentry
->d_name
.name
);
1384 obj
= yaffs_find_by_name(yaffs_inode_to_obj(dir
), dentry
->d_name
.name
);
1386 obj
= yaffs_get_equivalent_obj(obj
); /* in case it was a hardlink */
1388 /* Can't hold gross lock when calling yaffs_get_inode() */
1389 if (current
!= yaffs_dev_to_lc(dev
)->readdir_process
)
1390 yaffs_gross_unlock(dev
);
1393 yaffs_trace(YAFFS_TRACE_OS
,
1394 "yaffs_lookup found %d", obj
->obj_id
);
1396 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1398 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_lookup not found");
1402 /* added NCB for 2.5/6 compatability - forces add even if inode is
1403 * NULL which creates dentry hash */
1404 d_add(dentry
, inode
);
1412 static int yaffs_link(struct dentry
*old_dentry
, struct inode
*dir
,
1413 struct dentry
*dentry
)
1415 struct inode
*inode
= old_dentry
->d_inode
;
1416 struct yaffs_obj
*obj
= NULL
;
1417 struct yaffs_obj
*link
= NULL
;
1418 struct yaffs_dev
*dev
;
1420 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_link");
1422 obj
= yaffs_inode_to_obj(inode
);
1425 yaffs_gross_lock(dev
);
1427 if (!S_ISDIR(inode
->i_mode
)) /* Don't link directories */
1429 yaffs_link_obj(yaffs_inode_to_obj(dir
), dentry
->d_name
.name
,
1433 set_nlink(old_dentry
->d_inode
, yaffs_get_obj_link_count(obj
));
1434 d_instantiate(dentry
, old_dentry
->d_inode
);
1435 atomic_inc(&old_dentry
->d_inode
->i_count
);
1436 yaffs_trace(YAFFS_TRACE_OS
,
1437 "yaffs_link link count %d i_count %d",
1438 old_dentry
->d_inode
->i_nlink
,
1439 atomic_read(&old_dentry
->d_inode
->i_count
));
1442 yaffs_gross_unlock(dev
);
1445 update_dir_time(dir
);
1452 static int yaffs_symlink(struct inode
*dir
, struct dentry
*dentry
,
1453 const char *symname
)
1455 struct yaffs_obj
*obj
;
1456 struct yaffs_dev
*dev
;
1457 uid_t uid
= YPROC_uid(current
);
1459 (dir
->i_mode
& S_ISGID
) ? EXTRACT_gid(dir
->i_gid
) : YPROC_gid(current
);
1461 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_symlink");
1463 if (strnlen(dentry
->d_name
.name
, YAFFS_MAX_NAME_LENGTH
+ 1) >
1464 YAFFS_MAX_NAME_LENGTH
)
1465 return -ENAMETOOLONG
;
1467 if (strnlen(symname
, YAFFS_MAX_ALIAS_LENGTH
+ 1) >
1468 YAFFS_MAX_ALIAS_LENGTH
)
1469 return -ENAMETOOLONG
;
1471 dev
= yaffs_inode_to_obj(dir
)->my_dev
;
1472 yaffs_gross_lock(dev
);
1473 obj
= yaffs_create_symlink(yaffs_inode_to_obj(dir
), dentry
->d_name
.name
,
1474 S_IFLNK
| S_IRWXUGO
, uid
, gid
, symname
);
1475 yaffs_gross_unlock(dev
);
1478 struct inode
*inode
;
1480 inode
= yaffs_get_inode(dir
->i_sb
, obj
->yst_mode
, 0, obj
);
1481 d_instantiate(dentry
, inode
);
1482 update_dir_time(dir
);
1483 yaffs_trace(YAFFS_TRACE_OS
, "symlink created OK");
1486 yaffs_trace(YAFFS_TRACE_OS
, "symlink not created");
1493 * The VFS layer already does all the dentry stuff for rename.
1495 * NB: POSIX says you can rename an object over an old object of the same name
1497 static int yaffs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1498 struct inode
*new_dir
, struct dentry
*new_dentry
)
1500 struct yaffs_dev
*dev
;
1501 int ret_val
= YAFFS_FAIL
;
1502 struct yaffs_obj
*target
;
1504 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_rename");
1505 dev
= yaffs_inode_to_obj(old_dir
)->my_dev
;
1507 yaffs_gross_lock(dev
);
1509 /* Check if the target is an existing directory that is not empty. */
1510 target
= yaffs_find_by_name(yaffs_inode_to_obj(new_dir
),
1511 new_dentry
->d_name
.name
);
1513 if (target
&& target
->variant_type
== YAFFS_OBJECT_TYPE_DIRECTORY
&&
1514 !list_empty(&target
->variant
.dir_variant
.children
)) {
1516 yaffs_trace(YAFFS_TRACE_OS
, "target is non-empty dir");
1518 ret_val
= YAFFS_FAIL
;
1520 /* Now does unlinking internally using shadowing mechanism */
1521 yaffs_trace(YAFFS_TRACE_OS
, "calling yaffs_rename_obj");
1523 ret_val
= yaffs_rename_obj(yaffs_inode_to_obj(old_dir
),
1524 old_dentry
->d_name
.name
,
1525 yaffs_inode_to_obj(new_dir
),
1526 new_dentry
->d_name
.name
);
1528 yaffs_gross_unlock(dev
);
1530 if (ret_val
== YAFFS_OK
) {
1532 inode_dec_link_count(new_dentry
->d_inode
);
1534 update_dir_time(old_dir
);
1535 if (old_dir
!= new_dir
)
1536 update_dir_time(new_dir
);
1546 static int yaffs_unlink(struct inode
*dir
, struct dentry
*dentry
)
1550 struct yaffs_dev
*dev
;
1551 struct yaffs_obj
*obj
;
1553 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_unlink %d:%s",
1554 (int)(dir
->i_ino
), dentry
->d_name
.name
);
1555 obj
= yaffs_inode_to_obj(dir
);
1558 yaffs_gross_lock(dev
);
1560 ret_val
= yaffs_unlinker(obj
, dentry
->d_name
.name
);
1562 if (ret_val
== YAFFS_OK
) {
1563 inode_dec_link_count(dentry
->d_inode
);
1565 yaffs_gross_unlock(dev
);
1566 update_dir_time(dir
);
1569 yaffs_gross_unlock(dev
);
1575 static const struct inode_operations yaffs_dir_inode_operations
= {
1576 .create
= yaffs_create
,
1577 .lookup
= yaffs_lookup
,
1579 .unlink
= yaffs_unlink
,
1580 .symlink
= yaffs_symlink
,
1581 .mkdir
= yaffs_mkdir
,
1582 .rmdir
= yaffs_unlink
,
1583 .mknod
= yaffs_mknod
,
1584 .rename
= yaffs_rename
,
1585 .setattr
= yaffs_setattr
,
1586 .setxattr
= yaffs_setxattr
,
1587 .getxattr
= yaffs_getxattr
,
1588 .listxattr
= yaffs_listxattr
,
1589 .removexattr
= yaffs_removexattr
,
1592 /*-----------------------------------------------------------------*/
1593 /* Directory search context allows us to unlock access to yaffs during
1594 * filldir without causing problems with the directory being modified.
1595 * This is similar to the tried and tested mechanism used in yaffs direct.
1597 * A search context iterates along a doubly linked list of siblings in the
1598 * directory. If the iterating object is deleted then this would corrupt
1599 * the list iteration, likely causing a crash. The search context avoids
1600 * this by using the remove_obj_fn to move the search context to the
1601 * next object before the object is deleted.
1603 * Many readdirs (and thus seach conexts) may be alive simulateously so
1604 * each struct yaffs_dev has a list of these.
1606 * A seach context lives for the duration of a readdir.
1608 * All these functions must be called while yaffs is locked.
1611 struct yaffs_search_context
{
1612 struct yaffs_dev
*dev
;
1613 struct yaffs_obj
*dir_obj
;
1614 struct yaffs_obj
*next_return
;
1615 struct list_head others
;
1619 * yaffs_new_search() creates a new search context, initialises it and
1620 * adds it to the device's search context list.
1622 * Called at start of readdir.
1624 static struct yaffs_search_context
*yaffs_new_search(struct yaffs_obj
*dir
)
1626 struct yaffs_dev
*dev
= dir
->my_dev
;
1627 struct yaffs_search_context
*sc
=
1628 kmalloc(sizeof(struct yaffs_search_context
), GFP_NOFS
);
1632 if (list_empty(&sc
->dir_obj
->variant
.dir_variant
.children
))
1633 sc
->next_return
= NULL
;
1636 list_entry(dir
->variant
.dir_variant
.children
.next
,
1637 struct yaffs_obj
, siblings
);
1638 INIT_LIST_HEAD(&sc
->others
);
1639 list_add(&sc
->others
, &(yaffs_dev_to_lc(dev
)->search_contexts
));
1645 * yaffs_search_end() disposes of a search context and cleans up.
1647 static void yaffs_search_end(struct yaffs_search_context
*sc
)
1650 list_del(&sc
->others
);
1656 * yaffs_search_advance() moves a search context to the next object.
1657 * Called when the search iterates or when an object removal causes
1658 * the search context to be moved to the next object.
1660 static void yaffs_search_advance(struct yaffs_search_context
*sc
)
1665 if (sc
->next_return
== NULL
||
1666 list_empty(&sc
->dir_obj
->variant
.dir_variant
.children
))
1667 sc
->next_return
= NULL
;
1669 struct list_head
*next
= sc
->next_return
->siblings
.next
;
1671 if (next
== &sc
->dir_obj
->variant
.dir_variant
.children
)
1672 sc
->next_return
= NULL
; /* end of list */
1675 list_entry(next
, struct yaffs_obj
, siblings
);
1680 * yaffs_remove_obj_callback() is called when an object is unlinked.
1681 * We check open search contexts and advance any which are currently
1682 * on the object being iterated.
1684 static void yaffs_remove_obj_callback(struct yaffs_obj
*obj
)
1687 struct list_head
*i
;
1688 struct yaffs_search_context
*sc
;
1689 struct list_head
*search_contexts
=
1690 &(yaffs_dev_to_lc(obj
->my_dev
)->search_contexts
);
1692 /* Iterate through the directory search contexts.
1693 * If any are currently on the object being removed, then advance
1694 * the search context to the next object to prevent a hanging pointer.
1696 list_for_each(i
, search_contexts
) {
1697 sc
= list_entry(i
, struct yaffs_search_context
, others
);
1698 if (sc
->next_return
== obj
)
1699 yaffs_search_advance(sc
);
1705 /*-----------------------------------------------------------------*/
1707 #ifdef YAFFS_USE_DIR_ITERATE
1708 static int yaffs_iterate(struct file
*f
, struct dir_context
*dc
)
1710 struct yaffs_obj
*obj
;
1711 struct yaffs_dev
*dev
;
1712 struct yaffs_search_context
*sc
;
1713 unsigned long curoffs
;
1714 struct yaffs_obj
*l
;
1717 char name
[YAFFS_MAX_NAME_LENGTH
+ 1];
1719 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1722 yaffs_gross_lock(dev
);
1724 yaffs_dev_to_lc(dev
)->readdir_process
= current
;
1726 sc
= yaffs_new_search(obj
);
1732 if (!dir_emit_dots(f
, dc
))
1737 while (sc
->next_return
) {
1739 l
= sc
->next_return
;
1740 if (curoffs
>= dc
->pos
) {
1741 int this_inode
= yaffs_get_obj_inode(l
);
1742 int this_type
= yaffs_get_obj_type(l
);
1744 yaffs_get_obj_name(l
, name
, YAFFS_MAX_NAME_LENGTH
+ 1);
1745 yaffs_trace(YAFFS_TRACE_OS
,
1746 "yaffs_readdir: %s inode %d",
1747 name
, yaffs_get_obj_inode(l
));
1749 yaffs_gross_unlock(dev
);
1756 yaffs_gross_lock(dev
);
1760 yaffs_gross_lock(dev
);
1765 yaffs_search_advance(sc
);
1769 yaffs_search_end(sc
);
1770 yaffs_dev_to_lc(dev
)->readdir_process
= NULL
;
1771 yaffs_gross_unlock(dev
);
1778 static int yaffs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
)
1780 struct yaffs_obj
*obj
;
1781 struct yaffs_dev
*dev
;
1782 struct yaffs_search_context
*sc
;
1783 struct inode
*inode
= f
->f_dentry
->d_inode
;
1784 unsigned long offset
, curoffs
;
1785 struct yaffs_obj
*l
;
1788 char name
[YAFFS_MAX_NAME_LENGTH
+ 1];
1790 obj
= yaffs_dentry_to_obj(f
->f_dentry
);
1793 yaffs_gross_lock(dev
);
1795 yaffs_dev_to_lc(dev
)->readdir_process
= current
;
1799 sc
= yaffs_new_search(obj
);
1805 yaffs_trace(YAFFS_TRACE_OS
,
1806 "yaffs_readdir: starting at %d", (int)offset
);
1809 yaffs_trace(YAFFS_TRACE_OS
,
1810 "yaffs_readdir: entry . ino %d",
1812 yaffs_gross_unlock(dev
);
1813 if (filldir(dirent
, ".", 1, offset
, inode
->i_ino
, DT_DIR
) < 0) {
1814 yaffs_gross_lock(dev
);
1817 yaffs_gross_lock(dev
);
1822 yaffs_trace(YAFFS_TRACE_OS
,
1823 "yaffs_readdir: entry .. ino %d",
1824 (int)f
->f_dentry
->d_parent
->d_inode
->i_ino
);
1825 yaffs_gross_unlock(dev
);
1826 if (filldir(dirent
, "..", 2, offset
,
1827 f
->f_dentry
->d_parent
->d_inode
->i_ino
,
1829 yaffs_gross_lock(dev
);
1832 yaffs_gross_lock(dev
);
1839 /* If the directory has changed since the open or last call to
1840 readdir, rewind to after the 2 canned entries. */
1841 if (f
->f_version
!= inode
->i_version
) {
1844 f
->f_version
= inode
->i_version
;
1847 while (sc
->next_return
) {
1849 l
= sc
->next_return
;
1850 if (curoffs
>= offset
) {
1851 int this_inode
= yaffs_get_obj_inode(l
);
1852 int this_type
= yaffs_get_obj_type(l
);
1854 yaffs_get_obj_name(l
, name
, YAFFS_MAX_NAME_LENGTH
+ 1);
1855 yaffs_trace(YAFFS_TRACE_OS
,
1856 "yaffs_readdir: %s inode %d",
1857 name
, yaffs_get_obj_inode(l
));
1859 yaffs_gross_unlock(dev
);
1864 offset
, this_inode
, this_type
) < 0) {
1865 yaffs_gross_lock(dev
);
1869 yaffs_gross_lock(dev
);
1874 yaffs_search_advance(sc
);
1878 yaffs_search_end(sc
);
1879 yaffs_dev_to_lc(dev
)->readdir_process
= NULL
;
1880 yaffs_gross_unlock(dev
);
1887 static const struct file_operations yaffs_dir_operations
= {
1888 .read
= generic_read_dir
,
1889 #ifdef YAFFS_USE_DIR_ITERATE
1890 .iterate
= yaffs_iterate
,
1892 .readdir
= yaffs_readdir
,
1894 .fsync
= yaffs_sync_object
,
1895 .llseek
= generic_file_llseek
,
1898 static void yaffs_fill_inode_from_obj(struct inode
*inode
,
1899 struct yaffs_obj
*obj
)
1903 /* Check mode against the variant type and attempt to repair if broken. */
1904 u32 mode
= obj
->yst_mode
;
1905 switch (obj
->variant_type
) {
1906 case YAFFS_OBJECT_TYPE_FILE
:
1907 if (!S_ISREG(mode
)) {
1908 obj
->yst_mode
&= ~S_IFMT
;
1909 obj
->yst_mode
|= S_IFREG
;
1913 case YAFFS_OBJECT_TYPE_SYMLINK
:
1914 if (!S_ISLNK(mode
)) {
1915 obj
->yst_mode
&= ~S_IFMT
;
1916 obj
->yst_mode
|= S_IFLNK
;
1920 case YAFFS_OBJECT_TYPE_DIRECTORY
:
1921 if (!S_ISDIR(mode
)) {
1922 obj
->yst_mode
&= ~S_IFMT
;
1923 obj
->yst_mode
|= S_IFDIR
;
1927 case YAFFS_OBJECT_TYPE_UNKNOWN
:
1928 case YAFFS_OBJECT_TYPE_HARDLINK
:
1929 case YAFFS_OBJECT_TYPE_SPECIAL
:
1935 inode
->i_flags
|= S_NOATIME
;
1937 inode
->i_ino
= obj
->obj_id
;
1938 inode
->i_mode
= obj
->yst_mode
;
1939 inode
->i_uid
= MAKE_uid(obj
->yst_uid
);
1940 inode
->i_gid
= MAKE_gid(obj
->yst_gid
);
1941 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
1942 inode
->i_blksize
= inode
->i_sb
->s_blocksize
;
1944 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1946 inode
->i_rdev
= old_decode_dev(obj
->yst_rdev
);
1947 inode
->i_atime
.tv_sec
= (time_t) (obj
->yst_atime
);
1948 inode
->i_atime
.tv_nsec
= 0;
1949 inode
->i_mtime
.tv_sec
= (time_t) obj
->yst_mtime
;
1950 inode
->i_mtime
.tv_nsec
= 0;
1951 inode
->i_ctime
.tv_sec
= (time_t) obj
->yst_ctime
;
1952 inode
->i_ctime
.tv_nsec
= 0;
1954 inode
->i_rdev
= obj
->yst_rdev
;
1955 inode
->i_atime
= obj
->yst_atime
;
1956 inode
->i_mtime
= obj
->yst_mtime
;
1957 inode
->i_ctime
= obj
->yst_ctime
;
1959 inode
->i_size
= yaffs_get_obj_length(obj
);
1960 inode
->i_blocks
= (inode
->i_size
+ 511) >> 9;
1962 set_nlink(inode
, yaffs_get_obj_link_count(obj
));
1964 yaffs_trace(YAFFS_TRACE_OS
,
1965 "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
1966 inode
->i_mode
, obj
->yst_uid
, obj
->yst_gid
,
1967 inode
->i_size
, atomic_read(&inode
->i_count
));
1969 switch (obj
->yst_mode
& S_IFMT
) {
1970 default: /* fifo, device or socket */
1971 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1972 init_special_inode(inode
, obj
->yst_mode
,
1973 old_decode_dev(obj
->yst_rdev
));
1975 init_special_inode(inode
, obj
->yst_mode
,
1976 (dev_t
) (obj
->yst_rdev
));
1979 case S_IFREG
: /* file */
1980 inode
->i_op
= &yaffs_file_inode_operations
;
1981 inode
->i_fop
= &yaffs_file_operations
;
1982 inode
->i_mapping
->a_ops
=
1983 &yaffs_file_address_operations
;
1985 case S_IFDIR
: /* directory */
1986 inode
->i_op
= &yaffs_dir_inode_operations
;
1987 inode
->i_fop
= &yaffs_dir_operations
;
1989 case S_IFLNK
: /* symlink */
1990 inode
->i_op
= &yaffs_symlink_inode_operations
;
1994 yaffs_inode_to_obj_lv(inode
) = obj
;
1996 obj
->my_inode
= inode
;
1999 yaffs_trace(YAFFS_TRACE_OS
,
2000 "yaffs_fill_inode invalid parameters");
2008 * yaffs background thread functions .
2009 * yaffs_bg_thread_fn() the thread function
2010 * yaffs_bg_start() launches the background thread.
2011 * yaffs_bg_stop() cleans up the background thread.
2014 * The thread should only run after the yaffs is initialised
2015 * The thread should be stopped before yaffs is unmounted.
2016 * The thread should not do any writing while the fs is in read only.
2019 static unsigned yaffs_bg_gc_urgency(struct yaffs_dev
*dev
)
2021 unsigned erased_chunks
=
2022 dev
->n_erased_blocks
* dev
->param
.chunks_per_block
;
2023 struct yaffs_linux_context
*context
= yaffs_dev_to_lc(dev
);
2024 unsigned scattered
= 0; /* Free chunks not in an erased block */
2026 if (erased_chunks
< dev
->n_free_chunks
)
2027 scattered
= (dev
->n_free_chunks
- erased_chunks
);
2029 if (!context
->bg_running
)
2031 else if (scattered
< (dev
->param
.chunks_per_block
* 2))
2033 else if (erased_chunks
> dev
->n_free_chunks
/ 2)
2035 else if (erased_chunks
> dev
->n_free_chunks
/ 4)
2041 #ifdef YAFFS_COMPILE_BACKGROUND
2043 void yaffs_background_waker(unsigned long data
)
2045 wake_up_process((struct task_struct
*)data
);
2048 static int yaffs_bg_thread_fn(void *data
)
2050 struct yaffs_dev
*dev
= (struct yaffs_dev
*)data
;
2051 struct yaffs_linux_context
*context
= yaffs_dev_to_lc(dev
);
2052 unsigned long now
= jiffies
;
2053 unsigned long next_dir_update
= now
;
2054 unsigned long next_gc
= now
;
2055 unsigned long expires
;
2056 unsigned int urgency
;
2059 struct timer_list timer
;
2061 yaffs_trace(YAFFS_TRACE_BACKGROUND
,
2062 "yaffs_background starting for dev %p", (void *)dev
);
2064 #ifdef YAFFS_COMPILE_FREEZER
2067 while (context
->bg_running
) {
2068 yaffs_trace(YAFFS_TRACE_BACKGROUND
, "yaffs_background");
2070 if (kthread_should_stop())
2073 #ifdef YAFFS_COMPILE_FREEZER
2074 if (try_to_freeze())
2077 yaffs_gross_lock(dev
);
2081 if (time_after(now
, next_dir_update
) && yaffs_bg_enable
) {
2082 yaffs_update_dirty_dirs(dev
);
2083 next_dir_update
= now
+ HZ
;
2086 if (time_after(now
, next_gc
) && yaffs_bg_enable
) {
2087 if (!dev
->is_checkpointed
) {
2088 urgency
= yaffs_bg_gc_urgency(dev
);
2089 gc_result
= yaffs_bg_gc(dev
, urgency
);
2091 next_gc
= now
+ HZ
/ 20 + 1;
2092 else if (urgency
> 0)
2093 next_gc
= now
+ HZ
/ 10 + 1;
2095 next_gc
= now
+ HZ
* 2;
2098 * gc not running so set to next_dir_update
2099 * to cut down on wake ups
2101 next_gc
= next_dir_update
;
2104 yaffs_gross_unlock(dev
);
2106 expires
= next_dir_update
;
2107 if (time_before(next_gc
, expires
))
2109 if (time_before(expires
, now
))
2112 Y_INIT_TIMER(&timer
);
2113 timer
.expires
= expires
+ 1;
2114 timer
.data
= (unsigned long)current
;
2115 timer
.function
= yaffs_background_waker
;
2117 set_current_state(TASK_INTERRUPTIBLE
);
2120 del_timer_sync(&timer
);
2129 static int yaffs_bg_start(struct yaffs_dev
*dev
)
2132 struct yaffs_linux_context
*context
= yaffs_dev_to_lc(dev
);
2137 context
->bg_running
= 1;
2139 context
->bg_thread
= kthread_run(yaffs_bg_thread_fn
,
2140 (void *)dev
, "yaffs-bg-%d",
2143 if (IS_ERR(context
->bg_thread
)) {
2144 retval
= PTR_ERR(context
->bg_thread
);
2145 context
->bg_thread
= NULL
;
2146 context
->bg_running
= 0;
2151 static void yaffs_bg_stop(struct yaffs_dev
*dev
)
2153 struct yaffs_linux_context
*ctxt
= yaffs_dev_to_lc(dev
);
2155 ctxt
->bg_running
= 0;
2157 if (ctxt
->bg_thread
) {
2158 kthread_stop(ctxt
->bg_thread
);
2159 ctxt
->bg_thread
= NULL
;
2163 static int yaffs_bg_thread_fn(void *data
)
2168 static int yaffs_bg_start(struct yaffs_dev
*dev
)
2173 static void yaffs_bg_stop(struct yaffs_dev
*dev
)
2179 static void yaffs_flush_inodes(struct super_block
*sb
)
2182 struct yaffs_obj
*obj
;
2184 list_for_each_entry(iptr
, &sb
->s_inodes
, i_sb_list
) {
2185 obj
= yaffs_inode_to_obj(iptr
);
2187 yaffs_trace(YAFFS_TRACE_OS
,
2190 yaffs_flush_file(obj
, 1, 0);
2195 static void yaffs_flush_super(struct super_block
*sb
, int do_checkpoint
)
2197 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2201 yaffs_flush_inodes(sb
);
2202 yaffs_update_dirty_dirs(dev
);
2203 yaffs_flush_whole_cache(dev
);
2205 yaffs_checkpoint_save(dev
);
2208 static LIST_HEAD(yaffs_context_list
);
2209 struct mutex yaffs_context_lock
;
2211 static void yaffs_put_super(struct super_block
*sb
)
2213 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2214 struct mtd_info
*mtd
= yaffs_dev_to_mtd(dev
);
2216 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_ALWAYS
,
2219 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_BACKGROUND
,
2220 "Shutting down yaffs background thread");
2222 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_BACKGROUND
,
2223 "yaffs background thread shut down");
2225 yaffs_gross_lock(dev
);
2227 yaffs_flush_super(sb
, 1);
2229 yaffs_deinitialise(dev
);
2231 yaffs_gross_unlock(dev
);
2233 mutex_lock(&yaffs_context_lock
);
2234 list_del_init(&(yaffs_dev_to_lc(dev
)->context_list
));
2235 mutex_unlock(&yaffs_context_lock
);
2237 if (yaffs_dev_to_lc(dev
)->spare_buffer
) {
2238 kfree(yaffs_dev_to_lc(dev
)->spare_buffer
);
2239 yaffs_dev_to_lc(dev
)->spare_buffer
= NULL
;
2244 yaffs_put_mtd_device(mtd
);
2246 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_ALWAYS
,
2247 "yaffs_put_super done");
2251 static unsigned yaffs_gc_control_callback(struct yaffs_dev
*dev
)
2253 return yaffs_gc_control
;
2257 #ifdef YAFFS_COMPILE_EXPORTFS
2259 static struct inode
*yaffs2_nfs_get_inode(struct super_block
*sb
, uint64_t ino
,
2260 uint32_t generation
)
2262 return Y_IGET(sb
, ino
);
2265 static struct dentry
*yaffs2_fh_to_dentry(struct super_block
*sb
,
2266 struct fid
*fid
, int fh_len
,
2269 return generic_fh_to_dentry(sb
, fid
, fh_len
, fh_type
,
2270 yaffs2_nfs_get_inode
);
2273 static struct dentry
*yaffs2_fh_to_parent(struct super_block
*sb
,
2274 struct fid
*fid
, int fh_len
,
2277 return generic_fh_to_parent(sb
, fid
, fh_len
, fh_type
,
2278 yaffs2_nfs_get_inode
);
2281 struct dentry
*yaffs2_get_parent(struct dentry
*dentry
)
2284 struct super_block
*sb
= dentry
->d_inode
->i_sb
;
2285 struct dentry
*parent
= ERR_PTR(-ENOENT
);
2286 struct inode
*inode
;
2287 unsigned long parent_ino
;
2288 struct yaffs_obj
*d_obj
;
2289 struct yaffs_obj
*parent_obj
;
2291 d_obj
= yaffs_inode_to_obj(dentry
->d_inode
);
2294 parent_obj
= d_obj
->parent
;
2296 parent_ino
= yaffs_get_obj_inode(parent_obj
);
2297 inode
= Y_IGET(sb
, parent_ino
);
2299 if (IS_ERR(inode
)) {
2300 parent
= ERR_CAST(inode
);
2302 parent
= d_obtain_alias(inode
);
2303 if (!IS_ERR(parent
)) {
2304 parent
= ERR_PTR(-ENOMEM
);
2314 /* Just declare a zero structure as a NULL value implies
2315 * using the default functions of exportfs.
2318 static struct export_operations yaffs_export_ops
= {
2319 .fh_to_dentry
= yaffs2_fh_to_dentry
,
2320 .fh_to_parent
= yaffs2_fh_to_parent
,
2321 .get_parent
= yaffs2_get_parent
,
2326 static void yaffs_unstitch_obj(struct inode
*inode
, struct yaffs_obj
*obj
)
2328 /* Clear the association between the inode and
2329 * the struct yaffs_obj.
2331 obj
->my_inode
= NULL
;
2332 yaffs_inode_to_obj_lv(inode
) = NULL
;
2334 /* If the object freeing was deferred, then the real
2336 * This should fix the inode inconsistency problem.
2338 yaffs_handle_defered_free(obj
);
2341 #ifdef YAFFS_HAS_EVICT_INODE
2342 /* yaffs_evict_inode combines into one operation what was previously done in
2343 * yaffs_clear_inode() and yaffs_delete_inode()
2346 static void yaffs_evict_inode(struct inode
*inode
)
2348 struct yaffs_obj
*obj
;
2349 struct yaffs_dev
*dev
;
2352 obj
= yaffs_inode_to_obj(inode
);
2354 yaffs_trace(YAFFS_TRACE_OS
,
2355 "yaffs_evict_inode: ino %d, count %d %s",
2356 (int)inode
->i_ino
, atomic_read(&inode
->i_count
),
2357 obj
? "object exists" : "null object");
2359 if (!inode
->i_nlink
&& !is_bad_inode(inode
))
2361 truncate_inode_pages(&inode
->i_data
, 0);
2362 Y_CLEAR_INODE(inode
);
2364 if (deleteme
&& obj
) {
2366 yaffs_gross_lock(dev
);
2368 yaffs_gross_unlock(dev
);
2372 yaffs_gross_lock(dev
);
2373 yaffs_unstitch_obj(inode
, obj
);
2374 yaffs_gross_unlock(dev
);
2379 /* clear is called to tell the fs to release any per-inode data it holds.
2380 * The object might still exist on disk and is just being thrown out of the cache
2381 * or else the object has actually been deleted and we're being called via
2383 * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
2386 static void yaffs_clear_inode(struct inode
*inode
)
2388 struct yaffs_obj
*obj
;
2389 struct yaffs_dev
*dev
;
2391 obj
= yaffs_inode_to_obj(inode
);
2393 yaffs_trace(YAFFS_TRACE_OS
,
2394 "yaffs_clear_inode: ino %d, count %d %s",
2395 (int)inode
->i_ino
, atomic_read(&inode
->i_count
),
2396 obj
? "object exists" : "null object");
2400 yaffs_gross_lock(dev
);
2401 yaffs_unstitch_obj(inode
, obj
);
2402 yaffs_gross_unlock(dev
);
2407 /* delete is called when the link count is zero and the inode
2408 * is put (ie. nobody wants to know about it anymore, time to
2410 * NB Must call clear_inode()
2412 static void yaffs_delete_inode(struct inode
*inode
)
2414 struct yaffs_obj
*obj
= yaffs_inode_to_obj(inode
);
2415 struct yaffs_dev
*dev
;
2417 yaffs_trace(YAFFS_TRACE_OS
,
2418 "yaffs_delete_inode: ino %d, count %d %s",
2419 (int)inode
->i_ino
, atomic_read(&inode
->i_count
),
2420 obj
? "object exists" : "null object");
2424 yaffs_gross_lock(dev
);
2426 yaffs_gross_unlock(dev
);
2428 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
2429 truncate_inode_pages(&inode
->i_data
, 0);
2438 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2439 static int yaffs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
2441 struct yaffs_dev
*dev
= yaffs_dentry_to_obj(dentry
)->my_dev
;
2442 struct super_block
*sb
= dentry
->d_sb
;
2443 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2444 static int yaffs_statfs(struct super_block
*sb
, struct kstatfs
*buf
)
2446 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2448 static int yaffs_statfs(struct super_block
*sb
, struct statfs
*buf
)
2450 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2453 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_statfs");
2455 yaffs_gross_lock(dev
);
2457 buf
->f_type
= YAFFS_MAGIC
;
2458 buf
->f_bsize
= sb
->s_blocksize
;
2459 buf
->f_namelen
= 255;
2461 if (dev
->data_bytes_per_chunk
& (dev
->data_bytes_per_chunk
- 1)) {
2462 /* Do this if chunk size is not a power of 2 */
2464 uint64_t bytes_in_dev
;
2465 uint64_t bytes_free
;
2469 ((dev
->param
.end_block
- dev
->param
.start_block
+
2470 1))) * ((uint64_t) (dev
->param
.chunks_per_block
*
2471 dev
->data_bytes_per_chunk
));
2473 do_div(bytes_in_dev
, sb
->s_blocksize
); /* bytes_in_dev becomes the number of blocks */
2474 buf
->f_blocks
= bytes_in_dev
;
2476 bytes_free
= ((uint64_t) (yaffs_get_n_free_chunks(dev
))) *
2477 ((uint64_t) (dev
->data_bytes_per_chunk
));
2479 do_div(bytes_free
, sb
->s_blocksize
);
2481 buf
->f_bfree
= bytes_free
;
2483 } else if (sb
->s_blocksize
> dev
->data_bytes_per_chunk
) {
2486 (dev
->param
.end_block
- dev
->param
.start_block
+ 1) *
2487 dev
->param
.chunks_per_block
/
2488 (sb
->s_blocksize
/ dev
->data_bytes_per_chunk
);
2490 yaffs_get_n_free_chunks(dev
) /
2491 (sb
->s_blocksize
/ dev
->data_bytes_per_chunk
);
2494 (dev
->param
.end_block
- dev
->param
.start_block
+ 1) *
2495 dev
->param
.chunks_per_block
*
2496 (dev
->data_bytes_per_chunk
/ sb
->s_blocksize
);
2499 yaffs_get_n_free_chunks(dev
) *
2500 (dev
->data_bytes_per_chunk
/ sb
->s_blocksize
);
2505 buf
->f_bavail
= buf
->f_bfree
;
2507 yaffs_gross_unlock(dev
);
2513 static int yaffs_do_sync_fs(struct super_block
*sb
, int request_checkpoint
)
2516 struct yaffs_dev
*dev
= yaffs_super_to_dev(sb
);
2517 unsigned int oneshot_checkpoint
= (yaffs_auto_checkpoint
& 4);
2518 unsigned gc_urgent
= yaffs_bg_gc_urgency(dev
);
2520 int dirty
= yaffs_check_super_dirty(dev
);
2522 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
| YAFFS_TRACE_BACKGROUND
,
2523 "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
2525 dirty
? "dirty" : "clean",
2526 request_checkpoint
? "checkpoint requested" : "no checkpoint",
2527 oneshot_checkpoint
? " one-shot" : "");
2529 yaffs_gross_lock(dev
);
2530 do_checkpoint
= ((request_checkpoint
&& !gc_urgent
) ||
2531 oneshot_checkpoint
) && !dev
->is_checkpointed
;
2533 if (dirty
|| do_checkpoint
) {
2534 yaffs_flush_super(sb
, !dev
->is_checkpointed
&& do_checkpoint
);
2535 yaffs_clear_super_dirty(dev
);
2536 if (oneshot_checkpoint
)
2537 yaffs_auto_checkpoint
&= ~4;
2539 yaffs_gross_unlock(dev
);
2545 #ifdef YAFFS_HAS_WRITE_SUPER
2546 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2547 static void yaffs_write_super(struct super_block
*sb
)
2549 static int yaffs_write_super(struct super_block
*sb
)
2552 unsigned request_checkpoint
= (yaffs_auto_checkpoint
>= 2);
2554 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
| YAFFS_TRACE_BACKGROUND
,
2555 "yaffs_write_super %s",
2556 request_checkpoint
? " checkpt" : "");
2558 yaffs_do_sync_fs(sb
, request_checkpoint
);
2560 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
2566 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2567 static int yaffs_sync_fs(struct super_block
*sb
, int wait
)
2569 static int yaffs_sync_fs(struct super_block
*sb
)
2572 unsigned request_checkpoint
= (yaffs_auto_checkpoint
>= 1);
2574 yaffs_trace(YAFFS_TRACE_OS
| YAFFS_TRACE_SYNC
,
2575 "yaffs_sync_fs%s", request_checkpoint
? " checkpt" : "");
2577 yaffs_do_sync_fs(sb
, request_checkpoint
);
2584 static const struct super_operations yaffs_super_ops
= {
2585 .statfs
= yaffs_statfs
,
2587 #ifndef YAFFS_USE_OWN_IGET
2588 .read_inode
= yaffs_read_inode
,
2590 #ifdef YAFFS_HAS_PUT_INODE
2591 .put_inode
= yaffs_put_inode
,
2593 .put_super
= yaffs_put_super
,
2594 #ifdef YAFFS_HAS_EVICT_INODE
2595 .evict_inode
= yaffs_evict_inode
,
2597 .delete_inode
= yaffs_delete_inode
,
2598 .clear_inode
= yaffs_clear_inode
,
2600 .sync_fs
= yaffs_sync_fs
,
2601 #ifdef YAFFS_HAS_WRITE_SUPER
2602 .write_super
= yaffs_write_super
,
2606 struct yaffs_options
{
2608 int skip_checkpoint_read
;
2609 int skip_checkpoint_write
;
2612 int tags_ecc_overridden
;
2613 int lazy_loading_enabled
;
2614 int lazy_loading_overridden
;
2615 int empty_lost_and_found
;
2616 int empty_lost_and_found_overridden
;
2617 int disable_summary
;
2620 #define MAX_OPT_LEN 30
2621 static int yaffs_parse_options(struct yaffs_options
*options
,
2622 const char *options_str
)
2624 char cur_opt
[MAX_OPT_LEN
+ 1];
2628 /* Parse through the options which is a comma seperated list */
2630 while (options_str
&& *options_str
&& !error
) {
2631 memset(cur_opt
, 0, MAX_OPT_LEN
+ 1);
2634 while (*options_str
== ',')
2637 while (*options_str
&& *options_str
!= ',') {
2638 if (p
< MAX_OPT_LEN
) {
2639 cur_opt
[p
] = *options_str
;
2645 if (!strcmp(cur_opt
, "inband-tags")) {
2646 options
->inband_tags
= 1;
2647 } else if (!strcmp(cur_opt
, "tags-ecc-off")) {
2648 options
->tags_ecc_on
= 0;
2649 options
->tags_ecc_overridden
= 1;
2650 } else if (!strcmp(cur_opt
, "tags-ecc-on")) {
2651 options
->tags_ecc_on
= 1;
2652 options
->tags_ecc_overridden
= 1;
2653 } else if (!strcmp(cur_opt
, "lazy-loading-off")) {
2654 options
->lazy_loading_enabled
= 0;
2655 options
->lazy_loading_overridden
= 1;
2656 } else if (!strcmp(cur_opt
, "lazy-loading-on")) {
2657 options
->lazy_loading_enabled
= 1;
2658 options
->lazy_loading_overridden
= 1;
2659 } else if (!strcmp(cur_opt
, "disable-summary")) {
2660 options
->disable_summary
= 1;
2661 } else if (!strcmp(cur_opt
, "empty-lost-and-found-off")) {
2662 options
->empty_lost_and_found
= 0;
2663 options
->empty_lost_and_found_overridden
= 1;
2664 } else if (!strcmp(cur_opt
, "empty-lost-and-found-on")) {
2665 options
->empty_lost_and_found
= 1;
2666 options
->empty_lost_and_found_overridden
= 1;
2667 } else if (!strcmp(cur_opt
, "no-cache")) {
2668 options
->no_cache
= 1;
2669 } else if (!strcmp(cur_opt
, "no-checkpoint-read")) {
2670 options
->skip_checkpoint_read
= 1;
2671 } else if (!strcmp(cur_opt
, "no-checkpoint-write")) {
2672 options
->skip_checkpoint_write
= 1;
2673 } else if (!strcmp(cur_opt
, "no-checkpoint")) {
2674 options
->skip_checkpoint_read
= 1;
2675 options
->skip_checkpoint_write
= 1;
2677 printk(KERN_INFO
"yaffs: Bad mount option \"%s\"\n",
2687 static struct dentry
*yaffs_make_root(struct inode
*inode
)
2689 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
2690 struct dentry
*root
= d_alloc_root(inode
);
2697 return d_make_root(inode
);
2704 static struct super_block
*yaffs_internal_read_super(int yaffs_version
,
2705 struct super_block
*sb
,
2706 void *data
, int silent
)
2709 struct inode
*inode
= NULL
;
2710 struct dentry
*root
;
2711 struct yaffs_dev
*dev
= 0;
2712 char devname_buf
[BDEVNAME_SIZE
+ 1];
2713 struct mtd_info
*mtd
;
2715 char *data_str
= (char *)data
;
2716 struct yaffs_linux_context
*context
= NULL
;
2717 struct yaffs_param
*param
;
2720 int inband_tags
= 0;
2722 struct yaffs_options options
;
2726 struct yaffs_linux_context
*context_iterator
;
2727 struct list_head
*l
;
2730 printk(KERN_INFO
"yaffs: sb is NULL\n");
2734 sb
->s_magic
= YAFFS_MAGIC
;
2735 sb
->s_op
= &yaffs_super_ops
;
2736 sb
->s_flags
|= MS_NOATIME
;
2738 read_only
= ((sb
->s_flags
& MS_RDONLY
) != 0);
2740 #ifdef YAFFS_COMPILE_EXPORTFS
2741 sb
->s_export_op
= &yaffs_export_ops
;
2745 printk(KERN_INFO
"yaffs: sb->s_dev is NULL\n");
2746 else if (!yaffs_devname(sb
, devname_buf
))
2747 printk(KERN_INFO
"yaffs: devname is NULL\n");
2749 printk(KERN_INFO
"yaffs: dev is %d name is \"%s\" %s\n",
2751 yaffs_devname(sb
, devname_buf
), read_only
? "ro" : "rw");
2756 printk(KERN_INFO
"yaffs: passed flags \"%s\"\n", data_str
);
2758 memset(&options
, 0, sizeof(options
));
2760 if (yaffs_parse_options(&options
, data_str
)) {
2761 /* Option parsing failed */
2765 sb
->s_blocksize
= PAGE_CACHE_SIZE
;
2766 sb
->s_blocksize_bits
= PAGE_CACHE_SHIFT
;
2768 yaffs_trace(YAFFS_TRACE_OS
,
2769 "yaffs_read_super: Using yaffs%d", yaffs_version
);
2770 yaffs_trace(YAFFS_TRACE_OS
,
2771 "yaffs_read_super: block size %d", (int)(sb
->s_blocksize
));
2773 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2774 "yaffs: Attempting MTD mount of %u.%u,\"%s\"",
2775 MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
),
2776 yaffs_devname(sb
, devname_buf
));
2778 /* Get the device */
2779 mtd
= get_mtd_device(NULL
, MINOR(sb
->s_dev
));
2781 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2782 "yaffs: MTD device %u either not valid or unavailable",
2787 if (yaffs_auto_select
&& yaffs_version
== 1 && WRITE_SIZE(mtd
) >= 2048) {
2788 yaffs_trace(YAFFS_TRACE_ALWAYS
, "auto selecting yaffs2");
2792 /* Added NCB 26/5/2006 for completeness */
2793 if (yaffs_version
== 2 && !options
.inband_tags
2794 && WRITE_SIZE(mtd
) == 512) {
2795 yaffs_trace(YAFFS_TRACE_ALWAYS
, "auto selecting yaffs1");
2799 if (mtd
->oobavail
< sizeof(struct yaffs_packed_tags2
) ||
2800 options
.inband_tags
)
2803 if(yaffs_verify_mtd(mtd
, yaffs_version
, inband_tags
) < 0)
2806 /* OK, so if we got here, we have an MTD that's NAND and looks
2807 * like it has the right capabilities
2808 * Set the struct yaffs_dev up for mtd
2811 if (!read_only
&& !(mtd
->flags
& MTD_WRITEABLE
)) {
2814 "yaffs: mtd is read only, setting superblock read only\n"
2816 sb
->s_flags
|= MS_RDONLY
;
2819 dev
= kmalloc(sizeof(struct yaffs_dev
), GFP_KERNEL
);
2820 context
= kmalloc(sizeof(struct yaffs_linux_context
), GFP_KERNEL
);
2822 if (!dev
|| !context
) {
2828 /* Deep shit could not allocate device structure */
2829 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2830 "yaffs_read_super: Failed trying to allocate struct yaffs_dev."
2834 memset(dev
, 0, sizeof(struct yaffs_dev
));
2835 param
= &(dev
->param
);
2837 memset(context
, 0, sizeof(struct yaffs_linux_context
));
2838 dev
->os_context
= context
;
2839 INIT_LIST_HEAD(&(context
->context_list
));
2841 context
->super
= sb
;
2843 dev
->read_only
= read_only
;
2845 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2846 sb
->s_fs_info
= dev
;
2848 sb
->u
.generic_sbp
= dev
;
2852 dev
->driver_context
= mtd
;
2853 param
->name
= mtd
->name
;
2855 /* Set up the memory size parameters.... */
2858 param
->n_reserved_blocks
= 5;
2859 param
->n_caches
= (options
.no_cache
) ? 0 : 10;
2860 param
->inband_tags
= inband_tags
;
2862 param
->enable_xattr
= 1;
2863 if (options
.lazy_loading_overridden
)
2864 param
->disable_lazy_load
= !options
.lazy_loading_enabled
;
2866 param
->defered_dir_update
= 1;
2868 if (options
.tags_ecc_overridden
)
2869 param
->no_tags_ecc
= !options
.tags_ecc_on
;
2871 param
->empty_lost_n_found
= 1;
2872 param
->refresh_period
= 500;
2873 param
->disable_summary
= options
.disable_summary
;
2876 #ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING
2877 param
->disable_bad_block_marking
= 1;
2879 if (options
.empty_lost_and_found_overridden
)
2880 param
->empty_lost_n_found
= options
.empty_lost_and_found
;
2882 /* ... and the functions. */
2883 if (yaffs_version
== 2) {
2884 param
->is_yaffs2
= 1;
2885 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2886 param
->total_bytes_per_chunk
= mtd
->writesize
;
2887 param
->chunks_per_block
= mtd
->erasesize
/ mtd
->writesize
;
2889 param
->total_bytes_per_chunk
= mtd
->oobblock
;
2890 param
->chunks_per_block
= mtd
->erasesize
/ mtd
->oobblock
;
2892 n_blocks
= YCALCBLOCKS(mtd
->size
, mtd
->erasesize
);
2894 param
->start_block
= 0;
2895 param
->end_block
= n_blocks
- 1;
2897 param
->is_yaffs2
= 0;
2898 n_blocks
= YCALCBLOCKS(mtd
->size
,
2899 YAFFS_CHUNKS_PER_BLOCK
* YAFFS_BYTES_PER_CHUNK
);
2901 param
->chunks_per_block
= YAFFS_CHUNKS_PER_BLOCK
;
2902 param
->total_bytes_per_chunk
= YAFFS_BYTES_PER_CHUNK
;
2905 param
->start_block
= 0;
2906 param
->end_block
= n_blocks
- 1;
2908 yaffs_mtd_drv_install(dev
);
2910 param
->sb_dirty_fn
= yaffs_set_super_dirty
;
2911 param
->gc_control_fn
= yaffs_gc_control_callback
;
2913 yaffs_dev_to_lc(dev
)->super
= sb
;
2915 param
->use_nand_ecc
= 1;
2917 param
->skip_checkpt_rd
= options
.skip_checkpoint_read
;
2918 param
->skip_checkpt_wr
= options
.skip_checkpoint_write
;
2920 mutex_lock(&yaffs_context_lock
);
2921 /* Get a mount id */
2923 for (mount_id
= 0; !found
; mount_id
++) {
2925 list_for_each(l
, &yaffs_context_list
) {
2927 list_entry(l
, struct yaffs_linux_context
,
2929 if (context_iterator
->mount_id
== mount_id
)
2933 context
->mount_id
= mount_id
;
2935 list_add_tail(&(yaffs_dev_to_lc(dev
)->context_list
),
2936 &yaffs_context_list
);
2937 mutex_unlock(&yaffs_context_lock
);
2939 /* Directory search handling... */
2940 INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev
)->search_contexts
));
2941 param
->remove_obj_fn
= yaffs_remove_obj_callback
;
2943 mutex_init(&(yaffs_dev_to_lc(dev
)->gross_lock
));
2945 yaffs_gross_lock(dev
);
2947 err
= yaffs_guts_initialise(dev
);
2949 yaffs_trace(YAFFS_TRACE_OS
,
2950 "yaffs_read_super: guts initialised %s",
2951 (err
== YAFFS_OK
) ? "OK" : "FAILED");
2953 if (err
== YAFFS_OK
)
2954 yaffs_bg_start(dev
);
2956 if (!context
->bg_thread
)
2957 param
->defered_dir_update
= 0;
2959 sb
->s_maxbytes
= yaffs_max_file_size(dev
);
2961 /* Release lock before yaffs_get_inode() */
2962 yaffs_gross_unlock(dev
);
2964 /* Create root inode */
2965 if (err
== YAFFS_OK
)
2966 inode
= yaffs_get_inode(sb
, S_IFDIR
| 0755, 0, yaffs_root(dev
));
2971 inode
->i_op
= &yaffs_dir_inode_operations
;
2972 inode
->i_fop
= &yaffs_dir_operations
;
2974 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_read_super: got root inode");
2976 root
= yaffs_make_root(inode
);
2982 if(!dev
->is_checkpointed
)
2983 yaffs_set_super_dirty(dev
);
2985 yaffs_trace(YAFFS_TRACE_ALWAYS
,
2986 "yaffs_read_super: is_checkpointed %d",
2987 dev
->is_checkpointed
);
2989 yaffs_trace(YAFFS_TRACE_OS
, "yaffs_read_super: done");
2993 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2994 static int yaffs_internal_read_super_mtd(struct super_block
*sb
, void *data
,
2997 return yaffs_internal_read_super(1, sb
, data
, silent
) ? 0 : -EINVAL
;
3000 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
3001 static struct dentry
*yaffs_mount(struct file_system_type
*fs_type
, int flags
,
3002 const char *dev_name
, void *data
)
3004 return mount_bdev(fs_type
, flags
, dev_name
, data
, yaffs_internal_read_super_mtd
);
3006 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3007 static int yaffs_read_super(struct file_system_type
*fs
,
3008 int flags
, const char *dev_name
,
3009 void *data
, struct vfsmount
*mnt
)
3012 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3013 yaffs_internal_read_super_mtd
, mnt
);
3016 static struct super_block
*yaffs_read_super(struct file_system_type
*fs
,
3017 int flags
, const char *dev_name
,
3021 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3022 yaffs_internal_read_super_mtd
);
3026 static struct file_system_type yaffs_fs_type
= {
3027 .owner
= THIS_MODULE
,
3029 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
3030 .mount
= yaffs_mount
,
3032 .get_sb
= yaffs_read_super
,
3034 .kill_sb
= kill_block_super
,
3035 .fs_flags
= FS_REQUIRES_DEV
,
3038 static struct super_block
*yaffs_read_super(struct super_block
*sb
, void *data
,
3041 return yaffs_internal_read_super(1, sb
, data
, silent
);
3044 static DECLARE_FSTYPE(yaffs_fs_type
, "yaffs", yaffs_read_super
,
3049 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
3050 static int yaffs2_internal_read_super_mtd(struct super_block
*sb
, void *data
,
3053 return yaffs_internal_read_super(2, sb
, data
, silent
) ? 0 : -EINVAL
;
3056 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
3057 static struct dentry
*yaffs2_mount(struct file_system_type
*fs_type
, int flags
,
3058 const char *dev_name
, void *data
)
3060 return mount_bdev(fs_type
, flags
, dev_name
, data
, yaffs2_internal_read_super_mtd
);
3062 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3063 static int yaffs2_read_super(struct file_system_type
*fs
,
3064 int flags
, const char *dev_name
, void *data
,
3065 struct vfsmount
*mnt
)
3067 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3068 yaffs2_internal_read_super_mtd
, mnt
);
3071 static struct super_block
*yaffs2_read_super(struct file_system_type
*fs
,
3072 int flags
, const char *dev_name
,
3076 return get_sb_bdev(fs
, flags
, dev_name
, data
,
3077 yaffs2_internal_read_super_mtd
);
3081 static struct file_system_type yaffs2_fs_type
= {
3082 .owner
= THIS_MODULE
,
3084 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
3085 .mount
= yaffs2_mount
,
3087 .get_sb
= yaffs2_read_super
,
3089 .kill_sb
= kill_block_super
,
3090 .fs_flags
= FS_REQUIRES_DEV
,
3093 static struct super_block
*yaffs2_read_super(struct super_block
*sb
,
3094 void *data
, int silent
)
3096 return yaffs_internal_read_super(2, sb
, data
, silent
);
3099 static DECLARE_FSTYPE(yaffs2_fs_type
, "yaffs2", yaffs2_read_super
,
3104 static struct proc_dir_entry
*my_proc_entry
;
3106 static char *yaffs_dump_dev_part0(char *buf
, struct yaffs_dev
*dev
)
3108 struct yaffs_param
*param
= &dev
->param
;
3111 yaffs_count_blocks_by_state(dev
,bs
);
3113 buf
+= sprintf(buf
, "start_block.......... %d\n", param
->start_block
);
3114 buf
+= sprintf(buf
, "end_block............ %d\n", param
->end_block
);
3115 buf
+= sprintf(buf
, "total_bytes_per_chunk %d\n",
3116 param
->total_bytes_per_chunk
);
3117 buf
+= sprintf(buf
, "use_nand_ecc......... %d\n", param
->use_nand_ecc
);
3118 buf
+= sprintf(buf
, "no_tags_ecc.......... %d\n", param
->no_tags_ecc
);
3119 buf
+= sprintf(buf
, "is_yaffs2............ %d\n", param
->is_yaffs2
);
3120 buf
+= sprintf(buf
, "inband_tags.......... %d\n", param
->inband_tags
);
3121 buf
+= sprintf(buf
, "empty_lost_n_found... %d\n",
3122 param
->empty_lost_n_found
);
3123 buf
+= sprintf(buf
, "disable_lazy_load.... %d\n",
3124 param
->disable_lazy_load
);
3125 buf
+= sprintf(buf
, "disable_bad_block_mrk %d\n",
3126 param
->disable_bad_block_marking
);
3127 buf
+= sprintf(buf
, "refresh_period....... %d\n",
3128 param
->refresh_period
);
3129 buf
+= sprintf(buf
, "n_caches............. %d\n", param
->n_caches
);
3130 buf
+= sprintf(buf
, "n_reserved_blocks.... %d\n",
3131 param
->n_reserved_blocks
);
3132 buf
+= sprintf(buf
, "always_check_erased.. %d\n",
3133 param
->always_check_erased
);
3134 buf
+= sprintf(buf
, "\n");
3135 buf
+= sprintf(buf
, "block count by state\n");
3136 buf
+= sprintf(buf
, "0:%d 1:%d 2:%d 3:%d 4:%d\n",
3137 bs
[0], bs
[1], bs
[2], bs
[3], bs
[4]);
3138 buf
+= sprintf(buf
, "5:%d 6:%d 7:%d 8:%d 9:%d\n",
3139 bs
[5], bs
[6], bs
[7], bs
[8], bs
[9]);
3144 static char *yaffs_dump_dev_part1(char *buf
, struct yaffs_dev
*dev
)
3146 buf
+= sprintf(buf
, "max file size....... %lld\n",
3147 (long long) yaffs_max_file_size(dev
));
3148 buf
+= sprintf(buf
, "data_bytes_per_chunk. %d\n",
3149 dev
->data_bytes_per_chunk
);
3150 buf
+= sprintf(buf
, "chunk_grp_bits....... %d\n", dev
->chunk_grp_bits
);
3151 buf
+= sprintf(buf
, "chunk_grp_size....... %d\n", dev
->chunk_grp_size
);
3152 buf
+= sprintf(buf
, "n_erased_blocks...... %d\n", dev
->n_erased_blocks
);
3153 buf
+= sprintf(buf
, "blocks_in_checkpt.... %d\n",
3154 dev
->blocks_in_checkpt
);
3155 buf
+= sprintf(buf
, "\n");
3156 buf
+= sprintf(buf
, "n_tnodes............. %d\n", dev
->n_tnodes
);
3157 buf
+= sprintf(buf
, "n_obj................ %d\n", dev
->n_obj
);
3158 buf
+= sprintf(buf
, "n_free_chunks........ %d\n", dev
->n_free_chunks
);
3159 buf
+= sprintf(buf
, "\n");
3160 buf
+= sprintf(buf
, "n_page_writes........ %u\n", dev
->n_page_writes
);
3161 buf
+= sprintf(buf
, "n_page_reads......... %u\n", dev
->n_page_reads
);
3162 buf
+= sprintf(buf
, "n_erasures........... %u\n", dev
->n_erasures
);
3163 buf
+= sprintf(buf
, "n_gc_copies.......... %u\n", dev
->n_gc_copies
);
3164 buf
+= sprintf(buf
, "all_gcs.............. %u\n", dev
->all_gcs
);
3165 buf
+= sprintf(buf
, "passive_gc_count..... %u\n",
3166 dev
->passive_gc_count
);
3167 buf
+= sprintf(buf
, "oldest_dirty_gc_count %u\n",
3168 dev
->oldest_dirty_gc_count
);
3169 buf
+= sprintf(buf
, "n_gc_blocks.......... %u\n", dev
->n_gc_blocks
);
3170 buf
+= sprintf(buf
, "bg_gcs............... %u\n", dev
->bg_gcs
);
3171 buf
+= sprintf(buf
, "n_retried_writes..... %u\n",
3172 dev
->n_retried_writes
);
3173 buf
+= sprintf(buf
, "n_retired_blocks..... %u\n",
3174 dev
->n_retired_blocks
);
3175 buf
+= sprintf(buf
, "n_ecc_fixed.......... %u\n", dev
->n_ecc_fixed
);
3176 buf
+= sprintf(buf
, "n_ecc_unfixed........ %u\n", dev
->n_ecc_unfixed
);
3177 buf
+= sprintf(buf
, "n_tags_ecc_fixed..... %u\n",
3178 dev
->n_tags_ecc_fixed
);
3179 buf
+= sprintf(buf
, "n_tags_ecc_unfixed... %u\n",
3180 dev
->n_tags_ecc_unfixed
);
3181 buf
+= sprintf(buf
, "cache_hits........... %u\n", dev
->cache_hits
);
3182 buf
+= sprintf(buf
, "n_deleted_files...... %u\n", dev
->n_deleted_files
);
3183 buf
+= sprintf(buf
, "n_unlinked_files..... %u\n",
3184 dev
->n_unlinked_files
);
3185 buf
+= sprintf(buf
, "refresh_count........ %u\n", dev
->refresh_count
);
3186 buf
+= sprintf(buf
, "n_bg_deletions....... %u\n", dev
->n_bg_deletions
);
3187 buf
+= sprintf(buf
, "tags_used............ %u\n", dev
->tags_used
);
3188 buf
+= sprintf(buf
, "summary_used......... %u\n", dev
->summary_used
);
3193 static int yaffs_proc_read(char *page
,
3195 off_t offset
, int count
, int *eof
, void *data
)
3197 struct list_head
*item
;
3202 /* Get proc_file_read() to step 'offset' by one on each sucessive call.
3203 * We use 'offset' (*ppos) to indicate where we are in dev_list.
3204 * This also assumes the user has posted a read buffer large
3205 * enough to hold the complete output; but that's life in /proc.
3210 /* Print header first */
3214 "Multi-version YAFFS built:" __DATE__
" " __TIME__
3217 buf
+= sprintf(buf
, "\n");
3221 mutex_lock(&yaffs_context_lock
);
3223 /* Locate and print the Nth entry. Order N-squared but N is small. */
3224 list_for_each(item
, &yaffs_context_list
) {
3225 struct yaffs_linux_context
*dc
=
3226 list_entry(item
, struct yaffs_linux_context
,
3228 struct yaffs_dev
*dev
= dc
->dev
;
3230 if (n
< (step
& ~1)) {
3234 if ((step
& 1) == 0) {
3236 sprintf(buf
, "\nDevice %d \"%s\"\n", n
,
3238 buf
= yaffs_dump_dev_part0(buf
, dev
);
3240 buf
= yaffs_dump_dev_part1(buf
, dev
);
3245 mutex_unlock(&yaffs_context_lock
);
3248 return buf
- page
< count
? buf
- page
: count
;
3252 * Set the verbosity of the warnings and error messages.
3254 * Note that the names can only be a..z or _ with the current code.
3259 unsigned mask_bitfield
;
3261 {"allocate", YAFFS_TRACE_ALLOCATE
},
3262 {"always", YAFFS_TRACE_ALWAYS
},
3263 {"background", YAFFS_TRACE_BACKGROUND
},
3264 {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS
},
3265 {"buffers", YAFFS_TRACE_BUFFERS
},
3266 {"bug", YAFFS_TRACE_BUG
},
3267 {"checkpt", YAFFS_TRACE_CHECKPOINT
},
3268 {"deletion", YAFFS_TRACE_DELETION
},
3269 {"erase", YAFFS_TRACE_ERASE
},
3270 {"error", YAFFS_TRACE_ERROR
},
3271 {"gc_detail", YAFFS_TRACE_GC_DETAIL
},
3272 {"gc", YAFFS_TRACE_GC
},
3273 {"lock", YAFFS_TRACE_LOCK
},
3274 {"mtd", YAFFS_TRACE_MTD
},
3275 {"nandaccess", YAFFS_TRACE_NANDACCESS
},
3276 {"os", YAFFS_TRACE_OS
},
3277 {"scan_debug", YAFFS_TRACE_SCAN_DEBUG
},
3278 {"scan", YAFFS_TRACE_SCAN
},
3279 {"mount", YAFFS_TRACE_MOUNT
},
3280 {"tracing", YAFFS_TRACE_TRACING
},
3281 {"sync", YAFFS_TRACE_SYNC
},
3282 {"write", YAFFS_TRACE_WRITE
},
3283 {"verify", YAFFS_TRACE_VERIFY
},
3284 {"verify_nand", YAFFS_TRACE_VERIFY_NAND
},
3285 {"verify_full", YAFFS_TRACE_VERIFY_FULL
},
3286 {"verify_all", YAFFS_TRACE_VERIFY_ALL
},
3287 {"all", 0xffffffff},
3292 #define MAX_MASK_NAME_LENGTH 40
3293 static int yaffs_proc_write_trace_options(struct file
*file
, const char *buf
,
3294 unsigned long count
)
3296 unsigned rg
= 0, mask_bitfield
;
3300 char substring
[MAX_MASK_NAME_LENGTH
+ 1];
3306 rg
= yaffs_trace_mask
;
3308 while (!done
&& (pos
< count
)) {
3310 while ((pos
< count
) && isspace(buf
[pos
]))
3327 mask_bitfield
= simple_strtoul(buf
+ pos
, &end
, 0);
3329 if (end
> buf
+ pos
) {
3330 mask_name
= "numeral";
3331 len
= end
- (buf
+ pos
);
3335 for (x
= buf
+ pos
, i
= 0;
3336 (*x
== '_' || (*x
>= 'a' && *x
<= 'z')) &&
3337 i
< MAX_MASK_NAME_LENGTH
; x
++, i
++, pos
++)
3339 substring
[i
] = '\0';
3341 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
3342 if (strcmp(substring
, mask_flags
[i
].mask_name
)
3344 mask_name
= mask_flags
[i
].mask_name
;
3346 mask_flags
[i
].mask_bitfield
;
3353 if (mask_name
!= NULL
) {
3357 rg
&= ~mask_bitfield
;
3360 rg
|= mask_bitfield
;
3366 rg
|= mask_bitfield
;
3372 yaffs_trace_mask
= rg
| YAFFS_TRACE_ALWAYS
;
3374 printk(KERN_DEBUG
"new trace = 0x%08X\n", yaffs_trace_mask
);
3376 if (rg
& YAFFS_TRACE_ALWAYS
) {
3377 for (i
= 0; mask_flags
[i
].mask_name
!= NULL
; i
++) {
3379 flag
= ((rg
& mask_flags
[i
].mask_bitfield
) ==
3380 mask_flags
[i
].mask_bitfield
) ? '+' : '-';
3381 printk(KERN_DEBUG
"%c%s\n", flag
,
3382 mask_flags
[i
].mask_name
);
3389 /* Debug strings are of the form:
3390 * .bnnn print info on block n
3391 * .cobjn,chunkn print nand chunk id for objn:chunkn
3394 static int yaffs_proc_debug_write(struct file
*file
, const char *buf
,
3395 unsigned long count
)
3404 struct list_head
*item
;
3406 memset(str
, 0, sizeof(str
));
3407 memcpy(str
, buf
, min((size_t)count
, sizeof(str
) -1));
3415 while (*p1
&& *p1
!= ',') {
3421 p0_val
= simple_strtol(p0
, NULL
, 0);
3422 p1_val
= simple_strtol(p1
, NULL
, 0);
3425 mutex_lock(&yaffs_context_lock
);
3427 /* Locate and print the Nth entry. Order N-squared but N is small. */
3428 list_for_each(item
, &yaffs_context_list
) {
3429 struct yaffs_linux_context
*dc
=
3430 list_entry(item
, struct yaffs_linux_context
,
3432 struct yaffs_dev
*dev
= dc
->dev
;
3435 struct yaffs_block_info
*bi
;
3437 bi
= yaffs_get_block_info(dev
,p0_val
);
3440 printk("Block %d: state %d, retire %d, use %d, seq %d\n",
3441 (int)p0_val
, bi
->block_state
,
3442 bi
->needs_retiring
, bi
->pages_in_use
,
3445 } else if (cmd
== 'c') {
3446 struct yaffs_obj
*obj
;
3449 obj
= yaffs_find_by_number(dev
, p0_val
);
3451 printk("No obj %d\n", (int)p0_val
);
3454 nand_chunk
= obj
->hdr_chunk
;
3457 yaffs_find_chunk_in_file(obj
,
3459 printk("Nand chunk for %d:%d is %d\n",
3460 (int)p0_val
, (int)p1_val
, nand_chunk
);
3465 mutex_unlock(&yaffs_context_lock
);
3471 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
3472 static int yaffs_proc_write(struct file
*file
, const char *buf
,
3473 unsigned long count
, void *ppos
)
3475 static ssize_t
yaffs_proc_write(struct file
*file
, const char __user
*buf
,
3476 size_t count
, loff_t
*ppos
)
3480 return yaffs_proc_debug_write(file
, buf
, count
);
3481 return yaffs_proc_write_trace_options(file
, buf
, count
);
3484 /* Stuff to handle installation of file systems */
3485 struct file_system_to_install
{
3486 struct file_system_type
*fst
;
3490 static struct file_system_to_install fs_to_install
[] = {
3491 {&yaffs_fs_type
, 0},
3492 {&yaffs2_fs_type
, 0},
3497 #ifdef YAFFS_NEW_PROCFS
3498 static int yaffs_proc_show(struct seq_file
*m
, void *v
)
3500 /* FIXME: Unify in a better way? */
3505 len
= yaffs_proc_read(buffer
, &start
, 0, sizeof(buffer
), NULL
, NULL
);
3506 seq_puts(m
, buffer
);
3510 static int yaffs_proc_open(struct inode
*inode
, struct file
*file
)
3512 return single_open(file
, yaffs_proc_show
, NULL
);
3515 static struct file_operations procfs_ops
= {
3516 .owner
= THIS_MODULE
,
3517 .open
= yaffs_proc_open
,
3519 .write
= yaffs_proc_write
,
3522 static int yaffs_procfs_init(void)
3524 /* Install the proc_fs entries */
3525 my_proc_entry
= proc_create("yaffs",
3530 if (my_proc_entry
) {
3540 static int yaffs_procfs_init(void)
3542 /* Install the proc_fs entries */
3543 my_proc_entry
= create_proc_entry("yaffs",
3544 S_IRUGO
| S_IFREG
, YPROC_ROOT
);
3546 if (my_proc_entry
) {
3547 my_proc_entry
->write_proc
= yaffs_proc_write
;
3548 my_proc_entry
->read_proc
= yaffs_proc_read
;
3549 my_proc_entry
->data
= NULL
;
3559 static int __init
init_yaffs_fs(void)
3562 struct file_system_to_install
*fsinst
;
3564 yaffs_trace(YAFFS_TRACE_ALWAYS
,
3565 "yaffs built " __DATE__
" " __TIME__
" Installing.");
3567 mutex_init(&yaffs_context_lock
);
3569 error
= yaffs_procfs_init();
3573 /* Now add the file system entries */
3575 fsinst
= fs_to_install
;
3577 while (fsinst
->fst
&& !error
) {
3578 error
= register_filesystem(fsinst
->fst
);
3580 fsinst
->installed
= 1;
3584 /* Any errors? uninstall */
3586 fsinst
= fs_to_install
;
3588 while (fsinst
->fst
) {
3589 if (fsinst
->installed
) {
3590 unregister_filesystem(fsinst
->fst
);
3591 fsinst
->installed
= 0;
3600 static void __exit
exit_yaffs_fs(void)
3603 struct file_system_to_install
*fsinst
;
3605 yaffs_trace(YAFFS_TRACE_ALWAYS
,
3606 "yaffs built " __DATE__
" " __TIME__
" removing.");
3608 remove_proc_entry("yaffs", YPROC_ROOT
);
3610 fsinst
= fs_to_install
;
3612 while (fsinst
->fst
) {
3613 if (fsinst
->installed
) {
3614 unregister_filesystem(fsinst
->fst
);
3615 fsinst
->installed
= 0;
3621 module_init(init_yaffs_fs
)
3622 module_exit(exit_yaffs_fs
)
3624 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
3625 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
3626 MODULE_LICENSE("GPL");