kernel: update yaffs code to the latest version
[openwrt/staging/yousong.git] / target / linux / generic / files / fs / yaffs2 / yaffs_vfs.c
1 /*
2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3 *
4 * Copyright (C) 2002-2011 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
6 *
7 * Created by Charles Manning <charles@aleph1.co.uk>
8 * Acknowledgements:
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
15 *
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.
19 */
20
21 /*
22 *
23 * This is the file system front-end to YAFFS that hooks it up to
24 * the VFS.
25 *
26 * Special notes:
27 * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with
28 * this superblock
29 * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this
30 * superblock
31 * >> inode->u.generic_ip points to the associated struct yaffs_obj.
32 */
33
34 /*
35 * There are two variants of the VFS glue code. This variant should compile
36 * for any version of Linux.
37 */
38 #include <linux/version.h>
39
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
44 #endif
45 #endif
46
47 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
48 #define YAFFS_COMPILE_EXPORTFS
49 #endif
50
51 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
52 #define YAFFS_USE_SETATTR_COPY
53 #define YAFFS_USE_TRUNCATE_SETSIZE
54 #endif
55 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
56 #define YAFFS_HAS_EVICT_INODE
57 #endif
58
59 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
60 #define YAFFS_NEW_FOLLOW_LINK 1
61 #else
62 #define YAFFS_NEW_FOLLOW_LINK 0
63 #endif
64
65 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
66 #define YAFFS_HAS_WRITE_SUPER
67 #endif
68
69
70 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
71 #include <linux/config.h>
72 #endif
73
74 #include <linux/kernel.h>
75 #include <linux/module.h>
76 #include <linux/slab.h>
77 #include <linux/init.h>
78 #include <linux/fs.h>
79 #include <linux/proc_fs.h>
80 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
81 #include <linux/smp_lock.h>
82 #endif
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>
88
89 #if (YAFFS_NEW_FOLLOW_LINK == 1)
90 #include <linux/namei.h>
91 #endif
92
93 #ifdef YAFFS_COMPILE_EXPORTFS
94 #include <linux/exportfs.h>
95 #endif
96
97 #ifdef YAFFS_COMPILE_BACKGROUND
98 #include <linux/kthread.h>
99 #include <linux/delay.h>
100 #endif
101 #ifdef YAFFS_COMPILE_FREEZER
102 #include <linux/freezer.h>
103 #endif
104
105 #include <asm/div64.h>
106
107 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
108
109 #include <linux/statfs.h>
110
111 #define UnlockPage(p) unlock_page(p)
112 #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
113
114 /* FIXME: use sb->s_id instead ? */
115 #define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
116
117 #else
118
119 #include <linux/locks.h>
120 #define BDEVNAME_SIZE 0
121 #define yaffs_devname(sb, buf) kdevname(sb->s_dev)
122
123 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
124 /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
125 #define __user
126 #endif
127
128 #endif
129
130 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
131 #define YPROC_ROOT (&proc_root)
132 #else
133 #define YPROC_ROOT NULL
134 #endif
135
136 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
137 #define Y_INIT_TIMER(a) init_timer(a)
138 #else
139 #define Y_INIT_TIMER(a) init_timer_on_stack(a)
140 #endif
141
142 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
143 #define YAFFS_USE_WRITE_BEGIN_END 1
144 #else
145 #define YAFFS_USE_WRITE_BEGIN_END 0
146 #endif
147
148 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
149 #define YAFFS_SUPER_HAS_DIRTY
150 #endif
151
152
153 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
154 #define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0)
155 #endif
156
157 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
158 static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
159 {
160 uint64_t result = partition_size;
161 do_div(result, block_size);
162 return (uint32_t) result;
163 }
164 #else
165 #define YCALCBLOCKS(s, b) ((s)/(b))
166 #endif
167
168 #include <linux/uaccess.h>
169 #include <linux/mtd/mtd.h>
170
171 #include "yportenv.h"
172 #include "yaffs_trace.h"
173 #include "yaffs_guts.h"
174 #include "yaffs_attribs.h"
175
176 #include "yaffs_linux.h"
177
178 #include "yaffs_mtdif.h"
179 #include "yaffs_packedtags2.h"
180 #include "yaffs_getblockinfo.h"
181
182 unsigned int yaffs_trace_mask =
183 YAFFS_TRACE_BAD_BLOCKS |
184 YAFFS_TRACE_ALWAYS |
185 0;
186
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);
199 #else
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");
204 #endif
205
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))
209
210 #else
211 /* Call local equivalent */
212 #define YAFFS_USE_OWN_IGET
213 #define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
214
215 #endif
216
217 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
218 #define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private)
219 #else
220 #define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
221 #endif
222
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)
226
227 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
228 #define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info)
229 #else
230 #define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp)
231 #endif
232
233 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
234 #define Y_CLEAR_INODE(i) clear_inode(i)
235 #else
236 #define Y_CLEAR_INODE(i) end_writeback(i)
237 #endif
238
239 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
240 #define YAFFS_USE_DIR_ITERATE
241 #endif
242
243 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
244 #define YAFFS_NEW_PROCFS
245 #include <linux/seq_file.h>
246 #endif
247
248
249 #define update_dir_time(dir) do {\
250 (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
251 } while (0)
252
253 static void yaffs_fill_inode_from_obj(struct inode *inode,
254 struct yaffs_obj *obj);
255
256
257 static void yaffs_gross_lock(struct yaffs_dev *dev)
258 {
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);
262 }
263
264 static void yaffs_gross_unlock(struct yaffs_dev *dev)
265 {
266 yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current);
267 mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock));
268 }
269
270
271 static int yaffs_readpage_nolock(struct file *f, struct page *pg)
272 {
273 /* Lifted from jffs2 */
274
275 struct yaffs_obj *obj;
276 unsigned char *pg_buf;
277 int ret;
278 loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
279 struct yaffs_dev *dev;
280
281 yaffs_trace(YAFFS_TRACE_OS,
282 "yaffs_readpage_nolock at %lld, size %08x",
283 (long long)pos,
284 (unsigned)PAGE_CACHE_SIZE);
285
286 obj = yaffs_dentry_to_obj(f->f_dentry);
287
288 dev = obj->my_dev;
289
290 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
291 BUG_ON(!PageLocked(pg));
292 #else
293 if (!PageLocked(pg))
294 PAGE_BUG(pg);
295 #endif
296
297 pg_buf = kmap(pg);
298 /* FIXME: Can kmap fail? */
299
300 yaffs_gross_lock(dev);
301
302 ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE);
303
304 yaffs_gross_unlock(dev);
305
306 if (ret >= 0)
307 ret = 0;
308
309 if (ret) {
310 ClearPageUptodate(pg);
311 SetPageError(pg);
312 } else {
313 SetPageUptodate(pg);
314 ClearPageError(pg);
315 }
316
317 flush_dcache_page(pg);
318 kunmap(pg);
319
320 yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done");
321 return ret;
322 }
323
324 static int yaffs_readpage_unlock(struct file *f, struct page *pg)
325 {
326 int ret = yaffs_readpage_nolock(f, pg);
327 UnlockPage(pg);
328 return ret;
329 }
330
331 static int yaffs_readpage(struct file *f, struct page *pg)
332 {
333 int ret;
334
335 yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage");
336 ret = yaffs_readpage_unlock(f, pg);
337 yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done");
338 return ret;
339 }
340
341
342 static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
343 {
344 struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
345
346 if (lc)
347 lc->dirty = val;
348
349 # ifdef YAFFS_SUPER_HAS_DIRTY
350 {
351 struct super_block *sb = lc->super;
352
353 if (sb)
354 sb->s_dirt = val;
355 }
356 #endif
357
358 }
359
360 static void yaffs_set_super_dirty(struct yaffs_dev *dev)
361 {
362 yaffs_set_super_dirty_val(dev, 1);
363 }
364
365 static void yaffs_clear_super_dirty(struct yaffs_dev *dev)
366 {
367 yaffs_set_super_dirty_val(dev, 0);
368 }
369
370 static int yaffs_check_super_dirty(struct yaffs_dev *dev)
371 {
372 struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
373
374 if (lc && lc->dirty)
375 return 1;
376
377 # ifdef YAFFS_SUPER_HAS_DIRTY
378 {
379 struct super_block *sb = lc->super;
380
381 if (sb && sb->s_dirt)
382 return 1;
383 }
384 #endif
385 return 0;
386
387 }
388
389 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
390 static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
391 #else
392 static int yaffs_writepage(struct page *page)
393 #endif
394 {
395 struct yaffs_dev *dev;
396 struct address_space *mapping = page->mapping;
397 struct inode *inode;
398 unsigned long end_index;
399 char *buffer;
400 struct yaffs_obj *obj;
401 int n_written = 0;
402 unsigned n_bytes;
403 loff_t i_size;
404
405 if (!mapping)
406 BUG();
407 inode = mapping->host;
408 if (!inode)
409 BUG();
410 i_size = i_size_read(inode);
411
412 end_index = i_size >> PAGE_CACHE_SHIFT;
413
414 if (page->index < end_index)
415 n_bytes = PAGE_CACHE_SIZE;
416 else {
417 n_bytes = i_size & (PAGE_CACHE_SIZE - 1);
418
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,
423 inode->i_size);
424 yaffs_trace(YAFFS_TRACE_OS,
425 " -> don't care!!");
426
427 zero_user_segment(page, 0, PAGE_CACHE_SIZE);
428 set_page_writeback(page);
429 unlock_page(page);
430 end_page_writeback(page);
431 return 0;
432 }
433 }
434
435 if (n_bytes != PAGE_CACHE_SIZE)
436 zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE);
437
438 get_page(page);
439
440 buffer = kmap(page);
441
442 obj = yaffs_inode_to_obj(inode);
443 dev = obj->my_dev;
444 yaffs_gross_lock(dev);
445
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);
452
453 n_written = yaffs_wr_file(obj, buffer,
454 ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0);
455
456 yaffs_set_super_dirty(dev);
457
458 yaffs_trace(YAFFS_TRACE_OS,
459 "writepag1: obj = %lld, ino = %lld",
460 obj->variant.file_variant.file_size, inode->i_size);
461
462 yaffs_gross_unlock(dev);
463
464 kunmap(page);
465 set_page_writeback(page);
466 unlock_page(page);
467 end_page_writeback(page);
468 put_page(page);
469
470 return (n_written == n_bytes) ? 0 : -ENOSPC;
471 }
472
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 */
476
477 static ssize_t yaffs_hold_space(struct file *f)
478 {
479 struct yaffs_obj *obj;
480 struct yaffs_dev *dev;
481
482 int n_free_chunks;
483
484 obj = yaffs_dentry_to_obj(f->f_dentry);
485
486 dev = obj->my_dev;
487
488 yaffs_gross_lock(dev);
489
490 n_free_chunks = yaffs_get_n_free_chunks(dev);
491
492 yaffs_gross_unlock(dev);
493
494 return (n_free_chunks > 20) ? 1 : 0;
495 }
496
497 static void yaffs_release_space(struct file *f)
498 {
499 struct yaffs_obj *obj;
500 struct yaffs_dev *dev;
501
502 obj = yaffs_dentry_to_obj(f->f_dentry);
503
504 dev = obj->my_dev;
505
506 yaffs_gross_lock(dev);
507
508 yaffs_gross_unlock(dev);
509 }
510
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)
515 {
516 struct page *pg = NULL;
517 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
518
519 int ret = 0;
520 int space_held = 0;
521
522 /* Get a page */
523 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
524 pg = grab_cache_page_write_begin(mapping, index, flags);
525 #else
526 pg = __grab_cache_page(mapping, index);
527 #endif
528
529 *pagep = pg;
530 if (!pg) {
531 ret = -ENOMEM;
532 goto out;
533 }
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);
537
538 /* Get fs space */
539 space_held = yaffs_hold_space(filp);
540
541 if (!space_held) {
542 ret = -ENOSPC;
543 goto out;
544 }
545
546 /* Update page if required */
547
548 if (!Page_Uptodate(pg))
549 ret = yaffs_readpage_nolock(filp, pg);
550
551 if (ret)
552 goto out;
553
554 /* Happy path return */
555 yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok");
556
557 return 0;
558
559 out:
560 yaffs_trace(YAFFS_TRACE_OS,
561 "end yaffs_write_begin fail returning %d", ret);
562 if (space_held)
563 yaffs_release_space(filp);
564 if (pg) {
565 unlock_page(pg);
566 page_cache_release(pg);
567 }
568 return ret;
569 }
570
571 #else
572
573 static int yaffs_prepare_write(struct file *f, struct page *pg,
574 unsigned offset, unsigned to)
575 {
576 yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write");
577
578 if (!Page_Uptodate(pg))
579 return yaffs_readpage_nolock(f, pg);
580 return 0;
581 }
582 #endif
583
584
585 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
586 loff_t * pos)
587 {
588 struct yaffs_obj *obj;
589 int n_written;
590 loff_t ipos;
591 struct inode *inode;
592 struct yaffs_dev *dev;
593
594 obj = yaffs_dentry_to_obj(f->f_dentry);
595
596 if (!obj) {
597 yaffs_trace(YAFFS_TRACE_OS,
598 "yaffs_file_write: hey obj is null!");
599 return -EINVAL;
600 }
601
602 dev = obj->my_dev;
603
604 yaffs_gross_lock(dev);
605
606 inode = f->f_dentry->d_inode;
607
608 if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
609 ipos = inode->i_size;
610 else
611 ipos = *pos;
612
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);
616
617 n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
618
619 yaffs_set_super_dirty(dev);
620
621 yaffs_trace(YAFFS_TRACE_OS,
622 "yaffs_file_write: %d(%x) bytes written",
623 (unsigned)n, (unsigned)n);
624
625 if (n_written > 0) {
626 ipos += n_written;
627 *pos = ipos;
628 if (ipos > inode->i_size) {
629 inode->i_size = ipos;
630 inode->i_blocks = (ipos + 511) >> 9;
631
632 yaffs_trace(YAFFS_TRACE_OS,
633 "yaffs_file_write size updated to %lld bytes, %d blocks",
634 ipos, (int)(inode->i_blocks));
635 }
636
637 }
638 yaffs_gross_unlock(dev);
639 return (n_written == 0) && (n > 0) ? -ENOSPC : n_written;
640 }
641
642
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)
647 {
648 int ret = 0;
649 void *addr, *kva;
650 uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
651
652 kva = kmap(pg);
653 addr = kva + offset_into_page;
654
655 yaffs_trace(YAFFS_TRACE_OS,
656 "yaffs_write_end addr %p pos %lld n_bytes %d",
657 addr, pos, copied);
658
659 ret = yaffs_file_write(filp, addr, copied, &pos);
660
661 if (ret != copied) {
662 yaffs_trace(YAFFS_TRACE_OS,
663 "yaffs_write_end not same size ret %d copied %d",
664 ret, copied);
665 SetPageError(pg);
666 }
667
668 kunmap(pg);
669
670 yaffs_release_space(filp);
671 unlock_page(pg);
672 page_cache_release(pg);
673 return ret;
674 }
675 #else
676
677 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
678 unsigned to)
679 {
680 void *addr, *kva;
681
682 loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
683 int n_bytes = to - offset;
684 int n_written;
685
686 kva = kmap(pg);
687 addr = kva + offset;
688
689 yaffs_trace(YAFFS_TRACE_OS,
690 "yaffs_commit_write addr %p pos %lld n_bytes %d",
691 addr, pos, n_bytes);
692
693 n_written = yaffs_file_write(f, addr, n_bytes, &pos);
694
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",
698 n_written, n_bytes);
699 SetPageError(pg);
700 }
701 kunmap(pg);
702
703 yaffs_trace(YAFFS_TRACE_OS,
704 "yaffs_commit_write returning %d",
705 n_written == n_bytes ? 0 : n_written);
706
707 return n_written == n_bytes ? 0 : n_written;
708 }
709 #endif
710
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,
717 #else
718 .prepare_write = yaffs_prepare_write,
719 .commit_write = yaffs_commit_write,
720 #endif
721 };
722
723
724 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
725 static int yaffs_file_flush(struct file *file, fl_owner_t id)
726 #else
727 static int yaffs_file_flush(struct file *file)
728 #endif
729 {
730 struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
731
732 struct yaffs_dev *dev = obj->my_dev;
733
734 yaffs_trace(YAFFS_TRACE_OS,
735 "yaffs_file_flush object %d (%s)",
736 obj->obj_id,
737 obj->dirty ? "dirty" : "clean");
738
739 yaffs_gross_lock(dev);
740
741 yaffs_flush_file(obj, 1, 0);
742
743 yaffs_gross_unlock(dev);
744
745 return 0;
746 }
747
748
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)
753 #else
754 static int yaffs_sync_object(struct file *file, struct dentry *dentry,
755 int datasync)
756 #endif
757 {
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;
762 #endif
763
764 obj = yaffs_dentry_to_obj(dentry);
765
766 dev = obj->my_dev;
767
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);
773 return 0;
774 }
775
776
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,
789 };
790
791 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
792
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,
802 };
803
804 #else
805
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,
814 #endif
815 };
816 #endif
817
818
819
820
821 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
822 static void zero_user_segment(struct page *page, unsigned start, unsigned end)
823 {
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);
828 }
829 #endif
830
831
832 static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
833 {
834 #ifdef YAFFS_USE_TRUNCATE_SETSIZE
835 truncate_setsize(inode, newsize);
836 return 0;
837 #else
838 truncate_inode_pages(&inode->i_data, newsize);
839 return 0;
840 #endif
841
842 }
843
844
845 static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
846 {
847 #ifdef YAFFS_USE_SETATTR_COPY
848 setattr_copy(inode, attr);
849 return 0;
850 #else
851 return inode_setattr(inode, attr);
852 #endif
853
854 }
855
856 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
857 {
858 struct inode *inode = dentry->d_inode;
859 int error = 0;
860 struct yaffs_dev *dev;
861
862 yaffs_trace(YAFFS_TRACE_OS,
863 "yaffs_setattr of object %d",
864 yaffs_inode_to_obj(inode)->obj_id);
865 #if 0
866 /* Fail if a requested resize >= 2GB */
867 if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
868 error = -EINVAL;
869 #endif
870
871 if (error == 0)
872 error = inode_change_ok(inode, attr);
873 if (error == 0) {
874 int result;
875 if (!error) {
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;
881 }
882 }
883 dev = yaffs_inode_to_obj(inode)->my_dev;
884 if (attr->ia_valid & ATTR_SIZE) {
885 yaffs_trace(YAFFS_TRACE_OS,
886 "resize to %d(%x)",
887 (int)(attr->ia_size),
888 (int)(attr->ia_size));
889 }
890 yaffs_gross_lock(dev);
891 result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr);
892 if (result == YAFFS_OK) {
893 error = 0;
894 } else {
895 error = -EPERM;
896 }
897 yaffs_gross_unlock(dev);
898
899 }
900
901 yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error);
902
903 return error;
904 }
905
906 static int yaffs_setxattr(struct dentry *dentry, const char *name,
907 const void *value, size_t size, int flags)
908 {
909 struct inode *inode = dentry->d_inode;
910 int error = 0;
911 struct yaffs_dev *dev;
912 struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
913
914 yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id);
915
916 if (error == 0) {
917 int result;
918 dev = obj->my_dev;
919 yaffs_gross_lock(dev);
920 result = yaffs_set_xattrib(obj, name, value, size, flags);
921 if (result == YAFFS_OK)
922 error = 0;
923 else if (result < 0)
924 error = result;
925 yaffs_gross_unlock(dev);
926
927 }
928 yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error);
929
930 return error;
931 }
932
933 static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name,
934 void *buff, size_t size)
935 {
936 struct inode *inode = dentry->d_inode;
937 int error = 0;
938 struct yaffs_dev *dev;
939 struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
940
941 yaffs_trace(YAFFS_TRACE_OS,
942 "yaffs_getxattr \"%s\" from object %d",
943 name, obj->obj_id);
944
945 if (error == 0) {
946 dev = obj->my_dev;
947 yaffs_gross_lock(dev);
948 error = yaffs_get_xattrib(obj, name, buff, size);
949 yaffs_gross_unlock(dev);
950
951 }
952 yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error);
953
954 return error;
955 }
956
957 static int yaffs_removexattr(struct dentry *dentry, const char *name)
958 {
959 struct inode *inode = dentry->d_inode;
960 int error = 0;
961 struct yaffs_dev *dev;
962 struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
963
964 yaffs_trace(YAFFS_TRACE_OS,
965 "yaffs_removexattr of object %d", obj->obj_id);
966
967 if (error == 0) {
968 int result;
969 dev = obj->my_dev;
970 yaffs_gross_lock(dev);
971 result = yaffs_remove_xattrib(obj, name);
972 if (result == YAFFS_OK)
973 error = 0;
974 else if (result < 0)
975 error = result;
976 yaffs_gross_unlock(dev);
977
978 }
979 yaffs_trace(YAFFS_TRACE_OS,
980 "yaffs_removexattr done returning %d", error);
981
982 return error;
983 }
984
985 static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size)
986 {
987 struct inode *inode = dentry->d_inode;
988 int error = 0;
989 struct yaffs_dev *dev;
990 struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
991
992 yaffs_trace(YAFFS_TRACE_OS,
993 "yaffs_listxattr of object %d", obj->obj_id);
994
995 if (error == 0) {
996 dev = obj->my_dev;
997 yaffs_gross_lock(dev);
998 error = yaffs_list_xattrib(obj, buff, size);
999 yaffs_gross_unlock(dev);
1000
1001 }
1002 yaffs_trace(YAFFS_TRACE_OS,
1003 "yaffs_listxattr done returning %d", error);
1004
1005 return error;
1006 }
1007
1008
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,
1015 };
1016
1017
1018 static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
1019 int buflen)
1020 {
1021 unsigned char *alias;
1022 int ret;
1023
1024 struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
1025
1026 yaffs_gross_lock(dev);
1027
1028 alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
1029
1030 yaffs_gross_unlock(dev);
1031
1032 if (!alias)
1033 return -ENOMEM;
1034
1035 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
1036 ret = vfs_readlink(dentry, buffer, buflen, alias);
1037 #else
1038 ret = readlink_copy(buffer, buflen, alias);
1039 #endif
1040 kfree(alias);
1041 return ret;
1042 }
1043
1044 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1045 static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
1046 {
1047 void *ret;
1048 #else
1049 static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
1050 {
1051 int ret
1052 #endif
1053 unsigned char *alias;
1054 int ret_int = 0;
1055 struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
1056
1057 yaffs_gross_lock(dev);
1058
1059 alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
1060 yaffs_gross_unlock(dev);
1061
1062 if (!alias) {
1063 ret_int = -ENOMEM;
1064 goto out;
1065 }
1066 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1067 nd_set_link(nd, alias);
1068 ret = alias;
1069 out:
1070 if (ret_int)
1071 ret = ERR_PTR(ret_int);
1072 return ret;
1073 #else
1074 ret = vfs_follow_link(nd, alias);
1075 kfree(alias);
1076 out:
1077 if (ret_int)
1078 ret = ret_int;
1079 return ret;
1080 #endif
1081 }
1082
1083
1084 #ifdef YAFFS_HAS_PUT_INODE
1085
1086 /* For now put inode is just for debugging
1087 * Put inode is called when the inode **structure** is put.
1088 */
1089 static void yaffs_put_inode(struct inode *inode)
1090 {
1091 yaffs_trace(YAFFS_TRACE_OS,
1092 "yaffs_put_inode: ino %d, count %d"),
1093 (int)inode->i_ino, atomic_read(&inode->i_count);
1094
1095 }
1096 #endif
1097
1098 #if (YAFFS_NEW_FOLLOW_LINK == 1)
1099 void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias)
1100 {
1101 kfree(alias);
1102 }
1103 #endif
1104
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,
1110 #endif
1111 .setattr = yaffs_setattr,
1112 .setxattr = yaffs_setxattr,
1113 .getxattr = yaffs_getxattr,
1114 .listxattr = yaffs_listxattr,
1115 .removexattr = yaffs_removexattr,
1116 };
1117
1118 #ifdef YAFFS_USE_OWN_IGET
1119
1120 static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
1121 {
1122 struct inode *inode;
1123 struct yaffs_obj *obj;
1124 struct yaffs_dev *dev = yaffs_super_to_dev(sb);
1125
1126 yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino);
1127
1128 inode = iget_locked(sb, ino);
1129 if (!inode)
1130 return ERR_PTR(-ENOMEM);
1131 if (!(inode->i_state & I_NEW))
1132 return inode;
1133
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.
1137 */
1138
1139 yaffs_gross_lock(dev);
1140
1141 obj = yaffs_find_by_number(dev, inode->i_ino);
1142
1143 yaffs_fill_inode_from_obj(inode, obj);
1144
1145 yaffs_gross_unlock(dev);
1146
1147 unlock_new_inode(inode);
1148 return inode;
1149 }
1150
1151 #else
1152
1153 static void yaffs_read_inode(struct inode *inode)
1154 {
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.
1158 */
1159
1160 struct yaffs_obj *obj;
1161 struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb);
1162
1163 yaffs_trace(YAFFS_TRACE_OS,
1164 "yaffs_read_inode for %d", (int)inode->i_ino);
1165
1166 if (current != yaffs_dev_to_lc(dev)->readdir_process)
1167 yaffs_gross_lock(dev);
1168
1169 obj = yaffs_find_by_number(dev, inode->i_ino);
1170
1171 yaffs_fill_inode_from_obj(inode, obj);
1172
1173 if (current != yaffs_dev_to_lc(dev)->readdir_process)
1174 yaffs_gross_unlock(dev);
1175 }
1176
1177 #endif
1178
1179
1180
1181 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
1182 struct yaffs_obj *obj)
1183 {
1184 struct inode *inode;
1185
1186 if (!sb) {
1187 yaffs_trace(YAFFS_TRACE_OS,
1188 "yaffs_get_inode for NULL super_block!!");
1189 return NULL;
1190
1191 }
1192
1193 if (!obj) {
1194 yaffs_trace(YAFFS_TRACE_OS,
1195 "yaffs_get_inode for NULL object!!");
1196 return NULL;
1197
1198 }
1199
1200 yaffs_trace(YAFFS_TRACE_OS,
1201 "yaffs_get_inode for object %d", obj->obj_id);
1202
1203 inode = Y_IGET(sb, obj->obj_id);
1204 if (IS_ERR(inode))
1205 return NULL;
1206
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! */
1210
1211 return inode;
1212 }
1213
1214
1215
1216 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
1217 #define YCRED(x) x
1218 #else
1219 #define YCRED(x) (x->cred)
1220 #endif
1221
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
1229 #else
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)
1236 #endif
1237
1238
1239 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1240 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
1241 dev_t rdev)
1242 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1243 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
1244 dev_t rdev)
1245 #else
1246 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
1247 int rdev)
1248 #endif
1249 {
1250 struct inode *inode;
1251
1252 struct yaffs_obj *obj = NULL;
1253 struct yaffs_dev *dev;
1254
1255 struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
1256
1257 int error = -ENOSPC;
1258 uid_t uid = YPROC_uid(current);
1259 gid_t gid =
1260 (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
1261
1262 if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
1263 mode |= S_ISGID;
1264
1265 if (parent) {
1266 yaffs_trace(YAFFS_TRACE_OS,
1267 "yaffs_mknod: parent object %d type %d",
1268 parent->obj_id, parent->variant_type);
1269 } else {
1270 yaffs_trace(YAFFS_TRACE_OS,
1271 "yaffs_mknod: could not get parent object");
1272 return -EPERM;
1273 }
1274
1275 yaffs_trace(YAFFS_TRACE_OS,
1276 "yaffs_mknod: making oject for %s, mode %x dev %x",
1277 dentry->d_name.name, mode, rdev);
1278
1279 dev = parent->my_dev;
1280
1281 yaffs_gross_lock(dev);
1282
1283 switch (mode & S_IFMT) {
1284 default:
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))
1288 obj =
1289 yaffs_create_special(parent, dentry->d_name.name, mode, uid,
1290 gid, old_encode_dev(rdev));
1291 #else
1292 obj =
1293 yaffs_create_special(parent, dentry->d_name.name, mode, uid,
1294 gid, rdev);
1295 #endif
1296 break;
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,
1300 gid);
1301 break;
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,
1305 uid, gid);
1306 break;
1307 case S_IFLNK: /* symlink */
1308 yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink");
1309 obj = NULL; /* Do we ever get here? */
1310 break;
1311 }
1312
1313 /* Can not call yaffs_get_inode() with gross lock held */
1314 yaffs_gross_unlock(dev);
1315
1316 if (obj) {
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));
1323 error = 0;
1324 yaffs_fill_inode_from_obj(dir, parent);
1325 } else {
1326 yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object");
1327 error = -ENOMEM;
1328 }
1329
1330 return error;
1331 }
1332
1333 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
1334 static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1335 #else
1336 static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1337 #endif
1338 {
1339 int ret_val;
1340 yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir");
1341 ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
1342 return ret_val;
1343 }
1344
1345
1346 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1347 static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1348 bool dummy)
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)
1355 #else
1356 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
1357 #endif
1358 {
1359 yaffs_trace(YAFFS_TRACE_OS, "yaffs_create");
1360 return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
1361 }
1362
1363 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1364 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
1365 unsigned int dummy)
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)
1369 #else
1370 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
1371 #endif
1372 {
1373 struct yaffs_obj *obj;
1374 struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */
1375
1376 struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev;
1377
1378 if (current != yaffs_dev_to_lc(dev)->readdir_process)
1379 yaffs_gross_lock(dev);
1380
1381 yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s",
1382 yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name);
1383
1384 obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name);
1385
1386 obj = yaffs_get_equivalent_obj(obj); /* in case it was a hardlink */
1387
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);
1391
1392 if (obj) {
1393 yaffs_trace(YAFFS_TRACE_OS,
1394 "yaffs_lookup found %d", obj->obj_id);
1395
1396 inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
1397 } else {
1398 yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found");
1399
1400 }
1401
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);
1405
1406 return NULL;
1407 }
1408
1409 /*
1410 * Create a link...
1411 */
1412 static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
1413 struct dentry *dentry)
1414 {
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;
1419
1420 yaffs_trace(YAFFS_TRACE_OS, "yaffs_link");
1421
1422 obj = yaffs_inode_to_obj(inode);
1423 dev = obj->my_dev;
1424
1425 yaffs_gross_lock(dev);
1426
1427 if (!S_ISDIR(inode->i_mode)) /* Don't link directories */
1428 link =
1429 yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name,
1430 obj);
1431
1432 if (link) {
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));
1440 }
1441
1442 yaffs_gross_unlock(dev);
1443
1444 if (link) {
1445 update_dir_time(dir);
1446 return 0;
1447 }
1448
1449 return -EPERM;
1450 }
1451
1452 static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
1453 const char *symname)
1454 {
1455 struct yaffs_obj *obj;
1456 struct yaffs_dev *dev;
1457 uid_t uid = YPROC_uid(current);
1458 gid_t gid =
1459 (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
1460
1461 yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
1462
1463 if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) >
1464 YAFFS_MAX_NAME_LENGTH)
1465 return -ENAMETOOLONG;
1466
1467 if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) >
1468 YAFFS_MAX_ALIAS_LENGTH)
1469 return -ENAMETOOLONG;
1470
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);
1476
1477 if (obj) {
1478 struct inode *inode;
1479
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");
1484 return 0;
1485 } else {
1486 yaffs_trace(YAFFS_TRACE_OS, "symlink not created");
1487 }
1488
1489 return -ENOMEM;
1490 }
1491
1492 /*
1493 * The VFS layer already does all the dentry stuff for rename.
1494 *
1495 * NB: POSIX says you can rename an object over an old object of the same name
1496 */
1497 static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
1498 struct inode *new_dir, struct dentry *new_dentry)
1499 {
1500 struct yaffs_dev *dev;
1501 int ret_val = YAFFS_FAIL;
1502 struct yaffs_obj *target;
1503
1504 yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename");
1505 dev = yaffs_inode_to_obj(old_dir)->my_dev;
1506
1507 yaffs_gross_lock(dev);
1508
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);
1512
1513 if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
1514 !list_empty(&target->variant.dir_variant.children)) {
1515
1516 yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir");
1517
1518 ret_val = YAFFS_FAIL;
1519 } else {
1520 /* Now does unlinking internally using shadowing mechanism */
1521 yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj");
1522
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);
1527 }
1528 yaffs_gross_unlock(dev);
1529
1530 if (ret_val == YAFFS_OK) {
1531 if (target)
1532 inode_dec_link_count(new_dentry->d_inode);
1533
1534 update_dir_time(old_dir);
1535 if (old_dir != new_dir)
1536 update_dir_time(new_dir);
1537 return 0;
1538 } else {
1539 return -ENOTEMPTY;
1540 }
1541 }
1542
1543
1544
1545
1546 static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
1547 {
1548 int ret_val;
1549
1550 struct yaffs_dev *dev;
1551 struct yaffs_obj *obj;
1552
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);
1556 dev = obj->my_dev;
1557
1558 yaffs_gross_lock(dev);
1559
1560 ret_val = yaffs_unlinker(obj, dentry->d_name.name);
1561
1562 if (ret_val == YAFFS_OK) {
1563 inode_dec_link_count(dentry->d_inode);
1564 dir->i_version++;
1565 yaffs_gross_unlock(dev);
1566 update_dir_time(dir);
1567 return 0;
1568 }
1569 yaffs_gross_unlock(dev);
1570 return -ENOTEMPTY;
1571 }
1572
1573
1574
1575 static const struct inode_operations yaffs_dir_inode_operations = {
1576 .create = yaffs_create,
1577 .lookup = yaffs_lookup,
1578 .link = yaffs_link,
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,
1590 };
1591
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.
1596 *
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.
1602 *
1603 * Many readdirs (and thus seach conexts) may be alive simulateously so
1604 * each struct yaffs_dev has a list of these.
1605 *
1606 * A seach context lives for the duration of a readdir.
1607 *
1608 * All these functions must be called while yaffs is locked.
1609 */
1610
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;
1616 };
1617
1618 /*
1619 * yaffs_new_search() creates a new search context, initialises it and
1620 * adds it to the device's search context list.
1621 *
1622 * Called at start of readdir.
1623 */
1624 static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir)
1625 {
1626 struct yaffs_dev *dev = dir->my_dev;
1627 struct yaffs_search_context *sc =
1628 kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS);
1629 if (sc) {
1630 sc->dir_obj = dir;
1631 sc->dev = dev;
1632 if (list_empty(&sc->dir_obj->variant.dir_variant.children))
1633 sc->next_return = NULL;
1634 else
1635 sc->next_return =
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));
1640 }
1641 return sc;
1642 }
1643
1644 /*
1645 * yaffs_search_end() disposes of a search context and cleans up.
1646 */
1647 static void yaffs_search_end(struct yaffs_search_context *sc)
1648 {
1649 if (sc) {
1650 list_del(&sc->others);
1651 kfree(sc);
1652 }
1653 }
1654
1655 /*
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.
1659 */
1660 static void yaffs_search_advance(struct yaffs_search_context *sc)
1661 {
1662 if (!sc)
1663 return;
1664
1665 if (sc->next_return == NULL ||
1666 list_empty(&sc->dir_obj->variant.dir_variant.children))
1667 sc->next_return = NULL;
1668 else {
1669 struct list_head *next = sc->next_return->siblings.next;
1670
1671 if (next == &sc->dir_obj->variant.dir_variant.children)
1672 sc->next_return = NULL; /* end of list */
1673 else
1674 sc->next_return =
1675 list_entry(next, struct yaffs_obj, siblings);
1676 }
1677 }
1678
1679 /*
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.
1683 */
1684 static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
1685 {
1686
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);
1691
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.
1695 */
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);
1700 }
1701
1702 }
1703
1704
1705 /*-----------------------------------------------------------------*/
1706
1707 #ifdef YAFFS_USE_DIR_ITERATE
1708 static int yaffs_iterate(struct file *f, struct dir_context *dc)
1709 {
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;
1715 int ret_val = 0;
1716
1717 char name[YAFFS_MAX_NAME_LENGTH + 1];
1718
1719 obj = yaffs_dentry_to_obj(f->f_dentry);
1720 dev = obj->my_dev;
1721
1722 yaffs_gross_lock(dev);
1723
1724 yaffs_dev_to_lc(dev)->readdir_process = current;
1725
1726 sc = yaffs_new_search(obj);
1727 if (!sc) {
1728 ret_val = -ENOMEM;
1729 goto out;
1730 }
1731
1732 if (!dir_emit_dots(f, dc))
1733 return 0;
1734
1735 curoffs = 1;
1736
1737 while (sc->next_return) {
1738 curoffs++;
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);
1743
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));
1748
1749 yaffs_gross_unlock(dev);
1750
1751 if (!dir_emit(dc,
1752 name,
1753 strlen(name),
1754 this_inode,
1755 this_type)) {
1756 yaffs_gross_lock(dev);
1757 goto out;
1758 }
1759
1760 yaffs_gross_lock(dev);
1761
1762 dc->pos++;
1763 f->f_pos++;
1764 }
1765 yaffs_search_advance(sc);
1766 }
1767
1768 out:
1769 yaffs_search_end(sc);
1770 yaffs_dev_to_lc(dev)->readdir_process = NULL;
1771 yaffs_gross_unlock(dev);
1772
1773 return ret_val;
1774 }
1775
1776 #else
1777
1778 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
1779 {
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;
1786 int ret_val = 0;
1787
1788 char name[YAFFS_MAX_NAME_LENGTH + 1];
1789
1790 obj = yaffs_dentry_to_obj(f->f_dentry);
1791 dev = obj->my_dev;
1792
1793 yaffs_gross_lock(dev);
1794
1795 yaffs_dev_to_lc(dev)->readdir_process = current;
1796
1797 offset = f->f_pos;
1798
1799 sc = yaffs_new_search(obj);
1800 if (!sc) {
1801 ret_val = -ENOMEM;
1802 goto out;
1803 }
1804
1805 yaffs_trace(YAFFS_TRACE_OS,
1806 "yaffs_readdir: starting at %d", (int)offset);
1807
1808 if (offset == 0) {
1809 yaffs_trace(YAFFS_TRACE_OS,
1810 "yaffs_readdir: entry . ino %d",
1811 (int)inode->i_ino);
1812 yaffs_gross_unlock(dev);
1813 if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) {
1814 yaffs_gross_lock(dev);
1815 goto out;
1816 }
1817 yaffs_gross_lock(dev);
1818 offset++;
1819 f->f_pos++;
1820 }
1821 if (offset == 1) {
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,
1828 DT_DIR) < 0) {
1829 yaffs_gross_lock(dev);
1830 goto out;
1831 }
1832 yaffs_gross_lock(dev);
1833 offset++;
1834 f->f_pos++;
1835 }
1836
1837 curoffs = 1;
1838
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) {
1842 offset = 2;
1843 f->f_pos = offset;
1844 f->f_version = inode->i_version;
1845 }
1846
1847 while (sc->next_return) {
1848 curoffs++;
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);
1853
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));
1858
1859 yaffs_gross_unlock(dev);
1860
1861 if (filldir(dirent,
1862 name,
1863 strlen(name),
1864 offset, this_inode, this_type) < 0) {
1865 yaffs_gross_lock(dev);
1866 goto out;
1867 }
1868
1869 yaffs_gross_lock(dev);
1870
1871 offset++;
1872 f->f_pos++;
1873 }
1874 yaffs_search_advance(sc);
1875 }
1876
1877 out:
1878 yaffs_search_end(sc);
1879 yaffs_dev_to_lc(dev)->readdir_process = NULL;
1880 yaffs_gross_unlock(dev);
1881
1882 return ret_val;
1883 }
1884
1885 #endif
1886
1887 static const struct file_operations yaffs_dir_operations = {
1888 .read = generic_read_dir,
1889 #ifdef YAFFS_USE_DIR_ITERATE
1890 .iterate = yaffs_iterate,
1891 #else
1892 .readdir = yaffs_readdir,
1893 #endif
1894 .fsync = yaffs_sync_object,
1895 .llseek = generic_file_llseek,
1896 };
1897
1898 static void yaffs_fill_inode_from_obj(struct inode *inode,
1899 struct yaffs_obj *obj)
1900 {
1901 if (inode && obj) {
1902
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;
1910 }
1911
1912 break;
1913 case YAFFS_OBJECT_TYPE_SYMLINK:
1914 if (!S_ISLNK(mode)) {
1915 obj->yst_mode &= ~S_IFMT;
1916 obj->yst_mode |= S_IFLNK;
1917 }
1918
1919 break;
1920 case YAFFS_OBJECT_TYPE_DIRECTORY:
1921 if (!S_ISDIR(mode)) {
1922 obj->yst_mode &= ~S_IFMT;
1923 obj->yst_mode |= S_IFDIR;
1924 }
1925
1926 break;
1927 case YAFFS_OBJECT_TYPE_UNKNOWN:
1928 case YAFFS_OBJECT_TYPE_HARDLINK:
1929 case YAFFS_OBJECT_TYPE_SPECIAL:
1930 default:
1931 /* TODO? */
1932 break;
1933 }
1934
1935 inode->i_flags |= S_NOATIME;
1936
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;
1943 #endif
1944 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1945
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;
1953 #else
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;
1958 #endif
1959 inode->i_size = yaffs_get_obj_length(obj);
1960 inode->i_blocks = (inode->i_size + 511) >> 9;
1961
1962 set_nlink(inode, yaffs_get_obj_link_count(obj));
1963
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));
1968
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));
1974 #else
1975 init_special_inode(inode, obj->yst_mode,
1976 (dev_t) (obj->yst_rdev));
1977 #endif
1978 break;
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;
1984 break;
1985 case S_IFDIR: /* directory */
1986 inode->i_op = &yaffs_dir_inode_operations;
1987 inode->i_fop = &yaffs_dir_operations;
1988 break;
1989 case S_IFLNK: /* symlink */
1990 inode->i_op = &yaffs_symlink_inode_operations;
1991 break;
1992 }
1993
1994 yaffs_inode_to_obj_lv(inode) = obj;
1995
1996 obj->my_inode = inode;
1997
1998 } else {
1999 yaffs_trace(YAFFS_TRACE_OS,
2000 "yaffs_fill_inode invalid parameters");
2001 }
2002
2003 }
2004
2005
2006
2007 /*
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.
2012 *
2013 * NB:
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.
2017 */
2018
2019 static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
2020 {
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 */
2025
2026 if (erased_chunks < dev->n_free_chunks)
2027 scattered = (dev->n_free_chunks - erased_chunks);
2028
2029 if (!context->bg_running)
2030 return 0;
2031 else if (scattered < (dev->param.chunks_per_block * 2))
2032 return 0;
2033 else if (erased_chunks > dev->n_free_chunks / 2)
2034 return 0;
2035 else if (erased_chunks > dev->n_free_chunks / 4)
2036 return 1;
2037 else
2038 return 2;
2039 }
2040
2041 #ifdef YAFFS_COMPILE_BACKGROUND
2042
2043 void yaffs_background_waker(unsigned long data)
2044 {
2045 wake_up_process((struct task_struct *)data);
2046 }
2047
2048 static int yaffs_bg_thread_fn(void *data)
2049 {
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;
2057
2058 int gc_result;
2059 struct timer_list timer;
2060
2061 yaffs_trace(YAFFS_TRACE_BACKGROUND,
2062 "yaffs_background starting for dev %p", (void *)dev);
2063
2064 #ifdef YAFFS_COMPILE_FREEZER
2065 set_freezable();
2066 #endif
2067 while (context->bg_running) {
2068 yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background");
2069
2070 if (kthread_should_stop())
2071 break;
2072
2073 #ifdef YAFFS_COMPILE_FREEZER
2074 if (try_to_freeze())
2075 continue;
2076 #endif
2077 yaffs_gross_lock(dev);
2078
2079 now = jiffies;
2080
2081 if (time_after(now, next_dir_update) && yaffs_bg_enable) {
2082 yaffs_update_dirty_dirs(dev);
2083 next_dir_update = now + HZ;
2084 }
2085
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);
2090 if (urgency > 1)
2091 next_gc = now + HZ / 20 + 1;
2092 else if (urgency > 0)
2093 next_gc = now + HZ / 10 + 1;
2094 else
2095 next_gc = now + HZ * 2;
2096 } else {
2097 /*
2098 * gc not running so set to next_dir_update
2099 * to cut down on wake ups
2100 */
2101 next_gc = next_dir_update;
2102 }
2103 }
2104 yaffs_gross_unlock(dev);
2105 #if 1
2106 expires = next_dir_update;
2107 if (time_before(next_gc, expires))
2108 expires = next_gc;
2109 if (time_before(expires, now))
2110 expires = now + HZ;
2111
2112 Y_INIT_TIMER(&timer);
2113 timer.expires = expires + 1;
2114 timer.data = (unsigned long)current;
2115 timer.function = yaffs_background_waker;
2116
2117 set_current_state(TASK_INTERRUPTIBLE);
2118 add_timer(&timer);
2119 schedule();
2120 del_timer_sync(&timer);
2121 #else
2122 msleep(10);
2123 #endif
2124 }
2125
2126 return 0;
2127 }
2128
2129 static int yaffs_bg_start(struct yaffs_dev *dev)
2130 {
2131 int retval = 0;
2132 struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
2133
2134 if (dev->read_only)
2135 return -1;
2136
2137 context->bg_running = 1;
2138
2139 context->bg_thread = kthread_run(yaffs_bg_thread_fn,
2140 (void *)dev, "yaffs-bg-%d",
2141 context->mount_id);
2142
2143 if (IS_ERR(context->bg_thread)) {
2144 retval = PTR_ERR(context->bg_thread);
2145 context->bg_thread = NULL;
2146 context->bg_running = 0;
2147 }
2148 return retval;
2149 }
2150
2151 static void yaffs_bg_stop(struct yaffs_dev *dev)
2152 {
2153 struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev);
2154
2155 ctxt->bg_running = 0;
2156
2157 if (ctxt->bg_thread) {
2158 kthread_stop(ctxt->bg_thread);
2159 ctxt->bg_thread = NULL;
2160 }
2161 }
2162 #else
2163 static int yaffs_bg_thread_fn(void *data)
2164 {
2165 return 0;
2166 }
2167
2168 static int yaffs_bg_start(struct yaffs_dev *dev)
2169 {
2170 return 0;
2171 }
2172
2173 static void yaffs_bg_stop(struct yaffs_dev *dev)
2174 {
2175 }
2176 #endif
2177
2178
2179 static void yaffs_flush_inodes(struct super_block *sb)
2180 {
2181 struct inode *iptr;
2182 struct yaffs_obj *obj;
2183
2184 list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
2185 obj = yaffs_inode_to_obj(iptr);
2186 if (obj) {
2187 yaffs_trace(YAFFS_TRACE_OS,
2188 "flushing obj %d",
2189 obj->obj_id);
2190 yaffs_flush_file(obj, 1, 0);
2191 }
2192 }
2193 }
2194
2195 static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
2196 {
2197 struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2198 if (!dev)
2199 return;
2200
2201 yaffs_flush_inodes(sb);
2202 yaffs_update_dirty_dirs(dev);
2203 yaffs_flush_whole_cache(dev);
2204 if (do_checkpoint)
2205 yaffs_checkpoint_save(dev);
2206 }
2207
2208 static LIST_HEAD(yaffs_context_list);
2209 struct mutex yaffs_context_lock;
2210
2211 static void yaffs_put_super(struct super_block *sb)
2212 {
2213 struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2214 struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
2215
2216 yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
2217 "yaffs_put_super");
2218
2219 yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
2220 "Shutting down yaffs background thread");
2221 yaffs_bg_stop(dev);
2222 yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
2223 "yaffs background thread shut down");
2224
2225 yaffs_gross_lock(dev);
2226
2227 yaffs_flush_super(sb, 1);
2228
2229 yaffs_deinitialise(dev);
2230
2231 yaffs_gross_unlock(dev);
2232
2233 mutex_lock(&yaffs_context_lock);
2234 list_del_init(&(yaffs_dev_to_lc(dev)->context_list));
2235 mutex_unlock(&yaffs_context_lock);
2236
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;
2240 }
2241
2242 kfree(dev);
2243
2244 yaffs_put_mtd_device(mtd);
2245
2246 yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
2247 "yaffs_put_super done");
2248 }
2249
2250
2251 static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev)
2252 {
2253 return yaffs_gc_control;
2254 }
2255
2256
2257 #ifdef YAFFS_COMPILE_EXPORTFS
2258
2259 static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
2260 uint32_t generation)
2261 {
2262 return Y_IGET(sb, ino);
2263 }
2264
2265 static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb,
2266 struct fid *fid, int fh_len,
2267 int fh_type)
2268 {
2269 return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
2270 yaffs2_nfs_get_inode);
2271 }
2272
2273 static struct dentry *yaffs2_fh_to_parent(struct super_block *sb,
2274 struct fid *fid, int fh_len,
2275 int fh_type)
2276 {
2277 return generic_fh_to_parent(sb, fid, fh_len, fh_type,
2278 yaffs2_nfs_get_inode);
2279 }
2280
2281 struct dentry *yaffs2_get_parent(struct dentry *dentry)
2282 {
2283
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;
2290
2291 d_obj = yaffs_inode_to_obj(dentry->d_inode);
2292
2293 if (d_obj) {
2294 parent_obj = d_obj->parent;
2295 if (parent_obj) {
2296 parent_ino = yaffs_get_obj_inode(parent_obj);
2297 inode = Y_IGET(sb, parent_ino);
2298
2299 if (IS_ERR(inode)) {
2300 parent = ERR_CAST(inode);
2301 } else {
2302 parent = d_obtain_alias(inode);
2303 if (!IS_ERR(parent)) {
2304 parent = ERR_PTR(-ENOMEM);
2305 iput(inode);
2306 }
2307 }
2308 }
2309 }
2310
2311 return parent;
2312 }
2313
2314 /* Just declare a zero structure as a NULL value implies
2315 * using the default functions of exportfs.
2316 */
2317
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,
2322 };
2323
2324 #endif
2325
2326 static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj)
2327 {
2328 /* Clear the association between the inode and
2329 * the struct yaffs_obj.
2330 */
2331 obj->my_inode = NULL;
2332 yaffs_inode_to_obj_lv(inode) = NULL;
2333
2334 /* If the object freeing was deferred, then the real
2335 * free happens now.
2336 * This should fix the inode inconsistency problem.
2337 */
2338 yaffs_handle_defered_free(obj);
2339 }
2340
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()
2344 *
2345 */
2346 static void yaffs_evict_inode(struct inode *inode)
2347 {
2348 struct yaffs_obj *obj;
2349 struct yaffs_dev *dev;
2350 int deleteme = 0;
2351
2352 obj = yaffs_inode_to_obj(inode);
2353
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");
2358
2359 if (!inode->i_nlink && !is_bad_inode(inode))
2360 deleteme = 1;
2361 truncate_inode_pages(&inode->i_data, 0);
2362 Y_CLEAR_INODE(inode);
2363
2364 if (deleteme && obj) {
2365 dev = obj->my_dev;
2366 yaffs_gross_lock(dev);
2367 yaffs_del_obj(obj);
2368 yaffs_gross_unlock(dev);
2369 }
2370 if (obj) {
2371 dev = obj->my_dev;
2372 yaffs_gross_lock(dev);
2373 yaffs_unstitch_obj(inode, obj);
2374 yaffs_gross_unlock(dev);
2375 }
2376 }
2377 #else
2378
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
2382 * the chain
2383 * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
2384 */
2385
2386 static void yaffs_clear_inode(struct inode *inode)
2387 {
2388 struct yaffs_obj *obj;
2389 struct yaffs_dev *dev;
2390
2391 obj = yaffs_inode_to_obj(inode);
2392
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");
2397
2398 if (obj) {
2399 dev = obj->my_dev;
2400 yaffs_gross_lock(dev);
2401 yaffs_unstitch_obj(inode, obj);
2402 yaffs_gross_unlock(dev);
2403 }
2404
2405 }
2406
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
2409 * delete the file).
2410 * NB Must call clear_inode()
2411 */
2412 static void yaffs_delete_inode(struct inode *inode)
2413 {
2414 struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
2415 struct yaffs_dev *dev;
2416
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");
2421
2422 if (obj) {
2423 dev = obj->my_dev;
2424 yaffs_gross_lock(dev);
2425 yaffs_del_obj(obj);
2426 yaffs_gross_unlock(dev);
2427 }
2428 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
2429 truncate_inode_pages(&inode->i_data, 0);
2430 #endif
2431 clear_inode(inode);
2432 }
2433 #endif
2434
2435
2436
2437
2438 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2439 static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
2440 {
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)
2445 {
2446 struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2447 #else
2448 static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
2449 {
2450 struct yaffs_dev *dev = yaffs_super_to_dev(sb);
2451 #endif
2452
2453 yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs");
2454
2455 yaffs_gross_lock(dev);
2456
2457 buf->f_type = YAFFS_MAGIC;
2458 buf->f_bsize = sb->s_blocksize;
2459 buf->f_namelen = 255;
2460
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 */
2463
2464 uint64_t bytes_in_dev;
2465 uint64_t bytes_free;
2466
2467 bytes_in_dev =
2468 ((uint64_t)
2469 ((dev->param.end_block - dev->param.start_block +
2470 1))) * ((uint64_t) (dev->param.chunks_per_block *
2471 dev->data_bytes_per_chunk));
2472
2473 do_div(bytes_in_dev, sb->s_blocksize); /* bytes_in_dev becomes the number of blocks */
2474 buf->f_blocks = bytes_in_dev;
2475
2476 bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) *
2477 ((uint64_t) (dev->data_bytes_per_chunk));
2478
2479 do_div(bytes_free, sb->s_blocksize);
2480
2481 buf->f_bfree = bytes_free;
2482
2483 } else if (sb->s_blocksize > dev->data_bytes_per_chunk) {
2484
2485 buf->f_blocks =
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);
2489 buf->f_bfree =
2490 yaffs_get_n_free_chunks(dev) /
2491 (sb->s_blocksize / dev->data_bytes_per_chunk);
2492 } else {
2493 buf->f_blocks =
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);
2497
2498 buf->f_bfree =
2499 yaffs_get_n_free_chunks(dev) *
2500 (dev->data_bytes_per_chunk / sb->s_blocksize);
2501 }
2502
2503 buf->f_files = 0;
2504 buf->f_ffree = 0;
2505 buf->f_bavail = buf->f_bfree;
2506
2507 yaffs_gross_unlock(dev);
2508 return 0;
2509 }
2510
2511
2512
2513 static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
2514 {
2515
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);
2519 int do_checkpoint;
2520 int dirty = yaffs_check_super_dirty(dev);
2521
2522 yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
2523 "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
2524 gc_urgent,
2525 dirty ? "dirty" : "clean",
2526 request_checkpoint ? "checkpoint requested" : "no checkpoint",
2527 oneshot_checkpoint ? " one-shot" : "");
2528
2529 yaffs_gross_lock(dev);
2530 do_checkpoint = ((request_checkpoint && !gc_urgent) ||
2531 oneshot_checkpoint) && !dev->is_checkpointed;
2532
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;
2538 }
2539 yaffs_gross_unlock(dev);
2540
2541 return 0;
2542 }
2543
2544
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)
2548 #else
2549 static int yaffs_write_super(struct super_block *sb)
2550 #endif
2551 {
2552 unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
2553
2554 yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
2555 "yaffs_write_super %s",
2556 request_checkpoint ? " checkpt" : "");
2557
2558 yaffs_do_sync_fs(sb, request_checkpoint);
2559
2560 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
2561 return 0;
2562 #endif
2563 }
2564 #endif
2565
2566 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2567 static int yaffs_sync_fs(struct super_block *sb, int wait)
2568 #else
2569 static int yaffs_sync_fs(struct super_block *sb)
2570 #endif
2571 {
2572 unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1);
2573
2574 yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
2575 "yaffs_sync_fs%s", request_checkpoint ? " checkpt" : "");
2576
2577 yaffs_do_sync_fs(sb, request_checkpoint);
2578
2579 return 0;
2580 }
2581
2582
2583
2584 static const struct super_operations yaffs_super_ops = {
2585 .statfs = yaffs_statfs,
2586
2587 #ifndef YAFFS_USE_OWN_IGET
2588 .read_inode = yaffs_read_inode,
2589 #endif
2590 #ifdef YAFFS_HAS_PUT_INODE
2591 .put_inode = yaffs_put_inode,
2592 #endif
2593 .put_super = yaffs_put_super,
2594 #ifdef YAFFS_HAS_EVICT_INODE
2595 .evict_inode = yaffs_evict_inode,
2596 #else
2597 .delete_inode = yaffs_delete_inode,
2598 .clear_inode = yaffs_clear_inode,
2599 #endif
2600 .sync_fs = yaffs_sync_fs,
2601 #ifdef YAFFS_HAS_WRITE_SUPER
2602 .write_super = yaffs_write_super,
2603 #endif
2604 };
2605
2606 struct yaffs_options {
2607 int inband_tags;
2608 int skip_checkpoint_read;
2609 int skip_checkpoint_write;
2610 int no_cache;
2611 int tags_ecc_on;
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;
2618 };
2619
2620 #define MAX_OPT_LEN 30
2621 static int yaffs_parse_options(struct yaffs_options *options,
2622 const char *options_str)
2623 {
2624 char cur_opt[MAX_OPT_LEN + 1];
2625 int p;
2626 int error = 0;
2627
2628 /* Parse through the options which is a comma seperated list */
2629
2630 while (options_str && *options_str && !error) {
2631 memset(cur_opt, 0, MAX_OPT_LEN + 1);
2632 p = 0;
2633
2634 while (*options_str == ',')
2635 options_str++;
2636
2637 while (*options_str && *options_str != ',') {
2638 if (p < MAX_OPT_LEN) {
2639 cur_opt[p] = *options_str;
2640 p++;
2641 }
2642 options_str++;
2643 }
2644
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;
2676 } else {
2677 printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",
2678 cur_opt);
2679 error = 1;
2680 }
2681 }
2682
2683 return error;
2684 }
2685
2686
2687 static struct dentry *yaffs_make_root(struct inode *inode)
2688 {
2689 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
2690 struct dentry *root = d_alloc_root(inode);
2691
2692 if (!root)
2693 iput(inode);
2694
2695 return root;
2696 #else
2697 return d_make_root(inode);
2698 #endif
2699 }
2700
2701
2702
2703
2704 static struct super_block *yaffs_internal_read_super(int yaffs_version,
2705 struct super_block *sb,
2706 void *data, int silent)
2707 {
2708 int n_blocks;
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;
2714 int err;
2715 char *data_str = (char *)data;
2716 struct yaffs_linux_context *context = NULL;
2717 struct yaffs_param *param;
2718
2719 int read_only = 0;
2720 int inband_tags = 0;
2721
2722 struct yaffs_options options;
2723
2724 unsigned mount_id;
2725 int found;
2726 struct yaffs_linux_context *context_iterator;
2727 struct list_head *l;
2728
2729 if (!sb) {
2730 printk(KERN_INFO "yaffs: sb is NULL\n");
2731 return NULL;
2732 }
2733
2734 sb->s_magic = YAFFS_MAGIC;
2735 sb->s_op = &yaffs_super_ops;
2736 sb->s_flags |= MS_NOATIME;
2737
2738 read_only = ((sb->s_flags & MS_RDONLY) != 0);
2739
2740 #ifdef YAFFS_COMPILE_EXPORTFS
2741 sb->s_export_op = &yaffs_export_ops;
2742 #endif
2743
2744 if (!sb->s_dev)
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");
2748 else
2749 printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
2750 sb->s_dev,
2751 yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw");
2752
2753 if (!data_str)
2754 data_str = "";
2755
2756 printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str);
2757
2758 memset(&options, 0, sizeof(options));
2759
2760 if (yaffs_parse_options(&options, data_str)) {
2761 /* Option parsing failed */
2762 return NULL;
2763 }
2764
2765 sb->s_blocksize = PAGE_CACHE_SIZE;
2766 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
2767
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));
2772
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));
2777
2778 /* Get the device */
2779 mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
2780 if (IS_ERR(mtd)) {
2781 yaffs_trace(YAFFS_TRACE_ALWAYS,
2782 "yaffs: MTD device %u either not valid or unavailable",
2783 MINOR(sb->s_dev));
2784 return NULL;
2785 }
2786
2787 if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
2788 yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
2789 yaffs_version = 2;
2790 }
2791
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");
2796 yaffs_version = 1;
2797 }
2798
2799 if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) ||
2800 options.inband_tags)
2801 inband_tags = 1;
2802
2803 if(yaffs_verify_mtd(mtd, yaffs_version, inband_tags) < 0)
2804 return NULL;
2805
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
2809 */
2810
2811 if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
2812 read_only = 1;
2813 printk(KERN_INFO
2814 "yaffs: mtd is read only, setting superblock read only\n"
2815 );
2816 sb->s_flags |= MS_RDONLY;
2817 }
2818
2819 dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL);
2820 context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
2821
2822 if (!dev || !context) {
2823 kfree(dev);
2824 kfree(context);
2825 dev = NULL;
2826 context = NULL;
2827
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."
2831 );
2832 return NULL;
2833 }
2834 memset(dev, 0, sizeof(struct yaffs_dev));
2835 param = &(dev->param);
2836
2837 memset(context, 0, sizeof(struct yaffs_linux_context));
2838 dev->os_context = context;
2839 INIT_LIST_HEAD(&(context->context_list));
2840 context->dev = dev;
2841 context->super = sb;
2842
2843 dev->read_only = read_only;
2844
2845 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2846 sb->s_fs_info = dev;
2847 #else
2848 sb->u.generic_sbp = dev;
2849 #endif
2850
2851
2852 dev->driver_context = mtd;
2853 param->name = mtd->name;
2854
2855 /* Set up the memory size parameters.... */
2856
2857
2858 param->n_reserved_blocks = 5;
2859 param->n_caches = (options.no_cache) ? 0 : 10;
2860 param->inband_tags = inband_tags;
2861
2862 param->enable_xattr = 1;
2863 if (options.lazy_loading_overridden)
2864 param->disable_lazy_load = !options.lazy_loading_enabled;
2865
2866 param->defered_dir_update = 1;
2867
2868 if (options.tags_ecc_overridden)
2869 param->no_tags_ecc = !options.tags_ecc_on;
2870
2871 param->empty_lost_n_found = 1;
2872 param->refresh_period = 500;
2873 param->disable_summary = options.disable_summary;
2874
2875
2876 #ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING
2877 param->disable_bad_block_marking = 1;
2878 #endif
2879 if (options.empty_lost_and_found_overridden)
2880 param->empty_lost_n_found = options.empty_lost_and_found;
2881
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;
2888 #else
2889 param->total_bytes_per_chunk = mtd->oobblock;
2890 param->chunks_per_block = mtd->erasesize / mtd->oobblock;
2891 #endif
2892 n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize);
2893
2894 param->start_block = 0;
2895 param->end_block = n_blocks - 1;
2896 } else {
2897 param->is_yaffs2 = 0;
2898 n_blocks = YCALCBLOCKS(mtd->size,
2899 YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
2900
2901 param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
2902 param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
2903 }
2904
2905 param->start_block = 0;
2906 param->end_block = n_blocks - 1;
2907
2908 yaffs_mtd_drv_install(dev);
2909
2910 param->sb_dirty_fn = yaffs_set_super_dirty;
2911 param->gc_control_fn = yaffs_gc_control_callback;
2912
2913 yaffs_dev_to_lc(dev)->super = sb;
2914
2915 param->use_nand_ecc = 1;
2916
2917 param->skip_checkpt_rd = options.skip_checkpoint_read;
2918 param->skip_checkpt_wr = options.skip_checkpoint_write;
2919
2920 mutex_lock(&yaffs_context_lock);
2921 /* Get a mount id */
2922 found = 0;
2923 for (mount_id = 0; !found; mount_id++) {
2924 found = 1;
2925 list_for_each(l, &yaffs_context_list) {
2926 context_iterator =
2927 list_entry(l, struct yaffs_linux_context,
2928 context_list);
2929 if (context_iterator->mount_id == mount_id)
2930 found = 0;
2931 }
2932 }
2933 context->mount_id = mount_id;
2934
2935 list_add_tail(&(yaffs_dev_to_lc(dev)->context_list),
2936 &yaffs_context_list);
2937 mutex_unlock(&yaffs_context_lock);
2938
2939 /* Directory search handling... */
2940 INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts));
2941 param->remove_obj_fn = yaffs_remove_obj_callback;
2942
2943 mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock));
2944
2945 yaffs_gross_lock(dev);
2946
2947 err = yaffs_guts_initialise(dev);
2948
2949 yaffs_trace(YAFFS_TRACE_OS,
2950 "yaffs_read_super: guts initialised %s",
2951 (err == YAFFS_OK) ? "OK" : "FAILED");
2952
2953 if (err == YAFFS_OK)
2954 yaffs_bg_start(dev);
2955
2956 if (!context->bg_thread)
2957 param->defered_dir_update = 0;
2958
2959 sb->s_maxbytes = yaffs_max_file_size(dev);
2960
2961 /* Release lock before yaffs_get_inode() */
2962 yaffs_gross_unlock(dev);
2963
2964 /* Create root inode */
2965 if (err == YAFFS_OK)
2966 inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev));
2967
2968 if (!inode)
2969 return NULL;
2970
2971 inode->i_op = &yaffs_dir_inode_operations;
2972 inode->i_fop = &yaffs_dir_operations;
2973
2974 yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: got root inode");
2975
2976 root = yaffs_make_root(inode);
2977
2978 if (!root)
2979 return NULL;
2980
2981 sb->s_root = root;
2982 if(!dev->is_checkpointed)
2983 yaffs_set_super_dirty(dev);
2984
2985 yaffs_trace(YAFFS_TRACE_ALWAYS,
2986 "yaffs_read_super: is_checkpointed %d",
2987 dev->is_checkpointed);
2988
2989 yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done");
2990 return sb;
2991 }
2992
2993 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2994 static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
2995 int silent)
2996 {
2997 return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
2998 }
2999
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)
3003 {
3004 return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd);
3005 }
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)
3010 {
3011
3012 return get_sb_bdev(fs, flags, dev_name, data,
3013 yaffs_internal_read_super_mtd, mnt);
3014 }
3015 #else
3016 static struct super_block *yaffs_read_super(struct file_system_type *fs,
3017 int flags, const char *dev_name,
3018 void *data)
3019 {
3020
3021 return get_sb_bdev(fs, flags, dev_name, data,
3022 yaffs_internal_read_super_mtd);
3023 }
3024 #endif
3025
3026 static struct file_system_type yaffs_fs_type = {
3027 .owner = THIS_MODULE,
3028 .name = "yaffs",
3029 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
3030 .mount = yaffs_mount,
3031 #else
3032 .get_sb = yaffs_read_super,
3033 #endif
3034 .kill_sb = kill_block_super,
3035 .fs_flags = FS_REQUIRES_DEV,
3036 };
3037 #else
3038 static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
3039 int silent)
3040 {
3041 return yaffs_internal_read_super(1, sb, data, silent);
3042 }
3043
3044 static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
3045 FS_REQUIRES_DEV);
3046 #endif
3047
3048
3049 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
3050 static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
3051 int silent)
3052 {
3053 return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
3054 }
3055
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)
3059 {
3060 return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd);
3061 }
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)
3066 {
3067 return get_sb_bdev(fs, flags, dev_name, data,
3068 yaffs2_internal_read_super_mtd, mnt);
3069 }
3070 #else
3071 static struct super_block *yaffs2_read_super(struct file_system_type *fs,
3072 int flags, const char *dev_name,
3073 void *data)
3074 {
3075
3076 return get_sb_bdev(fs, flags, dev_name, data,
3077 yaffs2_internal_read_super_mtd);
3078 }
3079 #endif
3080
3081 static struct file_system_type yaffs2_fs_type = {
3082 .owner = THIS_MODULE,
3083 .name = "yaffs2",
3084 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
3085 .mount = yaffs2_mount,
3086 #else
3087 .get_sb = yaffs2_read_super,
3088 #endif
3089 .kill_sb = kill_block_super,
3090 .fs_flags = FS_REQUIRES_DEV,
3091 };
3092 #else
3093 static struct super_block *yaffs2_read_super(struct super_block *sb,
3094 void *data, int silent)
3095 {
3096 return yaffs_internal_read_super(2, sb, data, silent);
3097 }
3098
3099 static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
3100 FS_REQUIRES_DEV);
3101 #endif
3102
3103
3104 static struct proc_dir_entry *my_proc_entry;
3105
3106 static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
3107 {
3108 struct yaffs_param *param = &dev->param;
3109 int bs[10];
3110
3111 yaffs_count_blocks_by_state(dev,bs);
3112
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]);
3140
3141 return buf;
3142 }
3143
3144 static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
3145 {
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);
3189
3190 return buf;
3191 }
3192
3193 static int yaffs_proc_read(char *page,
3194 char **start,
3195 off_t offset, int count, int *eof, void *data)
3196 {
3197 struct list_head *item;
3198 char *buf = page;
3199 int step = offset;
3200 int n = 0;
3201
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.
3206 */
3207
3208 *(int *)start = 1;
3209
3210 /* Print header first */
3211 if (step == 0)
3212 buf +=
3213 sprintf(buf,
3214 "Multi-version YAFFS built:" __DATE__ " " __TIME__
3215 "\n");
3216 else if (step == 1)
3217 buf += sprintf(buf, "\n");
3218 else {
3219 step -= 2;
3220
3221 mutex_lock(&yaffs_context_lock);
3222
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,
3227 context_list);
3228 struct yaffs_dev *dev = dc->dev;
3229
3230 if (n < (step & ~1)) {
3231 n += 2;
3232 continue;
3233 }
3234 if ((step & 1) == 0) {
3235 buf +=
3236 sprintf(buf, "\nDevice %d \"%s\"\n", n,
3237 dev->param.name);
3238 buf = yaffs_dump_dev_part0(buf, dev);
3239 } else {
3240 buf = yaffs_dump_dev_part1(buf, dev);
3241 }
3242
3243 break;
3244 }
3245 mutex_unlock(&yaffs_context_lock);
3246 }
3247
3248 return buf - page < count ? buf - page : count;
3249 }
3250
3251 /**
3252 * Set the verbosity of the warnings and error messages.
3253 *
3254 * Note that the names can only be a..z or _ with the current code.
3255 */
3256
3257 static struct {
3258 char *mask_name;
3259 unsigned mask_bitfield;
3260 } mask_flags[] = {
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},
3288 {"none", 0},
3289 {NULL, 0},
3290 };
3291
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)
3295 {
3296 unsigned rg = 0, mask_bitfield;
3297 char *end;
3298 char *mask_name;
3299 const char *x;
3300 char substring[MAX_MASK_NAME_LENGTH + 1];
3301 int i;
3302 int done = 0;
3303 int add, len = 0;
3304 int pos = 0;
3305
3306 rg = yaffs_trace_mask;
3307
3308 while (!done && (pos < count)) {
3309 done = 1;
3310 while ((pos < count) && isspace(buf[pos]))
3311 pos++;
3312
3313 switch (buf[pos]) {
3314 case '+':
3315 case '-':
3316 case '=':
3317 add = buf[pos];
3318 pos++;
3319 break;
3320
3321 default:
3322 add = ' ';
3323 break;
3324 }
3325 mask_name = NULL;
3326
3327 mask_bitfield = simple_strtoul(buf + pos, &end, 0);
3328
3329 if (end > buf + pos) {
3330 mask_name = "numeral";
3331 len = end - (buf + pos);
3332 pos += len;
3333 done = 0;
3334 } else {
3335 for (x = buf + pos, i = 0;
3336 (*x == '_' || (*x >= 'a' && *x <= 'z')) &&
3337 i < MAX_MASK_NAME_LENGTH; x++, i++, pos++)
3338 substring[i] = *x;
3339 substring[i] = '\0';
3340
3341 for (i = 0; mask_flags[i].mask_name != NULL; i++) {
3342 if (strcmp(substring, mask_flags[i].mask_name)
3343 == 0) {
3344 mask_name = mask_flags[i].mask_name;
3345 mask_bitfield =
3346 mask_flags[i].mask_bitfield;
3347 done = 0;
3348 break;
3349 }
3350 }
3351 }
3352
3353 if (mask_name != NULL) {
3354 done = 0;
3355 switch (add) {
3356 case '-':
3357 rg &= ~mask_bitfield;
3358 break;
3359 case '+':
3360 rg |= mask_bitfield;
3361 break;
3362 case '=':
3363 rg = mask_bitfield;
3364 break;
3365 default:
3366 rg |= mask_bitfield;
3367 break;
3368 }
3369 }
3370 }
3371
3372 yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS;
3373
3374 printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask);
3375
3376 if (rg & YAFFS_TRACE_ALWAYS) {
3377 for (i = 0; mask_flags[i].mask_name != NULL; i++) {
3378 char flag;
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);
3383 }
3384 }
3385
3386 return count;
3387 }
3388
3389 /* Debug strings are of the form:
3390 * .bnnn print info on block n
3391 * .cobjn,chunkn print nand chunk id for objn:chunkn
3392 */
3393
3394 static int yaffs_proc_debug_write(struct file *file, const char *buf,
3395 unsigned long count)
3396 {
3397
3398 char str[100];
3399 char *p0;
3400 char *p1;
3401 long p1_val;
3402 long p0_val;
3403 char cmd;
3404 struct list_head *item;
3405
3406 memset(str, 0, sizeof(str));
3407 memcpy(str, buf, min((size_t)count, sizeof(str) -1));
3408
3409 cmd = str[1];
3410
3411 p0 = str + 2;
3412
3413 p1 = p0;
3414
3415 while (*p1 && *p1 != ',') {
3416 p1++;
3417 }
3418 *p1 = '\0';
3419 p1++;
3420
3421 p0_val = simple_strtol(p0, NULL, 0);
3422 p1_val = simple_strtol(p1, NULL, 0);
3423
3424
3425 mutex_lock(&yaffs_context_lock);
3426
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,
3431 context_list);
3432 struct yaffs_dev *dev = dc->dev;
3433
3434 if (cmd == 'b') {
3435 struct yaffs_block_info *bi;
3436
3437 bi = yaffs_get_block_info(dev,p0_val);
3438
3439 if(bi) {
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,
3443 bi->seq_number);
3444 }
3445 } else if (cmd == 'c') {
3446 struct yaffs_obj *obj;
3447 int nand_chunk;
3448
3449 obj = yaffs_find_by_number(dev, p0_val);
3450 if (!obj)
3451 printk("No obj %d\n", (int)p0_val);
3452 else {
3453 if(p1_val == 0)
3454 nand_chunk = obj->hdr_chunk;
3455 else
3456 nand_chunk =
3457 yaffs_find_chunk_in_file(obj,
3458 p1_val, NULL);
3459 printk("Nand chunk for %d:%d is %d\n",
3460 (int)p0_val, (int)p1_val, nand_chunk);
3461 }
3462 }
3463 }
3464
3465 mutex_unlock(&yaffs_context_lock);
3466
3467 return count;
3468 }
3469
3470
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)
3474 #else
3475 static ssize_t yaffs_proc_write(struct file *file, const char __user *buf,
3476 size_t count, loff_t *ppos)
3477 #endif
3478 {
3479 if (buf[0] == '.')
3480 return yaffs_proc_debug_write(file, buf, count);
3481 return yaffs_proc_write_trace_options(file, buf, count);
3482 }
3483
3484 /* Stuff to handle installation of file systems */
3485 struct file_system_to_install {
3486 struct file_system_type *fst;
3487 int installed;
3488 };
3489
3490 static struct file_system_to_install fs_to_install[] = {
3491 {&yaffs_fs_type, 0},
3492 {&yaffs2_fs_type, 0},
3493 {NULL, 0}
3494 };
3495
3496
3497 #ifdef YAFFS_NEW_PROCFS
3498 static int yaffs_proc_show(struct seq_file *m, void *v)
3499 {
3500 /* FIXME: Unify in a better way? */
3501 char buffer[512];
3502 char *start;
3503 int len;
3504
3505 len = yaffs_proc_read(buffer, &start, 0, sizeof(buffer), NULL, NULL);
3506 seq_puts(m, buffer);
3507 return 0;
3508 }
3509
3510 static int yaffs_proc_open(struct inode *inode, struct file *file)
3511 {
3512 return single_open(file, yaffs_proc_show, NULL);
3513 }
3514
3515 static struct file_operations procfs_ops = {
3516 .owner = THIS_MODULE,
3517 .open = yaffs_proc_open,
3518 .read = seq_read,
3519 .write = yaffs_proc_write,
3520 };
3521
3522 static int yaffs_procfs_init(void)
3523 {
3524 /* Install the proc_fs entries */
3525 my_proc_entry = proc_create("yaffs",
3526 S_IRUGO | S_IFREG,
3527 YPROC_ROOT,
3528 &procfs_ops);
3529
3530 if (my_proc_entry) {
3531 return 0;
3532 } else {
3533 return -ENOMEM;
3534 }
3535 }
3536
3537 #else
3538
3539
3540 static int yaffs_procfs_init(void)
3541 {
3542 /* Install the proc_fs entries */
3543 my_proc_entry = create_proc_entry("yaffs",
3544 S_IRUGO | S_IFREG, YPROC_ROOT);
3545
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;
3550 return 0;
3551 } else {
3552 return -ENOMEM;
3553 }
3554 }
3555
3556 #endif
3557
3558
3559 static int __init init_yaffs_fs(void)
3560 {
3561 int error = 0;
3562 struct file_system_to_install *fsinst;
3563
3564 yaffs_trace(YAFFS_TRACE_ALWAYS,
3565 "yaffs built " __DATE__ " " __TIME__ " Installing.");
3566
3567 mutex_init(&yaffs_context_lock);
3568
3569 error = yaffs_procfs_init();
3570 if (error)
3571 return error;
3572
3573 /* Now add the file system entries */
3574
3575 fsinst = fs_to_install;
3576
3577 while (fsinst->fst && !error) {
3578 error = register_filesystem(fsinst->fst);
3579 if (!error)
3580 fsinst->installed = 1;
3581 fsinst++;
3582 }
3583
3584 /* Any errors? uninstall */
3585 if (error) {
3586 fsinst = fs_to_install;
3587
3588 while (fsinst->fst) {
3589 if (fsinst->installed) {
3590 unregister_filesystem(fsinst->fst);
3591 fsinst->installed = 0;
3592 }
3593 fsinst++;
3594 }
3595 }
3596
3597 return error;
3598 }
3599
3600 static void __exit exit_yaffs_fs(void)
3601 {
3602
3603 struct file_system_to_install *fsinst;
3604
3605 yaffs_trace(YAFFS_TRACE_ALWAYS,
3606 "yaffs built " __DATE__ " " __TIME__ " removing.");
3607
3608 remove_proc_entry("yaffs", YPROC_ROOT);
3609
3610 fsinst = fs_to_install;
3611
3612 while (fsinst->fst) {
3613 if (fsinst->installed) {
3614 unregister_filesystem(fsinst->fst);
3615 fsinst->installed = 0;
3616 }
3617 fsinst++;
3618 }
3619 }
3620
3621 module_init(init_yaffs_fs)
3622 module_exit(exit_yaffs_fs)
3623
3624 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
3625 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
3626 MODULE_LICENSE("GPL");