linux/generic: refresh 2.6.36 kernel patches
[openwrt/svn-archive/archive.git] / target / linux / generic / patches-2.6.36 / 511-yaffs-git-2010-10-01.patch
1 --- a/fs/yaffs2/devextras.h
2 +++ b/fs/yaffs2/devextras.h
3 @@ -1,7 +1,7 @@
4 /*
5 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
6 *
7 - * Copyright (C) 2002-2007 Aleph One Ltd.
8 + * Copyright (C) 2002-2010 Aleph One Ltd.
9 * for Toby Churchill Ltd and Brightstar Engineering
10 *
11 * Created by Charles Manning <charles@aleph1.co.uk>
12 @@ -24,6 +24,8 @@
13 #define __EXTRAS_H__
14
15
16 +#include "yportenv.h"
17 +
18 #if !(defined __KERNEL__)
19
20 /* Definition of types */
21 @@ -33,103 +35,6 @@ typedef unsigned __u32;
22
23 #endif
24
25 -/*
26 - * This is a simple doubly linked list implementation that matches the
27 - * way the Linux kernel doubly linked list implementation works.
28 - */
29 -
30 -struct ylist_head {
31 - struct ylist_head *next; /* next in chain */
32 - struct ylist_head *prev; /* previous in chain */
33 -};
34 -
35 -
36 -/* Initialise a static list */
37 -#define YLIST_HEAD(name) \
38 -struct ylist_head name = { &(name), &(name)}
39 -
40 -
41 -
42 -/* Initialise a list head to an empty list */
43 -#define YINIT_LIST_HEAD(p) \
44 -do { \
45 - (p)->next = (p);\
46 - (p)->prev = (p); \
47 -} while (0)
48 -
49 -
50 -/* Add an element to a list */
51 -static __inline__ void ylist_add(struct ylist_head *newEntry,
52 - struct ylist_head *list)
53 -{
54 - struct ylist_head *listNext = list->next;
55 -
56 - list->next = newEntry;
57 - newEntry->prev = list;
58 - newEntry->next = listNext;
59 - listNext->prev = newEntry;
60 -
61 -}
62 -
63 -static __inline__ void ylist_add_tail(struct ylist_head *newEntry,
64 - struct ylist_head *list)
65 -{
66 - struct ylist_head *listPrev = list->prev;
67 -
68 - list->prev = newEntry;
69 - newEntry->next = list;
70 - newEntry->prev = listPrev;
71 - listPrev->next = newEntry;
72 -
73 -}
74 -
75 -
76 -/* Take an element out of its current list, with or without
77 - * reinitialising the links.of the entry*/
78 -static __inline__ void ylist_del(struct ylist_head *entry)
79 -{
80 - struct ylist_head *listNext = entry->next;
81 - struct ylist_head *listPrev = entry->prev;
82 -
83 - listNext->prev = listPrev;
84 - listPrev->next = listNext;
85 -
86 -}
87 -
88 -static __inline__ void ylist_del_init(struct ylist_head *entry)
89 -{
90 - ylist_del(entry);
91 - entry->next = entry->prev = entry;
92 -}
93 -
94 -
95 -/* Test if the list is empty */
96 -static __inline__ int ylist_empty(struct ylist_head *entry)
97 -{
98 - return (entry->next == entry);
99 -}
100 -
101 -
102 -/* ylist_entry takes a pointer to a list entry and offsets it to that
103 - * we can find a pointer to the object it is embedded in.
104 - */
105 -
106 -
107 -#define ylist_entry(entry, type, member) \
108 - ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
109 -
110 -
111 -/* ylist_for_each and list_for_each_safe iterate over lists.
112 - * ylist_for_each_safe uses temporary storage to make the list delete safe
113 - */
114 -
115 -#define ylist_for_each(itervar, list) \
116 - for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
117 -
118 -#define ylist_for_each_safe(itervar, saveVar, list) \
119 - for (itervar = (list)->next, saveVar = (list)->next->next; \
120 - itervar != (list); itervar = saveVar, saveVar = saveVar->next)
121 -
122
123 #if !(defined __KERNEL__)
124
125 --- a/fs/yaffs2/Kconfig
126 +++ b/fs/yaffs2/Kconfig
127 @@ -90,23 +90,15 @@ config YAFFS_AUTO_YAFFS2
128
129 If unsure, say Y.
130
131 -config YAFFS_DISABLE_LAZY_LOAD
132 - bool "Disable lazy loading"
133 - depends on YAFFS_YAFFS2
134 +config YAFFS_DISABLE_TAGS_ECC
135 + bool "Disable YAFFS from doing ECC on tags by default"
136 + depends on YAFFS_FS && YAFFS_YAFFS2
137 default n
138 help
139 - "Lazy loading" defers loading file details until they are
140 - required. This saves mount time, but makes the first look-up
141 - a bit longer.
142 -
143 - Lazy loading will only happen if enabled by this option being 'n'
144 - and if the appropriate tags are available, else yaffs2 will
145 - automatically fall back to immediate loading and do the right
146 - thing.
147 -
148 - Lazy laoding will be required by checkpointing.
149 -
150 - Setting this to 'y' will disable lazy loading.
151 + This defaults Yaffs to using its own ECC calculations on tags instead of
152 + just relying on the MTD.
153 + This behavior can also be overridden with tags_ecc_on and
154 + tags_ecc_off mount options.
155
156 If unsure, say N.
157
158 @@ -154,3 +146,45 @@ config YAFFS_SHORT_NAMES_IN_RAM
159 but makes look-ups faster.
160
161 If unsure, say Y.
162 +
163 +config YAFFS_EMPTY_LOST_AND_FOUND
164 + bool "Empty lost and found on boot"
165 + depends on YAFFS_FS
166 + default n
167 + help
168 + If this is enabled then the contents of lost and found is
169 + automatically dumped at mount.
170 +
171 + If unsure, say N.
172 +
173 +config YAFFS_DISABLE_BLOCK_REFRESHING
174 + bool "Disable yaffs2 block refreshing"
175 + depends on YAFFS_FS
176 + default n
177 + help
178 + If this is set, then block refreshing is disabled.
179 + Block refreshing infrequently refreshes the oldest block in
180 + a yaffs2 file system. This mechanism helps to refresh flash to
181 + mitigate against data loss. This is particularly useful for MLC.
182 +
183 + If unsure, say N.
184 +
185 +config YAFFS_DISABLE_BACKGROUND
186 + bool "Disable yaffs2 background processing"
187 + depends on YAFFS_FS
188 + default n
189 + help
190 + If this is set, then background processing is disabled.
191 + Background processing makes many foreground activities faster.
192 +
193 + If unsure, say N.
194 +
195 +config YAFFS_XATTR
196 + bool "Enable yaffs2 xattr support"
197 + depends on YAFFS_FS
198 + default y
199 + help
200 + If this is set then yaffs2 will provide xattr support.
201 + If unsure, say Y.
202 +
203 +
204 --- a/fs/yaffs2/Makefile
205 +++ b/fs/yaffs2/Makefile
206 @@ -4,7 +4,14 @@
207
208 obj-$(CONFIG_YAFFS_FS) += yaffs.o
209
210 -yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
211 -yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
212 +yaffs-y := yaffs_ecc.o yaffs_vfs_glue.o yaffs_guts.o yaffs_checkptrw.o
213 +yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
214 yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
215 yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
216 +yaffs-y += yaffs_nameval.o
217 +yaffs-y += yaffs_allocator.o
218 +yaffs-y += yaffs_yaffs1.o
219 +yaffs-y += yaffs_yaffs2.o
220 +yaffs-y += yaffs_bitmap.o
221 +yaffs-y += yaffs_verify.o
222 +
223 --- a/fs/yaffs2/moduleconfig.h
224 +++ b/fs/yaffs2/moduleconfig.h
225 @@ -1,7 +1,7 @@
226 /*
227 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
228 *
229 - * Copyright (C) 2002-2007 Aleph One Ltd.
230 + * Copyright (C) 2002-2010 Aleph One Ltd.
231 * for Toby Churchill Ltd and Brightstar Engineering
232 *
233 * Created by Martin Fouts <Martin.Fouts@palmsource.com>
234 @@ -29,22 +29,43 @@
235 /* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
236 /* #define CONFIG_YAFFS_DOES_ECC */
237
238 +/* Default: Selected */
239 +/* Meaning: Yaffs does its own ECC on tags for packed tags rather than use mtd */
240 +#define CONFIG_YAFFS_DOES_TAGS_ECC
241 +
242 /* Default: Not selected */
243 /* Meaning: ECC byte order is 'wrong'. Only meaningful if */
244 /* CONFIG_YAFFS_DOES_ECC is set */
245 /* #define CONFIG_YAFFS_ECC_WRONG_ORDER */
246
247 -/* Default: Selected */
248 -/* Meaning: Disables testing whether chunks are erased before writing to them*/
249 -#define CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
250 +/* Default: Not selected */
251 +/* Meaning: Always test whether chunks are erased before writing to them.
252 + Use during mtd debugging and init. */
253 +/* #define CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED */
254 +
255 +/* Default: Not Selected */
256 +/* Meaning: At mount automatically empty all files from lost and found. */
257 +/* This is done to fix an old problem where rmdir was not checking for an */
258 +/* empty directory. This can also be achieved with a mount option. */
259 +#define CONFIG_YAFFS_EMPTY_LOST_AND_FOUND
260
261 /* Default: Selected */
262 /* Meaning: Cache short names, taking more RAM, but faster look-ups */
263 #define CONFIG_YAFFS_SHORT_NAMES_IN_RAM
264
265 -/* Default: 10 */
266 -/* Meaning: set the count of blocks to reserve for checkpointing */
267 -#define CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS 10
268 +/* Default: Unselected */
269 +/* Meaning: Select to disable block refreshing. */
270 +/* Block Refreshing periodically rewrites the oldest block. */
271 +/* #define CONFIG_DISABLE_BLOCK_REFRESHING */
272 +
273 +/* Default: Unselected */
274 +/* Meaning: Select to disable background processing */
275 +/* #define CONFIG_DISABLE_BACKGROUND */
276 +
277 +
278 +/* Default: Selected */
279 +/* Meaning: Enable XATTR support */
280 +#define CONFIG_YAFFS_XATTR
281
282 /*
283 Older-style on-NAND data format has a "pageStatus" byte to record
284 --- /dev/null
285 +++ b/fs/yaffs2/yaffs_allocator.c
286 @@ -0,0 +1,409 @@
287 +/*
288 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
289 + *
290 + * Copyright (C) 2002-2010 Aleph One Ltd.
291 + * for Toby Churchill Ltd and Brightstar Engineering
292 + *
293 + * Created by Charles Manning <charles@aleph1.co.uk>
294 + *
295 + * This program is free software; you can redistribute it and/or modify
296 + * it under the terms of the GNU Lesser General Public License version 2.1 as
297 + * published by the Free Software Foundation.
298 + *
299 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
300 + */
301 +
302 +
303 +#include "yaffs_allocator.h"
304 +#include "yaffs_guts.h"
305 +#include "yaffs_trace.h"
306 +#include "yportenv.h"
307 +
308 +#ifdef CONFIG_YAFFS_YMALLOC_ALLOCATOR
309 +
310 +void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
311 +{
312 + dev = dev;
313 +}
314 +
315 +void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
316 +{
317 + dev = dev;
318 +}
319 +
320 +yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
321 +{
322 + return (yaffs_Tnode *)YMALLOC(dev->tnodeSize);
323 +}
324 +
325 +void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
326 +{
327 + dev = dev;
328 + YFREE(tn);
329 +}
330 +
331 +void yaffs_InitialiseRawObjects(yaffs_Device *dev)
332 +{
333 + dev = dev;
334 +}
335 +
336 +void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
337 +{
338 + dev = dev;
339 +}
340 +
341 +yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
342 +{
343 + dev = dev;
344 + return (yaffs_Object *) YMALLOC(sizeof(yaffs_Object));
345 +}
346 +
347 +
348 +void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
349 +{
350 +
351 + dev = dev;
352 + YFREE(obj);
353 +}
354 +
355 +#else
356 +
357 +struct yaffs_TnodeList_struct {
358 + struct yaffs_TnodeList_struct *next;
359 + yaffs_Tnode *tnodes;
360 +};
361 +
362 +typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
363 +
364 +struct yaffs_ObjectList_struct {
365 + yaffs_Object *objects;
366 + struct yaffs_ObjectList_struct *next;
367 +};
368 +
369 +typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
370 +
371 +
372 +struct yaffs_AllocatorStruct {
373 + int nTnodesCreated;
374 + yaffs_Tnode *freeTnodes;
375 + int nFreeTnodes;
376 + yaffs_TnodeList *allocatedTnodeList;
377 +
378 + int nObjectsCreated;
379 + yaffs_Object *freeObjects;
380 + int nFreeObjects;
381 +
382 + yaffs_ObjectList *allocatedObjectList;
383 +};
384 +
385 +typedef struct yaffs_AllocatorStruct yaffs_Allocator;
386 +
387 +
388 +static void yaffs_DeinitialiseRawTnodes(yaffs_Device *dev)
389 +{
390 +
391 + yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
392 +
393 + yaffs_TnodeList *tmp;
394 +
395 + if(!allocator){
396 + YBUG();
397 + return;
398 + }
399 +
400 + while (allocator->allocatedTnodeList) {
401 + tmp = allocator->allocatedTnodeList->next;
402 +
403 + YFREE(allocator->allocatedTnodeList->tnodes);
404 + YFREE(allocator->allocatedTnodeList);
405 + allocator->allocatedTnodeList = tmp;
406 +
407 + }
408 +
409 + allocator->freeTnodes = NULL;
410 + allocator->nFreeTnodes = 0;
411 + allocator->nTnodesCreated = 0;
412 +}
413 +
414 +static void yaffs_InitialiseRawTnodes(yaffs_Device *dev)
415 +{
416 + yaffs_Allocator *allocator = dev->allocator;
417 +
418 + if(allocator){
419 + allocator->allocatedTnodeList = NULL;
420 + allocator->freeTnodes = NULL;
421 + allocator->nFreeTnodes = 0;
422 + allocator->nTnodesCreated = 0;
423 + } else
424 + YBUG();
425 +}
426 +
427 +static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes)
428 +{
429 + yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
430 + int i;
431 + yaffs_Tnode *newTnodes;
432 + __u8 *mem;
433 + yaffs_Tnode *curr;
434 + yaffs_Tnode *next;
435 + yaffs_TnodeList *tnl;
436 +
437 + if(!allocator){
438 + YBUG();
439 + return YAFFS_FAIL;
440 + }
441 +
442 + if (nTnodes < 1)
443 + return YAFFS_OK;
444 +
445 +
446 + /* make these things */
447 +
448 + newTnodes = YMALLOC(nTnodes * dev->tnodeSize);
449 + mem = (__u8 *)newTnodes;
450 +
451 + if (!newTnodes) {
452 + T(YAFFS_TRACE_ERROR,
453 + (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
454 + return YAFFS_FAIL;
455 + }
456 +
457 + /* New hookup for wide tnodes */
458 + for (i = 0; i < nTnodes - 1; i++) {
459 + curr = (yaffs_Tnode *) &mem[i * dev->tnodeSize];
460 + next = (yaffs_Tnode *) &mem[(i+1) * dev->tnodeSize];
461 + curr->internal[0] = next;
462 + }
463 +
464 + curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * dev->tnodeSize];
465 + curr->internal[0] = allocator->freeTnodes;
466 + allocator->freeTnodes = (yaffs_Tnode *)mem;
467 +
468 + allocator->nFreeTnodes += nTnodes;
469 + allocator->nTnodesCreated += nTnodes;
470 +
471 + /* Now add this bunch of tnodes to a list for freeing up.
472 + * NB If we can't add this to the management list it isn't fatal
473 + * but it just means we can't free this bunch of tnodes later.
474 + */
475 +
476 + tnl = YMALLOC(sizeof(yaffs_TnodeList));
477 + if (!tnl) {
478 + T(YAFFS_TRACE_ERROR,
479 + (TSTR
480 + ("yaffs: Could not add tnodes to management list" TENDSTR)));
481 + return YAFFS_FAIL;
482 + } else {
483 + tnl->tnodes = newTnodes;
484 + tnl->next = allocator->allocatedTnodeList;
485 + allocator->allocatedTnodeList = tnl;
486 + }
487 +
488 + T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
489 +
490 + return YAFFS_OK;
491 +}
492 +
493 +
494 +yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
495 +{
496 + yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
497 + yaffs_Tnode *tn = NULL;
498 +
499 + if(!allocator){
500 + YBUG();
501 + return NULL;
502 + }
503 +
504 + /* If there are none left make more */
505 + if (!allocator->freeTnodes)
506 + yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
507 +
508 + if (allocator->freeTnodes) {
509 + tn = allocator->freeTnodes;
510 + allocator->freeTnodes = allocator->freeTnodes->internal[0];
511 + allocator->nFreeTnodes--;
512 + }
513 +
514 + return tn;
515 +}
516 +
517 +/* FreeTnode frees up a tnode and puts it back on the free list */
518 +void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
519 +{
520 + yaffs_Allocator *allocator = dev->allocator;
521 +
522 + if(!allocator){
523 + YBUG();
524 + return;
525 + }
526 +
527 + if (tn) {
528 + tn->internal[0] = allocator->freeTnodes;
529 + allocator->freeTnodes = tn;
530 + allocator->nFreeTnodes++;
531 + }
532 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
533 +}
534 +
535 +
536 +
537 +static void yaffs_InitialiseRawObjects(yaffs_Device *dev)
538 +{
539 + yaffs_Allocator *allocator = dev->allocator;
540 +
541 + if(allocator) {
542 + allocator->allocatedObjectList = NULL;
543 + allocator->freeObjects = NULL;
544 + allocator->nFreeObjects = 0;
545 + } else
546 + YBUG();
547 +}
548 +
549 +static void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
550 +{
551 + yaffs_Allocator *allocator = dev->allocator;
552 + yaffs_ObjectList *tmp;
553 +
554 + if(!allocator){
555 + YBUG();
556 + return;
557 + }
558 +
559 + while (allocator->allocatedObjectList) {
560 + tmp = allocator->allocatedObjectList->next;
561 + YFREE(allocator->allocatedObjectList->objects);
562 + YFREE(allocator->allocatedObjectList);
563 +
564 + allocator->allocatedObjectList = tmp;
565 + }
566 +
567 + allocator->freeObjects = NULL;
568 + allocator->nFreeObjects = 0;
569 + allocator->nObjectsCreated = 0;
570 +}
571 +
572 +
573 +static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
574 +{
575 + yaffs_Allocator *allocator = dev->allocator;
576 +
577 + int i;
578 + yaffs_Object *newObjects;
579 + yaffs_ObjectList *list;
580 +
581 + if(!allocator){
582 + YBUG();
583 + return YAFFS_FAIL;
584 + }
585 +
586 + if (nObjects < 1)
587 + return YAFFS_OK;
588 +
589 + /* make these things */
590 + newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
591 + list = YMALLOC(sizeof(yaffs_ObjectList));
592 +
593 + if (!newObjects || !list) {
594 + if (newObjects){
595 + YFREE(newObjects);
596 + newObjects = NULL;
597 + }
598 + if (list){
599 + YFREE(list);
600 + list = NULL;
601 + }
602 + T(YAFFS_TRACE_ALLOCATE,
603 + (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
604 + return YAFFS_FAIL;
605 + }
606 +
607 + /* Hook them into the free list */
608 + for (i = 0; i < nObjects - 1; i++) {
609 + newObjects[i].siblings.next =
610 + (struct ylist_head *)(&newObjects[i + 1]);
611 + }
612 +
613 + newObjects[nObjects - 1].siblings.next = (void *)allocator->freeObjects;
614 + allocator->freeObjects = newObjects;
615 + allocator->nFreeObjects += nObjects;
616 + allocator->nObjectsCreated += nObjects;
617 +
618 + /* Now add this bunch of Objects to a list for freeing up. */
619 +
620 + list->objects = newObjects;
621 + list->next = allocator->allocatedObjectList;
622 + allocator->allocatedObjectList = list;
623 +
624 + return YAFFS_OK;
625 +}
626 +
627 +yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
628 +{
629 + yaffs_Object *obj = NULL;
630 + yaffs_Allocator *allocator = dev->allocator;
631 +
632 + if(!allocator) {
633 + YBUG();
634 + return obj;
635 + }
636 +
637 + /* If there are none left make more */
638 + if (!allocator->freeObjects)
639 + yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
640 +
641 + if (allocator->freeObjects) {
642 + obj = allocator->freeObjects;
643 + allocator->freeObjects =
644 + (yaffs_Object *) (allocator->freeObjects->siblings.next);
645 + allocator->nFreeObjects--;
646 + }
647 +
648 + return obj;
649 +}
650 +
651 +
652 +void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
653 +{
654 +
655 + yaffs_Allocator *allocator = dev->allocator;
656 +
657 + if(!allocator)
658 + YBUG();
659 + else {
660 + /* Link into the free list. */
661 + obj->siblings.next = (struct ylist_head *)(allocator->freeObjects);
662 + allocator->freeObjects = obj;
663 + allocator->nFreeObjects++;
664 + }
665 +}
666 +
667 +void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
668 +{
669 + if(dev->allocator){
670 + yaffs_DeinitialiseRawTnodes(dev);
671 + yaffs_DeinitialiseRawObjects(dev);
672 +
673 + YFREE(dev->allocator);
674 + dev->allocator=NULL;
675 + } else
676 + YBUG();
677 +}
678 +
679 +void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
680 +{
681 + yaffs_Allocator *allocator;
682 +
683 + if(!dev->allocator){
684 + allocator = YMALLOC(sizeof(yaffs_Allocator));
685 + if(allocator){
686 + dev->allocator = allocator;
687 + yaffs_InitialiseRawTnodes(dev);
688 + yaffs_InitialiseRawObjects(dev);
689 + }
690 + } else
691 + YBUG();
692 +}
693 +
694 +
695 +#endif
696 --- /dev/null
697 +++ b/fs/yaffs2/yaffs_allocator.h
698 @@ -0,0 +1,30 @@
699 +/*
700 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
701 + *
702 + * Copyright (C) 2002-2010 Aleph One Ltd.
703 + * for Toby Churchill Ltd and Brightstar Engineering
704 + *
705 + * Created by Charles Manning <charles@aleph1.co.uk>
706 + *
707 + * This program is free software; you can redistribute it and/or modify
708 + * it under the terms of the GNU Lesser General Public License version 2.1 as
709 + * published by the Free Software Foundation.
710 + *
711 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
712 + */
713 +
714 +#ifndef __YAFFS_ALLOCATOR_H__
715 +#define __YAFFS_ALLOCATOR_H__
716 +
717 +#include "yaffs_guts.h"
718 +
719 +void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev);
720 +void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev);
721 +
722 +yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev);
723 +void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn);
724 +
725 +yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev);
726 +void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj);
727 +
728 +#endif
729 --- /dev/null
730 +++ b/fs/yaffs2/yaffs_bitmap.c
731 @@ -0,0 +1,105 @@
732 +/*
733 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
734 + *
735 + * Copyright (C) 2002-2010 Aleph One Ltd.
736 + * for Toby Churchill Ltd and Brightstar Engineering
737 + *
738 + * Created by Charles Manning <charles@aleph1.co.uk>
739 + *
740 + * This program is free software; you can redistribute it and/or modify
741 + * it under the terms of the GNU General Public License version 2 as
742 + * published by the Free Software Foundation.
743 + */
744 +
745 +#include "yaffs_bitmap.h"
746 +#include "yaffs_trace.h"
747 +/*
748 + * Chunk bitmap manipulations
749 + */
750 +
751 +static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk)
752 +{
753 + if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
754 + T(YAFFS_TRACE_ERROR,
755 + (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),
756 + blk));
757 + YBUG();
758 + }
759 + return dev->chunkBits +
760 + (dev->chunkBitmapStride * (blk - dev->internalStartBlock));
761 +}
762 +
763 +void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk)
764 +{
765 + if (blk < dev->internalStartBlock || blk > dev->internalEndBlock ||
766 + chunk < 0 || chunk >= dev->param.nChunksPerBlock) {
767 + T(YAFFS_TRACE_ERROR,
768 + (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),
769 + blk, chunk));
770 + YBUG();
771 + }
772 +}
773 +
774 +void yaffs_ClearChunkBits(yaffs_Device *dev, int blk)
775 +{
776 + __u8 *blkBits = yaffs_BlockBits(dev, blk);
777 +
778 + memset(blkBits, 0, dev->chunkBitmapStride);
779 +}
780 +
781 +void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk)
782 +{
783 + __u8 *blkBits = yaffs_BlockBits(dev, blk);
784 +
785 + yaffs_VerifyChunkBitId(dev, blk, chunk);
786 +
787 + blkBits[chunk / 8] &= ~(1 << (chunk & 7));
788 +}
789 +
790 +void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk)
791 +{
792 + __u8 *blkBits = yaffs_BlockBits(dev, blk);
793 +
794 + yaffs_VerifyChunkBitId(dev, blk, chunk);
795 +
796 + blkBits[chunk / 8] |= (1 << (chunk & 7));
797 +}
798 +
799 +int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk)
800 +{
801 + __u8 *blkBits = yaffs_BlockBits(dev, blk);
802 + yaffs_VerifyChunkBitId(dev, blk, chunk);
803 +
804 + return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
805 +}
806 +
807 +int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk)
808 +{
809 + __u8 *blkBits = yaffs_BlockBits(dev, blk);
810 + int i;
811 + for (i = 0; i < dev->chunkBitmapStride; i++) {
812 + if (*blkBits)
813 + return 1;
814 + blkBits++;
815 + }
816 + return 0;
817 +}
818 +
819 +int yaffs_CountChunkBits(yaffs_Device *dev, int blk)
820 +{
821 + __u8 *blkBits = yaffs_BlockBits(dev, blk);
822 + int i;
823 + int n = 0;
824 + for (i = 0; i < dev->chunkBitmapStride; i++) {
825 + __u8 x = *blkBits;
826 + while (x) {
827 + if (x & 1)
828 + n++;
829 + x >>= 1;
830 + }
831 +
832 + blkBits++;
833 + }
834 + return n;
835 +}
836 +
837 --- /dev/null
838 +++ b/fs/yaffs2/yaffs_bitmap.h
839 @@ -0,0 +1,31 @@
840 +/*
841 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
842 + *
843 + * Copyright (C) 2002-2010 Aleph One Ltd.
844 + * for Toby Churchill Ltd and Brightstar Engineering
845 + *
846 + * Created by Charles Manning <charles@aleph1.co.uk>
847 + *
848 + * This program is free software; you can redistribute it and/or modify
849 + * it under the terms of the GNU General Public License version 2 as
850 + * published by the Free Software Foundation.
851 + */
852 +
853 +/*
854 + * Chunk bitmap manipulations
855 + */
856 +
857 +#ifndef __YAFFS_BITMAP_H__
858 +#define __YAFFS_BITMAP_H__
859 +
860 +#include "yaffs_guts.h"
861 +
862 +void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk);
863 +void yaffs_ClearChunkBits(yaffs_Device *dev, int blk);
864 +void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk);
865 +void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk);
866 +int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk);
867 +int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk);
868 +int yaffs_CountChunkBits(yaffs_Device *dev, int blk);
869 +
870 +#endif
871 --- a/fs/yaffs2/yaffs_checkptrw.c
872 +++ b/fs/yaffs2/yaffs_checkptrw.c
873 @@ -1,7 +1,7 @@
874 /*
875 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
876 *
877 - * Copyright (C) 2002-2007 Aleph One Ltd.
878 + * Copyright (C) 2002-2010 Aleph One Ltd.
879 * for Toby Churchill Ltd and Brightstar Engineering
880 *
881 * Created by Charles Manning <charles@aleph1.co.uk>
882 @@ -11,16 +11,12 @@
883 * published by the Free Software Foundation.
884 */
885
886 -const char *yaffs_checkptrw_c_version =
887 - "$Id: yaffs_checkptrw.c,v 1.18 2009-03-06 17:20:49 wookey Exp $";
888 -
889 -
890 #include "yaffs_checkptrw.h"
891 #include "yaffs_getblockinfo.h"
892
893 -static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
894 +static int yaffs2_CheckpointSpaceOk(yaffs_Device *dev)
895 {
896 - int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
897 + int blocksAvailable = dev->nErasedBlocks - dev->param.nReservedBlocks;
898
899 T(YAFFS_TRACE_CHECKPOINT,
900 (TSTR("checkpt blocks available = %d" TENDSTR),
901 @@ -30,11 +26,11 @@ static int yaffs_CheckpointSpaceOk(yaffs
902 }
903
904
905 -static int yaffs_CheckpointErase(yaffs_Device *dev)
906 +static int yaffs2_CheckpointErase(yaffs_Device *dev)
907 {
908 int i;
909
910 - if (!dev->eraseBlockInNAND)
911 + if (!dev->param.eraseBlockInNAND)
912 return 0;
913 T(YAFFS_TRACE_CHECKPOINT, (TSTR("checking blocks %d to %d"TENDSTR),
914 dev->internalStartBlock, dev->internalEndBlock));
915 @@ -43,12 +39,15 @@ static int yaffs_CheckpointErase(yaffs_D
916 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i);
917 if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) {
918 T(YAFFS_TRACE_CHECKPOINT, (TSTR("erasing checkpt block %d"TENDSTR), i));
919 - if (dev->eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) {
920 +
921 + dev->nBlockErasures++;
922 +
923 + if (dev->param.eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) {
924 bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
925 dev->nErasedBlocks++;
926 - dev->nFreeChunks += dev->nChunksPerBlock;
927 + dev->nFreeChunks += dev->param.nChunksPerBlock;
928 } else {
929 - dev->markNANDBlockBad(dev, i);
930 + dev->param.markNANDBlockBad(dev, i);
931 bi->blockState = YAFFS_BLOCK_STATE_DEAD;
932 }
933 }
934 @@ -60,13 +59,13 @@ static int yaffs_CheckpointErase(yaffs_D
935 }
936
937
938 -static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev)
939 +static void yaffs2_CheckpointFindNextErasedBlock(yaffs_Device *dev)
940 {
941 int i;
942 - int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
943 + int blocksAvailable = dev->nErasedBlocks - dev->param.nReservedBlocks;
944 T(YAFFS_TRACE_CHECKPOINT,
945 (TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR),
946 - dev->nErasedBlocks, dev->nReservedBlocks, blocksAvailable, dev->checkpointNextBlock));
947 + dev->nErasedBlocks, dev->param.nReservedBlocks, blocksAvailable, dev->checkpointNextBlock));
948
949 if (dev->checkpointNextBlock >= 0 &&
950 dev->checkpointNextBlock <= dev->internalEndBlock &&
951 @@ -88,7 +87,7 @@ static void yaffs_CheckpointFindNextEras
952 dev->checkpointCurrentBlock = -1;
953 }
954
955 -static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
956 +static void yaffs2_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
957 {
958 int i;
959 yaffs_ExtendedTags tags;
960 @@ -98,10 +97,10 @@ static void yaffs_CheckpointFindNextChec
961
962 if (dev->blocksInCheckpoint < dev->checkpointMaxBlocks)
963 for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) {
964 - int chunk = i * dev->nChunksPerBlock;
965 + int chunk = i * dev->param.nChunksPerBlock;
966 int realignedChunk = chunk - dev->chunkOffset;
967
968 - dev->readChunkWithTagsFromNAND(dev, realignedChunk,
969 + dev->param.readChunkWithTagsFromNAND(dev, realignedChunk,
970 NULL, &tags);
971 T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR),
972 i, tags.objectId, tags.sequenceNumber, tags.eccResult));
973 @@ -124,29 +123,29 @@ static void yaffs_CheckpointFindNextChec
974 }
975
976
977 -int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
978 +int yaffs2_CheckpointOpen(yaffs_Device *dev, int forWriting)
979 {
980
981 +
982 + dev->checkpointOpenForWrite = forWriting;
983 +
984 /* Got the functions we need? */
985 - if (!dev->writeChunkWithTagsToNAND ||
986 - !dev->readChunkWithTagsFromNAND ||
987 - !dev->eraseBlockInNAND ||
988 - !dev->markNANDBlockBad)
989 + if (!dev->param.writeChunkWithTagsToNAND ||
990 + !dev->param.readChunkWithTagsFromNAND ||
991 + !dev->param.eraseBlockInNAND ||
992 + !dev->param.markNANDBlockBad)
993 return 0;
994
995 - if (forWriting && !yaffs_CheckpointSpaceOk(dev))
996 + if (forWriting && !yaffs2_CheckpointSpaceOk(dev))
997 return 0;
998
999 if (!dev->checkpointBuffer)
1000 - dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
1001 + dev->checkpointBuffer = YMALLOC_DMA(dev->param.totalBytesPerChunk);
1002 if (!dev->checkpointBuffer)
1003 return 0;
1004
1005
1006 dev->checkpointPageSequence = 0;
1007 -
1008 - dev->checkpointOpenForWrite = forWriting;
1009 -
1010 dev->checkpointByteCount = 0;
1011 dev->checkpointSum = 0;
1012 dev->checkpointXor = 0;
1013 @@ -158,7 +157,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
1014 if (forWriting) {
1015 memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);
1016 dev->checkpointByteOffset = 0;
1017 - return yaffs_CheckpointErase(dev);
1018 + return yaffs2_CheckpointErase(dev);
1019 } else {
1020 int i;
1021 /* Set to a value that will kick off a read */
1022 @@ -168,6 +167,9 @@ int yaffs_CheckpointOpen(yaffs_Device *d
1023 dev->blocksInCheckpoint = 0;
1024 dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2;
1025 dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks);
1026 + if(!dev->checkpointBlockList)
1027 + return 0;
1028 +
1029 for (i = 0; i < dev->checkpointMaxBlocks; i++)
1030 dev->checkpointBlockList[i] = -1;
1031 }
1032 @@ -175,7 +177,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
1033 return 1;
1034 }
1035
1036 -int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
1037 +int yaffs2_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
1038 {
1039 __u32 compositeSum;
1040 compositeSum = (dev->checkpointSum << 8) | (dev->checkpointXor & 0xFF);
1041 @@ -183,7 +185,7 @@ int yaffs_GetCheckpointSum(yaffs_Device
1042 return 1;
1043 }
1044
1045 -static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
1046 +static int yaffs2_CheckpointFlushBuffer(yaffs_Device *dev)
1047 {
1048 int chunk;
1049 int realignedChunk;
1050 @@ -191,7 +193,7 @@ static int yaffs_CheckpointFlushBuffer(y
1051 yaffs_ExtendedTags tags;
1052
1053 if (dev->checkpointCurrentBlock < 0) {
1054 - yaffs_CheckpointFindNextErasedBlock(dev);
1055 + yaffs2_CheckpointFindNextErasedBlock(dev);
1056 dev->checkpointCurrentChunk = 0;
1057 }
1058
1059 @@ -211,7 +213,7 @@ static int yaffs_CheckpointFlushBuffer(y
1060 dev->blocksInCheckpoint++;
1061 }
1062
1063 - chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk;
1064 + chunk = dev->checkpointCurrentBlock * dev->param.nChunksPerBlock + dev->checkpointCurrentChunk;
1065
1066
1067 T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR),
1068 @@ -219,12 +221,14 @@ static int yaffs_CheckpointFlushBuffer(y
1069
1070 realignedChunk = chunk - dev->chunkOffset;
1071
1072 - dev->writeChunkWithTagsToNAND(dev, realignedChunk,
1073 + dev->nPageWrites++;
1074 +
1075 + dev->param.writeChunkWithTagsToNAND(dev, realignedChunk,
1076 dev->checkpointBuffer, &tags);
1077 dev->checkpointByteOffset = 0;
1078 dev->checkpointPageSequence++;
1079 dev->checkpointCurrentChunk++;
1080 - if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock) {
1081 + if (dev->checkpointCurrentChunk >= dev->param.nChunksPerBlock) {
1082 dev->checkpointCurrentChunk = 0;
1083 dev->checkpointCurrentBlock = -1;
1084 }
1085 @@ -234,7 +238,7 @@ static int yaffs_CheckpointFlushBuffer(y
1086 }
1087
1088
1089 -int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)
1090 +int yaffs2_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)
1091 {
1092 int i = 0;
1093 int ok = 1;
1094 @@ -263,13 +267,13 @@ int yaffs_CheckpointWrite(yaffs_Device *
1095
1096 if (dev->checkpointByteOffset < 0 ||
1097 dev->checkpointByteOffset >= dev->nDataBytesPerChunk)
1098 - ok = yaffs_CheckpointFlushBuffer(dev);
1099 + ok = yaffs2_CheckpointFlushBuffer(dev);
1100 }
1101
1102 return i;
1103 }
1104
1105 -int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
1106 +int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
1107 {
1108 int i = 0;
1109 int ok = 1;
1110 @@ -294,7 +298,7 @@ int yaffs_CheckpointRead(yaffs_Device *d
1111 dev->checkpointByteOffset >= dev->nDataBytesPerChunk) {
1112
1113 if (dev->checkpointCurrentBlock < 0) {
1114 - yaffs_CheckpointFindNextCheckpointBlock(dev);
1115 + yaffs2_CheckpointFindNextCheckpointBlock(dev);
1116 dev->checkpointCurrentChunk = 0;
1117 }
1118
1119 @@ -302,14 +306,16 @@ int yaffs_CheckpointRead(yaffs_Device *d
1120 ok = 0;
1121 else {
1122 chunk = dev->checkpointCurrentBlock *
1123 - dev->nChunksPerBlock +
1124 + dev->param.nChunksPerBlock +
1125 dev->checkpointCurrentChunk;
1126
1127 realignedChunk = chunk - dev->chunkOffset;
1128 +
1129 + dev->nPageReads++;
1130
1131 /* read in the next chunk */
1132 /* printf("read checkpoint page %d\n",dev->checkpointPage); */
1133 - dev->readChunkWithTagsFromNAND(dev,
1134 + dev->param.readChunkWithTagsFromNAND(dev,
1135 realignedChunk,
1136 dev->checkpointBuffer,
1137 &tags);
1138 @@ -323,7 +329,7 @@ int yaffs_CheckpointRead(yaffs_Device *d
1139 dev->checkpointPageSequence++;
1140 dev->checkpointCurrentChunk++;
1141
1142 - if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock)
1143 + if (dev->checkpointCurrentChunk >= dev->param.nChunksPerBlock)
1144 dev->checkpointCurrentBlock = -1;
1145 }
1146 }
1147 @@ -342,17 +348,20 @@ int yaffs_CheckpointRead(yaffs_Device *d
1148 return i;
1149 }
1150
1151 -int yaffs_CheckpointClose(yaffs_Device *dev)
1152 +int yaffs2_CheckpointClose(yaffs_Device *dev)
1153 {
1154
1155 if (dev->checkpointOpenForWrite) {
1156 if (dev->checkpointByteOffset != 0)
1157 - yaffs_CheckpointFlushBuffer(dev);
1158 - } else {
1159 + yaffs2_CheckpointFlushBuffer(dev);
1160 + } else if(dev->checkpointBlockList){
1161 int i;
1162 for (i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++) {
1163 - yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointBlockList[i]);
1164 - if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
1165 + int blk = dev->checkpointBlockList[i];
1166 + yaffs_BlockInfo *bi = NULL;
1167 + if( dev->internalStartBlock <= blk && blk <= dev->internalEndBlock)
1168 + bi = yaffs_GetBlockInfo(dev, blk);
1169 + if (bi && bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
1170 bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
1171 else {
1172 /* Todo this looks odd... */
1173 @@ -362,7 +371,7 @@ int yaffs_CheckpointClose(yaffs_Device *
1174 dev->checkpointBlockList = NULL;
1175 }
1176
1177 - dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock;
1178 + dev->nFreeChunks -= dev->blocksInCheckpoint * dev->param.nChunksPerBlock;
1179 dev->nErasedBlocks -= dev->blocksInCheckpoint;
1180
1181
1182 @@ -378,16 +387,14 @@ int yaffs_CheckpointClose(yaffs_Device *
1183 return 0;
1184 }
1185
1186 -int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)
1187 +int yaffs2_CheckpointInvalidateStream(yaffs_Device *dev)
1188 {
1189 - /* Erase the first checksum block */
1190 -
1191 - T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate"TENDSTR)));
1192 + /* Erase the checkpoint data */
1193
1194 - if (!yaffs_CheckpointSpaceOk(dev))
1195 - return 0;
1196 + T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate of %d blocks"TENDSTR),
1197 + dev->blocksInCheckpoint));
1198
1199 - return yaffs_CheckpointErase(dev);
1200 + return yaffs2_CheckpointErase(dev);
1201 }
1202
1203
1204 --- a/fs/yaffs2/yaffs_checkptrw.h
1205 +++ b/fs/yaffs2/yaffs_checkptrw.h
1206 @@ -1,7 +1,7 @@
1207 /*
1208 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
1209 *
1210 - * Copyright (C) 2002-2007 Aleph One Ltd.
1211 + * Copyright (C) 2002-2010 Aleph One Ltd.
1212 * for Toby Churchill Ltd and Brightstar Engineering
1213 *
1214 * Created by Charles Manning <charles@aleph1.co.uk>
1215 @@ -18,18 +18,17 @@
1216
1217 #include "yaffs_guts.h"
1218
1219 -int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting);
1220 +int yaffs2_CheckpointOpen(yaffs_Device *dev, int forWriting);
1221
1222 -int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes);
1223 +int yaffs2_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes);
1224
1225 -int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);
1226 +int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);
1227
1228 -int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
1229 +int yaffs2_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
1230
1231 -int yaffs_CheckpointClose(yaffs_Device *dev);
1232 +int yaffs2_CheckpointClose(yaffs_Device *dev);
1233
1234 -int yaffs_CheckpointInvalidateStream(yaffs_Device *dev);
1235 +int yaffs2_CheckpointInvalidateStream(yaffs_Device *dev);
1236
1237
1238 #endif
1239 -
1240 --- a/fs/yaffs2/yaffs_ecc.c
1241 +++ b/fs/yaffs2/yaffs_ecc.c
1242 @@ -1,7 +1,7 @@
1243 /*
1244 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
1245 *
1246 - * Copyright (C) 2002-2007 Aleph One Ltd.
1247 + * Copyright (C) 2002-2010 Aleph One Ltd.
1248 * for Toby Churchill Ltd and Brightstar Engineering
1249 *
1250 * Created by Charles Manning <charles@aleph1.co.uk>
1251 @@ -28,9 +28,6 @@
1252 * this bytes influence on the line parity.
1253 */
1254
1255 -const char *yaffs_ecc_c_version =
1256 - "$Id: yaffs_ecc.c,v 1.11 2009-03-06 17:20:50 wookey Exp $";
1257 -
1258 #include "yportenv.h"
1259
1260 #include "yaffs_ecc.h"
1261 --- a/fs/yaffs2/yaffs_ecc.h
1262 +++ b/fs/yaffs2/yaffs_ecc.h
1263 @@ -1,7 +1,7 @@
1264 /*
1265 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
1266 *
1267 - * Copyright (C) 2002-2007 Aleph One Ltd.
1268 + * Copyright (C) 2002-2010 Aleph One Ltd.
1269 * for Toby Churchill Ltd and Brightstar Engineering
1270 *
1271 * Created by Charles Manning <charles@aleph1.co.uk>
1272 --- a/fs/yaffs2/yaffs_fs.c
1273 +++ /dev/null
1274 @@ -1,2529 +0,0 @@
1275 -/*
1276 - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
1277 - *
1278 - * Copyright (C) 2002-2009 Aleph One Ltd.
1279 - * for Toby Churchill Ltd and Brightstar Engineering
1280 - *
1281 - * Created by Charles Manning <charles@aleph1.co.uk>
1282 - * Acknowledgements:
1283 - * Luc van OostenRyck for numerous patches.
1284 - * Nick Bane for numerous patches.
1285 - * Nick Bane for 2.5/2.6 integration.
1286 - * Andras Toth for mknod rdev issue.
1287 - * Michael Fischer for finding the problem with inode inconsistency.
1288 - * Some code bodily lifted from JFFS
1289 - *
1290 - * This program is free software; you can redistribute it and/or modify
1291 - * it under the terms of the GNU General Public License version 2 as
1292 - * published by the Free Software Foundation.
1293 - */
1294 -
1295 -/*
1296 - *
1297 - * This is the file system front-end to YAFFS that hooks it up to
1298 - * the VFS.
1299 - *
1300 - * Special notes:
1301 - * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with
1302 - * this superblock
1303 - * >> 2.6: sb->s_fs_info points to the yaffs_Device associated with this
1304 - * superblock
1305 - * >> inode->u.generic_ip points to the associated yaffs_Object.
1306 - */
1307 -
1308 -const char *yaffs_fs_c_version =
1309 - "$Id: yaffs_fs.c,v 1.79 2009-03-17 01:12:00 wookey Exp $";
1310 -extern const char *yaffs_guts_c_version;
1311 -
1312 -#include <linux/version.h>
1313 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
1314 -#include <linux/config.h>
1315 -#endif
1316 -#include <linux/kernel.h>
1317 -#include <linux/module.h>
1318 -#include <linux/slab.h>
1319 -#include <linux/init.h>
1320 -#include <linux/fs.h>
1321 -#include <linux/proc_fs.h>
1322 -#include <linux/smp_lock.h>
1323 -#include <linux/pagemap.h>
1324 -#include <linux/mtd/mtd.h>
1325 -#include <linux/interrupt.h>
1326 -#include <linux/string.h>
1327 -#include <linux/ctype.h>
1328 -
1329 -#include "asm/div64.h"
1330 -
1331 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1332 -
1333 -#include <linux/statfs.h> /* Added NCB 15-8-2003 */
1334 -#include <linux/statfs.h>
1335 -#define UnlockPage(p) unlock_page(p)
1336 -#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
1337 -
1338 -/* FIXME: use sb->s_id instead ? */
1339 -#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
1340 -
1341 -#else
1342 -
1343 -#include <linux/locks.h>
1344 -#define BDEVNAME_SIZE 0
1345 -#define yaffs_devname(sb, buf) kdevname(sb->s_dev)
1346 -
1347 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
1348 -/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
1349 -#define __user
1350 -#endif
1351 -
1352 -#endif
1353 -
1354 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
1355 -#define YPROC_ROOT (&proc_root)
1356 -#else
1357 -#define YPROC_ROOT NULL
1358 -#endif
1359 -
1360 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1361 -#define WRITE_SIZE_STR "writesize"
1362 -#define WRITE_SIZE(mtd) ((mtd)->writesize)
1363 -#else
1364 -#define WRITE_SIZE_STR "oobblock"
1365 -#define WRITE_SIZE(mtd) ((mtd)->oobblock)
1366 -#endif
1367 -
1368 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
1369 -#define YAFFS_USE_WRITE_BEGIN_END 1
1370 -#else
1371 -#define YAFFS_USE_WRITE_BEGIN_END 0
1372 -#endif
1373 -
1374 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
1375 -static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
1376 -{
1377 - uint64_t result = partition_size;
1378 - do_div(result, block_size);
1379 - return (uint32_t)result;
1380 -}
1381 -#else
1382 -#define YCALCBLOCKS(s, b) ((s)/(b))
1383 -#endif
1384 -
1385 -#include <linux/uaccess.h>
1386 -
1387 -#include "yportenv.h"
1388 -#include "yaffs_guts.h"
1389 -
1390 -#include <linux/mtd/mtd.h>
1391 -#include "yaffs_mtdif.h"
1392 -#include "yaffs_mtdif1.h"
1393 -#include "yaffs_mtdif2.h"
1394 -
1395 -unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS;
1396 -unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
1397 -unsigned int yaffs_auto_checkpoint = 1;
1398 -
1399 -/* Module Parameters */
1400 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1401 -module_param(yaffs_traceMask, uint, 0644);
1402 -module_param(yaffs_wr_attempts, uint, 0644);
1403 -module_param(yaffs_auto_checkpoint, uint, 0644);
1404 -#else
1405 -MODULE_PARM(yaffs_traceMask, "i");
1406 -MODULE_PARM(yaffs_wr_attempts, "i");
1407 -MODULE_PARM(yaffs_auto_checkpoint, "i");
1408 -#endif
1409 -
1410 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
1411 -/* use iget and read_inode */
1412 -#define Y_IGET(sb, inum) iget((sb), (inum))
1413 -static void yaffs_read_inode(struct inode *inode);
1414 -
1415 -#else
1416 -/* Call local equivalent */
1417 -#define YAFFS_USE_OWN_IGET
1418 -#define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
1419 -
1420 -static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino);
1421 -#endif
1422 -
1423 -/*#define T(x) printk x */
1424 -
1425 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
1426 -#define yaffs_InodeToObjectLV(iptr) ((iptr)->i_private)
1427 -#else
1428 -#define yaffs_InodeToObjectLV(iptr) ((iptr)->u.generic_ip)
1429 -#endif
1430 -
1431 -#define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr)))
1432 -#define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode)
1433 -
1434 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1435 -#define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->s_fs_info)
1436 -#else
1437 -#define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp)
1438 -#endif
1439 -
1440 -static void yaffs_put_super(struct super_block *sb);
1441 -
1442 -static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
1443 - loff_t *pos);
1444 -static ssize_t yaffs_hold_space(struct file *f);
1445 -static void yaffs_release_space(struct file *f);
1446 -
1447 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1448 -static int yaffs_file_flush(struct file *file, fl_owner_t id);
1449 -#else
1450 -static int yaffs_file_flush(struct file *file);
1451 -#endif
1452 -
1453 -static int yaffs_sync_object(struct file *file, struct dentry *dentry,
1454 - int datasync);
1455 -
1456 -static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
1457 -
1458 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1459 -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
1460 - struct nameidata *n);
1461 -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
1462 - struct nameidata *n);
1463 -#else
1464 -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
1465 -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry);
1466 -#endif
1467 -static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
1468 - struct dentry *dentry);
1469 -static int yaffs_unlink(struct inode *dir, struct dentry *dentry);
1470 -static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
1471 - const char *symname);
1472 -static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1473 -
1474 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1475 -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
1476 - dev_t dev);
1477 -#else
1478 -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
1479 - int dev);
1480 -#endif
1481 -static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
1482 - struct inode *new_dir, struct dentry *new_dentry);
1483 -static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);
1484 -
1485 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1486 -static int yaffs_sync_fs(struct super_block *sb, int wait);
1487 -static void yaffs_write_super(struct super_block *sb);
1488 -#else
1489 -static int yaffs_sync_fs(struct super_block *sb);
1490 -static int yaffs_write_super(struct super_block *sb);
1491 -#endif
1492 -
1493 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1494 -static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf);
1495 -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1496 -static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf);
1497 -#else
1498 -static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
1499 -#endif
1500 -
1501 -#ifdef YAFFS_HAS_PUT_INODE
1502 -static void yaffs_put_inode(struct inode *inode);
1503 -#endif
1504 -
1505 -static void yaffs_delete_inode(struct inode *);
1506 -static void yaffs_clear_inode(struct inode *);
1507 -
1508 -static int yaffs_readpage(struct file *file, struct page *page);
1509 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1510 -static int yaffs_writepage(struct page *page, struct writeback_control *wbc);
1511 -#else
1512 -static int yaffs_writepage(struct page *page);
1513 -#endif
1514 -
1515 -
1516 -#if (YAFFS_USE_WRITE_BEGIN_END != 0)
1517 -static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
1518 - loff_t pos, unsigned len, unsigned flags,
1519 - struct page **pagep, void **fsdata);
1520 -static int yaffs_write_end(struct file *filp, struct address_space *mapping,
1521 - loff_t pos, unsigned len, unsigned copied,
1522 - struct page *pg, void *fsdadata);
1523 -#else
1524 -static int yaffs_prepare_write(struct file *f, struct page *pg,
1525 - unsigned offset, unsigned to);
1526 -static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
1527 - unsigned to);
1528 -
1529 -#endif
1530 -
1531 -static int yaffs_readlink(struct dentry *dentry, char __user *buffer,
1532 - int buflen);
1533 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
1534 -static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
1535 -#else
1536 -static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
1537 -#endif
1538 -
1539 -static struct address_space_operations yaffs_file_address_operations = {
1540 - .readpage = yaffs_readpage,
1541 - .writepage = yaffs_writepage,
1542 -#if (YAFFS_USE_WRITE_BEGIN_END > 0)
1543 - .write_begin = yaffs_write_begin,
1544 - .write_end = yaffs_write_end,
1545 -#else
1546 - .prepare_write = yaffs_prepare_write,
1547 - .commit_write = yaffs_commit_write,
1548 -#endif
1549 -};
1550 -
1551 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
1552 -static const struct file_operations yaffs_file_operations = {
1553 - .read = do_sync_read,
1554 - .write = do_sync_write,
1555 - .aio_read = generic_file_aio_read,
1556 - .aio_write = generic_file_aio_write,
1557 - .mmap = generic_file_mmap,
1558 - .flush = yaffs_file_flush,
1559 - .fsync = yaffs_sync_object,
1560 - .splice_read = generic_file_splice_read,
1561 - .splice_write = generic_file_splice_write,
1562 - .llseek = generic_file_llseek,
1563 -};
1564 -
1565 -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
1566 -
1567 -static const struct file_operations yaffs_file_operations = {
1568 - .read = do_sync_read,
1569 - .write = do_sync_write,
1570 - .aio_read = generic_file_aio_read,
1571 - .aio_write = generic_file_aio_write,
1572 - .mmap = generic_file_mmap,
1573 - .flush = yaffs_file_flush,
1574 - .fsync = yaffs_sync_object,
1575 - .sendfile = generic_file_sendfile,
1576 -};
1577 -
1578 -#else
1579 -
1580 -static const struct file_operations yaffs_file_operations = {
1581 - .read = generic_file_read,
1582 - .write = generic_file_write,
1583 - .mmap = generic_file_mmap,
1584 - .flush = yaffs_file_flush,
1585 - .fsync = yaffs_sync_object,
1586 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1587 - .sendfile = generic_file_sendfile,
1588 -#endif
1589 -};
1590 -#endif
1591 -
1592 -static const struct inode_operations yaffs_file_inode_operations = {
1593 - .setattr = yaffs_setattr,
1594 -};
1595 -
1596 -static const struct inode_operations yaffs_symlink_inode_operations = {
1597 - .readlink = yaffs_readlink,
1598 - .follow_link = yaffs_follow_link,
1599 - .setattr = yaffs_setattr,
1600 -};
1601 -
1602 -static const struct inode_operations yaffs_dir_inode_operations = {
1603 - .create = yaffs_create,
1604 - .lookup = yaffs_lookup,
1605 - .link = yaffs_link,
1606 - .unlink = yaffs_unlink,
1607 - .symlink = yaffs_symlink,
1608 - .mkdir = yaffs_mkdir,
1609 - .rmdir = yaffs_unlink,
1610 - .mknod = yaffs_mknod,
1611 - .rename = yaffs_rename,
1612 - .setattr = yaffs_setattr,
1613 -};
1614 -
1615 -static const struct file_operations yaffs_dir_operations = {
1616 - .read = generic_read_dir,
1617 - .readdir = yaffs_readdir,
1618 - .fsync = yaffs_sync_object,
1619 -};
1620 -
1621 -static const struct super_operations yaffs_super_ops = {
1622 - .statfs = yaffs_statfs,
1623 -
1624 -#ifndef YAFFS_USE_OWN_IGET
1625 - .read_inode = yaffs_read_inode,
1626 -#endif
1627 -#ifdef YAFFS_HAS_PUT_INODE
1628 - .put_inode = yaffs_put_inode,
1629 -#endif
1630 - .put_super = yaffs_put_super,
1631 - .delete_inode = yaffs_delete_inode,
1632 - .clear_inode = yaffs_clear_inode,
1633 - .sync_fs = yaffs_sync_fs,
1634 - .write_super = yaffs_write_super,
1635 -};
1636 -
1637 -static void yaffs_GrossLock(yaffs_Device *dev)
1638 -{
1639 - T(YAFFS_TRACE_OS, ("yaffs locking %p\n", current));
1640 - down(&dev->grossLock);
1641 - T(YAFFS_TRACE_OS, ("yaffs locked %p\n", current));
1642 -}
1643 -
1644 -static void yaffs_GrossUnlock(yaffs_Device *dev)
1645 -{
1646 - T(YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current));
1647 - up(&dev->grossLock);
1648 -}
1649 -
1650 -static int yaffs_readlink(struct dentry *dentry, char __user *buffer,
1651 - int buflen)
1652 -{
1653 - unsigned char *alias;
1654 - int ret;
1655 -
1656 - yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
1657 -
1658 - yaffs_GrossLock(dev);
1659 -
1660 - alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
1661 -
1662 - yaffs_GrossUnlock(dev);
1663 -
1664 - if (!alias)
1665 - return -ENOMEM;
1666 -
1667 - ret = vfs_readlink(dentry, buffer, buflen, alias);
1668 - kfree(alias);
1669 - return ret;
1670 -}
1671 -
1672 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
1673 -static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
1674 -#else
1675 -static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
1676 -#endif
1677 -{
1678 - unsigned char *alias;
1679 - int ret;
1680 - yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
1681 -
1682 - yaffs_GrossLock(dev);
1683 -
1684 - alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
1685 -
1686 - yaffs_GrossUnlock(dev);
1687 -
1688 - if (!alias) {
1689 - ret = -ENOMEM;
1690 - goto out;
1691 - }
1692 -
1693 - ret = vfs_follow_link(nd, alias);
1694 - kfree(alias);
1695 -out:
1696 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
1697 - return ERR_PTR(ret);
1698 -#else
1699 - return ret;
1700 -#endif
1701 -}
1702 -
1703 -struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
1704 - yaffs_Object *obj);
1705 -
1706 -/*
1707 - * Lookup is used to find objects in the fs
1708 - */
1709 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1710 -
1711 -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
1712 - struct nameidata *n)
1713 -#else
1714 -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
1715 -#endif
1716 -{
1717 - yaffs_Object *obj;
1718 - struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */
1719 -
1720 - yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
1721 -
1722 - yaffs_GrossLock(dev);
1723 -
1724 - T(YAFFS_TRACE_OS,
1725 - ("yaffs_lookup for %d:%s\n",
1726 - yaffs_InodeToObject(dir)->objectId, dentry->d_name.name));
1727 -
1728 - obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),
1729 - dentry->d_name.name);
1730 -
1731 - obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */
1732 -
1733 - /* Can't hold gross lock when calling yaffs_get_inode() */
1734 - yaffs_GrossUnlock(dev);
1735 -
1736 - if (obj) {
1737 - T(YAFFS_TRACE_OS,
1738 - ("yaffs_lookup found %d\n", obj->objectId));
1739 -
1740 - inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
1741 -
1742 - if (inode) {
1743 - T(YAFFS_TRACE_OS,
1744 - ("yaffs_loookup dentry \n"));
1745 -/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to
1746 - * d_add even if NULL inode */
1747 -#if 0
1748 - /*dget(dentry); // try to solve directory bug */
1749 - d_add(dentry, inode);
1750 -
1751 - /* return dentry; */
1752 - return NULL;
1753 -#endif
1754 - }
1755 -
1756 - } else {
1757 - T(YAFFS_TRACE_OS, ("yaffs_lookup not found\n"));
1758 -
1759 - }
1760 -
1761 -/* added NCB for 2.5/6 compatability - forces add even if inode is
1762 - * NULL which creates dentry hash */
1763 - d_add(dentry, inode);
1764 -
1765 - return NULL;
1766 -}
1767 -
1768 -
1769 -#ifdef YAFFS_HAS_PUT_INODE
1770 -
1771 -/* For now put inode is just for debugging
1772 - * Put inode is called when the inode **structure** is put.
1773 - */
1774 -static void yaffs_put_inode(struct inode *inode)
1775 -{
1776 - T(YAFFS_TRACE_OS,
1777 - ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino,
1778 - atomic_read(&inode->i_count)));
1779 -
1780 -}
1781 -#endif
1782 -
1783 -/* clear is called to tell the fs to release any per-inode data it holds */
1784 -static void yaffs_clear_inode(struct inode *inode)
1785 -{
1786 - yaffs_Object *obj;
1787 - yaffs_Device *dev;
1788 -
1789 - obj = yaffs_InodeToObject(inode);
1790 -
1791 - T(YAFFS_TRACE_OS,
1792 - ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino,
1793 - atomic_read(&inode->i_count),
1794 - obj ? "object exists" : "null object"));
1795 -
1796 - if (obj) {
1797 - dev = obj->myDev;
1798 - yaffs_GrossLock(dev);
1799 -
1800 - /* Clear the association between the inode and
1801 - * the yaffs_Object.
1802 - */
1803 - obj->myInode = NULL;
1804 - yaffs_InodeToObjectLV(inode) = NULL;
1805 -
1806 - /* If the object freeing was deferred, then the real
1807 - * free happens now.
1808 - * This should fix the inode inconsistency problem.
1809 - */
1810 -
1811 - yaffs_HandleDeferedFree(obj);
1812 -
1813 - yaffs_GrossUnlock(dev);
1814 - }
1815 -
1816 -}
1817 -
1818 -/* delete is called when the link count is zero and the inode
1819 - * is put (ie. nobody wants to know about it anymore, time to
1820 - * delete the file).
1821 - * NB Must call clear_inode()
1822 - */
1823 -static void yaffs_delete_inode(struct inode *inode)
1824 -{
1825 - yaffs_Object *obj = yaffs_InodeToObject(inode);
1826 - yaffs_Device *dev;
1827 -
1828 - T(YAFFS_TRACE_OS,
1829 - ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino,
1830 - atomic_read(&inode->i_count),
1831 - obj ? "object exists" : "null object"));
1832 -
1833 - if (obj) {
1834 - dev = obj->myDev;
1835 - yaffs_GrossLock(dev);
1836 - yaffs_DeleteObject(obj);
1837 - yaffs_GrossUnlock(dev);
1838 - }
1839 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
1840 - truncate_inode_pages(&inode->i_data, 0);
1841 -#endif
1842 - clear_inode(inode);
1843 -}
1844 -
1845 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
1846 -static int yaffs_file_flush(struct file *file, fl_owner_t id)
1847 -#else
1848 -static int yaffs_file_flush(struct file *file)
1849 -#endif
1850 -{
1851 - yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry);
1852 -
1853 - yaffs_Device *dev = obj->myDev;
1854 -
1855 - T(YAFFS_TRACE_OS,
1856 - ("yaffs_file_flush object %d (%s)\n", obj->objectId,
1857 - obj->dirty ? "dirty" : "clean"));
1858 -
1859 - yaffs_GrossLock(dev);
1860 -
1861 - yaffs_FlushFile(obj, 1);
1862 -
1863 - yaffs_GrossUnlock(dev);
1864 -
1865 - return 0;
1866 -}
1867 -
1868 -static int yaffs_readpage_nolock(struct file *f, struct page *pg)
1869 -{
1870 - /* Lifted from jffs2 */
1871 -
1872 - yaffs_Object *obj;
1873 - unsigned char *pg_buf;
1874 - int ret;
1875 -
1876 - yaffs_Device *dev;
1877 -
1878 - T(YAFFS_TRACE_OS, ("yaffs_readpage at %08x, size %08x\n",
1879 - (unsigned)(pg->index << PAGE_CACHE_SHIFT),
1880 - (unsigned)PAGE_CACHE_SIZE));
1881 -
1882 - obj = yaffs_DentryToObject(f->f_dentry);
1883 -
1884 - dev = obj->myDev;
1885 -
1886 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1887 - BUG_ON(!PageLocked(pg));
1888 -#else
1889 - if (!PageLocked(pg))
1890 - PAGE_BUG(pg);
1891 -#endif
1892 -
1893 - pg_buf = kmap(pg);
1894 - /* FIXME: Can kmap fail? */
1895 -
1896 - yaffs_GrossLock(dev);
1897 -
1898 - ret = yaffs_ReadDataFromFile(obj, pg_buf,
1899 - pg->index << PAGE_CACHE_SHIFT,
1900 - PAGE_CACHE_SIZE);
1901 -
1902 - yaffs_GrossUnlock(dev);
1903 -
1904 - if (ret >= 0)
1905 - ret = 0;
1906 -
1907 - if (ret) {
1908 - ClearPageUptodate(pg);
1909 - SetPageError(pg);
1910 - } else {
1911 - SetPageUptodate(pg);
1912 - ClearPageError(pg);
1913 - }
1914 -
1915 - flush_dcache_page(pg);
1916 - kunmap(pg);
1917 -
1918 - T(YAFFS_TRACE_OS, ("yaffs_readpage done\n"));
1919 - return ret;
1920 -}
1921 -
1922 -static int yaffs_readpage_unlock(struct file *f, struct page *pg)
1923 -{
1924 - int ret = yaffs_readpage_nolock(f, pg);
1925 - UnlockPage(pg);
1926 - return ret;
1927 -}
1928 -
1929 -static int yaffs_readpage(struct file *f, struct page *pg)
1930 -{
1931 - return yaffs_readpage_unlock(f, pg);
1932 -}
1933 -
1934 -/* writepage inspired by/stolen from smbfs */
1935 -
1936 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
1937 -static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
1938 -#else
1939 -static int yaffs_writepage(struct page *page)
1940 -#endif
1941 -{
1942 - struct address_space *mapping = page->mapping;
1943 - loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT;
1944 - struct inode *inode;
1945 - unsigned long end_index;
1946 - char *buffer;
1947 - yaffs_Object *obj;
1948 - int nWritten = 0;
1949 - unsigned nBytes;
1950 -
1951 - if (!mapping)
1952 - BUG();
1953 - inode = mapping->host;
1954 - if (!inode)
1955 - BUG();
1956 -
1957 - if (offset > inode->i_size) {
1958 - T(YAFFS_TRACE_OS,
1959 - ("yaffs_writepage at %08x, inode size = %08x!!!\n",
1960 - (unsigned)(page->index << PAGE_CACHE_SHIFT),
1961 - (unsigned)inode->i_size));
1962 - T(YAFFS_TRACE_OS,
1963 - (" -> don't care!!\n"));
1964 - unlock_page(page);
1965 - return 0;
1966 - }
1967 -
1968 - end_index = inode->i_size >> PAGE_CACHE_SHIFT;
1969 -
1970 - /* easy case */
1971 - if (page->index < end_index)
1972 - nBytes = PAGE_CACHE_SIZE;
1973 - else
1974 - nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1);
1975 -
1976 - get_page(page);
1977 -
1978 - buffer = kmap(page);
1979 -
1980 - obj = yaffs_InodeToObject(inode);
1981 - yaffs_GrossLock(obj->myDev);
1982 -
1983 - T(YAFFS_TRACE_OS,
1984 - ("yaffs_writepage at %08x, size %08x\n",
1985 - (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes));
1986 - T(YAFFS_TRACE_OS,
1987 - ("writepag0: obj = %05x, ino = %05x\n",
1988 - (int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
1989 -
1990 - nWritten = yaffs_WriteDataToFile(obj, buffer,
1991 - page->index << PAGE_CACHE_SHIFT, nBytes, 0);
1992 -
1993 - T(YAFFS_TRACE_OS,
1994 - ("writepag1: obj = %05x, ino = %05x\n",
1995 - (int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
1996 -
1997 - yaffs_GrossUnlock(obj->myDev);
1998 -
1999 - kunmap(page);
2000 - SetPageUptodate(page);
2001 - UnlockPage(page);
2002 - put_page(page);
2003 -
2004 - return (nWritten == nBytes) ? 0 : -ENOSPC;
2005 -}
2006 -
2007 -
2008 -#if (YAFFS_USE_WRITE_BEGIN_END > 0)
2009 -static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
2010 - loff_t pos, unsigned len, unsigned flags,
2011 - struct page **pagep, void **fsdata)
2012 -{
2013 - struct page *pg = NULL;
2014 - pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2015 - uint32_t offset = pos & (PAGE_CACHE_SIZE - 1);
2016 - uint32_t to = offset + len;
2017 -
2018 - int ret = 0;
2019 - int space_held = 0;
2020 -
2021 - T(YAFFS_TRACE_OS, ("start yaffs_write_begin\n"));
2022 - /* Get a page */
2023 -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)
2024 - pg = grab_cache_page_write_begin(mapping, index, flags);
2025 -#else
2026 - pg = __grab_cache_page(mapping, index);
2027 -#endif
2028 -
2029 - *pagep = pg;
2030 - if (!pg) {
2031 - ret = -ENOMEM;
2032 - goto out;
2033 - }
2034 - /* Get fs space */
2035 - space_held = yaffs_hold_space(filp);
2036 -
2037 - if (!space_held) {
2038 - ret = -ENOSPC;
2039 - goto out;
2040 - }
2041 -
2042 - /* Update page if required */
2043 -
2044 - if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
2045 - ret = yaffs_readpage_nolock(filp, pg);
2046 -
2047 - if (ret)
2048 - goto out;
2049 -
2050 - /* Happy path return */
2051 - T(YAFFS_TRACE_OS, ("end yaffs_write_begin - ok\n"));
2052 -
2053 - return 0;
2054 -
2055 -out:
2056 - T(YAFFS_TRACE_OS, ("end yaffs_write_begin fail returning %d\n", ret));
2057 - if (space_held)
2058 - yaffs_release_space(filp);
2059 - if (pg) {
2060 - unlock_page(pg);
2061 - page_cache_release(pg);
2062 - }
2063 - return ret;
2064 -}
2065 -
2066 -#else
2067 -
2068 -static int yaffs_prepare_write(struct file *f, struct page *pg,
2069 - unsigned offset, unsigned to)
2070 -{
2071 - T(YAFFS_TRACE_OS, ("yaffs_prepair_write\n"));
2072 -
2073 - if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
2074 - return yaffs_readpage_nolock(f, pg);
2075 - return 0;
2076 -}
2077 -#endif
2078 -
2079 -#if (YAFFS_USE_WRITE_BEGIN_END > 0)
2080 -static int yaffs_write_end(struct file *filp, struct address_space *mapping,
2081 - loff_t pos, unsigned len, unsigned copied,
2082 - struct page *pg, void *fsdadata)
2083 -{
2084 - int ret = 0;
2085 - void *addr, *kva;
2086 - uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
2087 -
2088 - kva = kmap(pg);
2089 - addr = kva + offset_into_page;
2090 -
2091 - T(YAFFS_TRACE_OS,
2092 - ("yaffs_write_end addr %x pos %x nBytes %d\n",
2093 - (unsigned) addr,
2094 - (int)pos, copied));
2095 -
2096 - ret = yaffs_file_write(filp, addr, copied, &pos);
2097 -
2098 - if (ret != copied) {
2099 - T(YAFFS_TRACE_OS,
2100 - ("yaffs_write_end not same size ret %d copied %d\n",
2101 - ret, copied));
2102 - SetPageError(pg);
2103 - ClearPageUptodate(pg);
2104 - } else {
2105 - SetPageUptodate(pg);
2106 - }
2107 -
2108 - kunmap(pg);
2109 -
2110 - yaffs_release_space(filp);
2111 - unlock_page(pg);
2112 - page_cache_release(pg);
2113 - return ret;
2114 -}
2115 -#else
2116 -
2117 -static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
2118 - unsigned to)
2119 -{
2120 - void *addr, *kva;
2121 -
2122 - loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
2123 - int nBytes = to - offset;
2124 - int nWritten;
2125 -
2126 - unsigned spos = pos;
2127 - unsigned saddr;
2128 -
2129 - kva = kmap(pg);
2130 - addr = kva + offset;
2131 -
2132 - saddr = (unsigned) addr;
2133 -
2134 - T(YAFFS_TRACE_OS,
2135 - ("yaffs_commit_write addr %x pos %x nBytes %d\n",
2136 - saddr, spos, nBytes));
2137 -
2138 - nWritten = yaffs_file_write(f, addr, nBytes, &pos);
2139 -
2140 - if (nWritten != nBytes) {
2141 - T(YAFFS_TRACE_OS,
2142 - ("yaffs_commit_write not same size nWritten %d nBytes %d\n",
2143 - nWritten, nBytes));
2144 - SetPageError(pg);
2145 - ClearPageUptodate(pg);
2146 - } else {
2147 - SetPageUptodate(pg);
2148 - }
2149 -
2150 - kunmap(pg);
2151 -
2152 - T(YAFFS_TRACE_OS,
2153 - ("yaffs_commit_write returning %d\n",
2154 - nWritten == nBytes ? 0 : nWritten));
2155 -
2156 - return nWritten == nBytes ? 0 : nWritten;
2157 -}
2158 -#endif
2159 -
2160 -
2161 -static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
2162 -{
2163 - if (inode && obj) {
2164 -
2165 -
2166 - /* Check mode against the variant type and attempt to repair if broken. */
2167 - __u32 mode = obj->yst_mode;
2168 - switch (obj->variantType) {
2169 - case YAFFS_OBJECT_TYPE_FILE:
2170 - if (!S_ISREG(mode)) {
2171 - obj->yst_mode &= ~S_IFMT;
2172 - obj->yst_mode |= S_IFREG;
2173 - }
2174 -
2175 - break;
2176 - case YAFFS_OBJECT_TYPE_SYMLINK:
2177 - if (!S_ISLNK(mode)) {
2178 - obj->yst_mode &= ~S_IFMT;
2179 - obj->yst_mode |= S_IFLNK;
2180 - }
2181 -
2182 - break;
2183 - case YAFFS_OBJECT_TYPE_DIRECTORY:
2184 - if (!S_ISDIR(mode)) {
2185 - obj->yst_mode &= ~S_IFMT;
2186 - obj->yst_mode |= S_IFDIR;
2187 - }
2188 -
2189 - break;
2190 - case YAFFS_OBJECT_TYPE_UNKNOWN:
2191 - case YAFFS_OBJECT_TYPE_HARDLINK:
2192 - case YAFFS_OBJECT_TYPE_SPECIAL:
2193 - default:
2194 - /* TODO? */
2195 - break;
2196 - }
2197 -
2198 - inode->i_flags |= S_NOATIME;
2199 -
2200 - inode->i_ino = obj->objectId;
2201 - inode->i_mode = obj->yst_mode;
2202 - inode->i_uid = obj->yst_uid;
2203 - inode->i_gid = obj->yst_gid;
2204 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
2205 - inode->i_blksize = inode->i_sb->s_blocksize;
2206 -#endif
2207 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2208 -
2209 - inode->i_rdev = old_decode_dev(obj->yst_rdev);
2210 - inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
2211 - inode->i_atime.tv_nsec = 0;
2212 - inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
2213 - inode->i_mtime.tv_nsec = 0;
2214 - inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
2215 - inode->i_ctime.tv_nsec = 0;
2216 -#else
2217 - inode->i_rdev = obj->yst_rdev;
2218 - inode->i_atime = obj->yst_atime;
2219 - inode->i_mtime = obj->yst_mtime;
2220 - inode->i_ctime = obj->yst_ctime;
2221 -#endif
2222 - inode->i_size = yaffs_GetObjectFileLength(obj);
2223 - inode->i_blocks = (inode->i_size + 511) >> 9;
2224 -
2225 - inode->i_nlink = yaffs_GetObjectLinkCount(obj);
2226 -
2227 - T(YAFFS_TRACE_OS,
2228 - ("yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
2229 - inode->i_mode, inode->i_uid, inode->i_gid,
2230 - (int)inode->i_size, atomic_read(&inode->i_count)));
2231 -
2232 - switch (obj->yst_mode & S_IFMT) {
2233 - default: /* fifo, device or socket */
2234 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2235 - init_special_inode(inode, obj->yst_mode,
2236 - old_decode_dev(obj->yst_rdev));
2237 -#else
2238 - init_special_inode(inode, obj->yst_mode,
2239 - (dev_t) (obj->yst_rdev));
2240 -#endif
2241 - break;
2242 - case S_IFREG: /* file */
2243 - inode->i_op = &yaffs_file_inode_operations;
2244 - inode->i_fop = &yaffs_file_operations;
2245 - inode->i_mapping->a_ops =
2246 - &yaffs_file_address_operations;
2247 - break;
2248 - case S_IFDIR: /* directory */
2249 - inode->i_op = &yaffs_dir_inode_operations;
2250 - inode->i_fop = &yaffs_dir_operations;
2251 - break;
2252 - case S_IFLNK: /* symlink */
2253 - inode->i_op = &yaffs_symlink_inode_operations;
2254 - break;
2255 - }
2256 -
2257 - yaffs_InodeToObjectLV(inode) = obj;
2258 -
2259 - obj->myInode = inode;
2260 -
2261 - } else {
2262 - T(YAFFS_TRACE_OS,
2263 - ("yaffs_FileInode invalid parameters\n"));
2264 - }
2265 -
2266 -}
2267 -
2268 -struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
2269 - yaffs_Object *obj)
2270 -{
2271 - struct inode *inode;
2272 -
2273 - if (!sb) {
2274 - T(YAFFS_TRACE_OS,
2275 - ("yaffs_get_inode for NULL super_block!!\n"));
2276 - return NULL;
2277 -
2278 - }
2279 -
2280 - if (!obj) {
2281 - T(YAFFS_TRACE_OS,
2282 - ("yaffs_get_inode for NULL object!!\n"));
2283 - return NULL;
2284 -
2285 - }
2286 -
2287 - T(YAFFS_TRACE_OS,
2288 - ("yaffs_get_inode for object %d\n", obj->objectId));
2289 -
2290 - inode = Y_IGET(sb, obj->objectId);
2291 - if (IS_ERR(inode))
2292 - return NULL;
2293 -
2294 - /* NB Side effect: iget calls back to yaffs_read_inode(). */
2295 - /* iget also increments the inode's i_count */
2296 - /* NB You can't be holding grossLock or deadlock will happen! */
2297 -
2298 - return inode;
2299 -}
2300 -
2301 -static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
2302 - loff_t *pos)
2303 -{
2304 - yaffs_Object *obj;
2305 - int nWritten, ipos;
2306 - struct inode *inode;
2307 - yaffs_Device *dev;
2308 -
2309 - obj = yaffs_DentryToObject(f->f_dentry);
2310 -
2311 - dev = obj->myDev;
2312 -
2313 - yaffs_GrossLock(dev);
2314 -
2315 - inode = f->f_dentry->d_inode;
2316 -
2317 - if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
2318 - ipos = inode->i_size;
2319 - else
2320 - ipos = *pos;
2321 -
2322 - if (!obj)
2323 - T(YAFFS_TRACE_OS,
2324 - ("yaffs_file_write: hey obj is null!\n"));
2325 - else
2326 - T(YAFFS_TRACE_OS,
2327 - ("yaffs_file_write about to write writing %zu bytes"
2328 - "to object %d at %d\n",
2329 - n, obj->objectId, ipos));
2330 -
2331 - nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0);
2332 -
2333 - T(YAFFS_TRACE_OS,
2334 - ("yaffs_file_write writing %zu bytes, %d written at %d\n",
2335 - n, nWritten, ipos));
2336 -
2337 - if (nWritten > 0) {
2338 - ipos += nWritten;
2339 - *pos = ipos;
2340 - if (ipos > inode->i_size) {
2341 - inode->i_size = ipos;
2342 - inode->i_blocks = (ipos + 511) >> 9;
2343 -
2344 - T(YAFFS_TRACE_OS,
2345 - ("yaffs_file_write size updated to %d bytes, "
2346 - "%d blocks\n",
2347 - ipos, (int)(inode->i_blocks)));
2348 - }
2349 -
2350 - }
2351 - yaffs_GrossUnlock(dev);
2352 - return nWritten == 0 ? -ENOSPC : nWritten;
2353 -}
2354 -
2355 -/* Space holding and freeing is done to ensure we have space available for write_begin/end */
2356 -/* For now we just assume few parallel writes and check against a small number. */
2357 -/* Todo: need to do this with a counter to handle parallel reads better */
2358 -
2359 -static ssize_t yaffs_hold_space(struct file *f)
2360 -{
2361 - yaffs_Object *obj;
2362 - yaffs_Device *dev;
2363 -
2364 - int nFreeChunks;
2365 -
2366 -
2367 - obj = yaffs_DentryToObject(f->f_dentry);
2368 -
2369 - dev = obj->myDev;
2370 -
2371 - yaffs_GrossLock(dev);
2372 -
2373 - nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
2374 -
2375 - yaffs_GrossUnlock(dev);
2376 -
2377 - return (nFreeChunks > 20) ? 1 : 0;
2378 -}
2379 -
2380 -static void yaffs_release_space(struct file *f)
2381 -{
2382 - yaffs_Object *obj;
2383 - yaffs_Device *dev;
2384 -
2385 -
2386 - obj = yaffs_DentryToObject(f->f_dentry);
2387 -
2388 - dev = obj->myDev;
2389 -
2390 - yaffs_GrossLock(dev);
2391 -
2392 -
2393 - yaffs_GrossUnlock(dev);
2394 -}
2395 -
2396 -static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
2397 -{
2398 - yaffs_Object *obj;
2399 - yaffs_Device *dev;
2400 - struct inode *inode = f->f_dentry->d_inode;
2401 - unsigned long offset, curoffs;
2402 - struct ylist_head *i;
2403 - yaffs_Object *l;
2404 -
2405 - char name[YAFFS_MAX_NAME_LENGTH + 1];
2406 -
2407 - obj = yaffs_DentryToObject(f->f_dentry);
2408 - dev = obj->myDev;
2409 -
2410 - yaffs_GrossLock(dev);
2411 -
2412 - offset = f->f_pos;
2413 -
2414 - T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset));
2415 -
2416 - if (offset == 0) {
2417 - T(YAFFS_TRACE_OS,
2418 - ("yaffs_readdir: entry . ino %d \n",
2419 - (int)inode->i_ino));
2420 - if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0)
2421 - goto out;
2422 - offset++;
2423 - f->f_pos++;
2424 - }
2425 - if (offset == 1) {
2426 - T(YAFFS_TRACE_OS,
2427 - ("yaffs_readdir: entry .. ino %d \n",
2428 - (int)f->f_dentry->d_parent->d_inode->i_ino));
2429 - if (filldir(dirent, "..", 2, offset,
2430 - f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
2431 - goto out;
2432 - offset++;
2433 - f->f_pos++;
2434 - }
2435 -
2436 - curoffs = 1;
2437 -
2438 - /* If the directory has changed since the open or last call to
2439 - readdir, rewind to after the 2 canned entries. */
2440 -
2441 - if (f->f_version != inode->i_version) {
2442 - offset = 2;
2443 - f->f_pos = offset;
2444 - f->f_version = inode->i_version;
2445 - }
2446 -
2447 - ylist_for_each(i, &obj->variant.directoryVariant.children) {
2448 - curoffs++;
2449 - if (curoffs >= offset) {
2450 - l = ylist_entry(i, yaffs_Object, siblings);
2451 -
2452 - yaffs_GetObjectName(l, name,
2453 - YAFFS_MAX_NAME_LENGTH + 1);
2454 - T(YAFFS_TRACE_OS,
2455 - ("yaffs_readdir: %s inode %d\n", name,
2456 - yaffs_GetObjectInode(l)));
2457 -
2458 - if (filldir(dirent,
2459 - name,
2460 - strlen(name),
2461 - offset,
2462 - yaffs_GetObjectInode(l),
2463 - yaffs_GetObjectType(l)) < 0)
2464 - goto up_and_out;
2465 -
2466 - offset++;
2467 - f->f_pos++;
2468 - }
2469 - }
2470 -
2471 -up_and_out:
2472 -out:
2473 - yaffs_GrossUnlock(dev);
2474 -
2475 - return 0;
2476 -}
2477 -
2478 -/*
2479 - * File creation. Allocate an inode, and we're done..
2480 - */
2481 -
2482 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
2483 -#define YCRED(x) x
2484 -#else
2485 -#define YCRED(x) (x->cred)
2486 -#endif
2487 -
2488 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2489 -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
2490 - dev_t rdev)
2491 -#else
2492 -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
2493 - int rdev)
2494 -#endif
2495 -{
2496 - struct inode *inode;
2497 -
2498 - yaffs_Object *obj = NULL;
2499 - yaffs_Device *dev;
2500 -
2501 - yaffs_Object *parent = yaffs_InodeToObject(dir);
2502 -
2503 - int error = -ENOSPC;
2504 - uid_t uid = YCRED(current)->fsuid;
2505 - gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
2506 -
2507 - if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
2508 - mode |= S_ISGID;
2509 -
2510 - if (parent) {
2511 - T(YAFFS_TRACE_OS,
2512 - ("yaffs_mknod: parent object %d type %d\n",
2513 - parent->objectId, parent->variantType));
2514 - } else {
2515 - T(YAFFS_TRACE_OS,
2516 - ("yaffs_mknod: could not get parent object\n"));
2517 - return -EPERM;
2518 - }
2519 -
2520 - T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, "
2521 - "mode %x dev %x\n",
2522 - dentry->d_name.name, mode, rdev));
2523 -
2524 - dev = parent->myDev;
2525 -
2526 - yaffs_GrossLock(dev);
2527 -
2528 - switch (mode & S_IFMT) {
2529 - default:
2530 - /* Special (socket, fifo, device...) */
2531 - T(YAFFS_TRACE_OS, ("yaffs_mknod: making special\n"));
2532 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2533 - obj = yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid,
2534 - gid, old_encode_dev(rdev));
2535 -#else
2536 - obj = yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid,
2537 - gid, rdev);
2538 -#endif
2539 - break;
2540 - case S_IFREG: /* file */
2541 - T(YAFFS_TRACE_OS, ("yaffs_mknod: making file\n"));
2542 - obj = yaffs_MknodFile(parent, dentry->d_name.name, mode, uid,
2543 - gid);
2544 - break;
2545 - case S_IFDIR: /* directory */
2546 - T(YAFFS_TRACE_OS,
2547 - ("yaffs_mknod: making directory\n"));
2548 - obj = yaffs_MknodDirectory(parent, dentry->d_name.name, mode,
2549 - uid, gid);
2550 - break;
2551 - case S_IFLNK: /* symlink */
2552 - T(YAFFS_TRACE_OS, ("yaffs_mknod: making symlink\n"));
2553 - obj = NULL; /* Do we ever get here? */
2554 - break;
2555 - }
2556 -
2557 - /* Can not call yaffs_get_inode() with gross lock held */
2558 - yaffs_GrossUnlock(dev);
2559 -
2560 - if (obj) {
2561 - inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
2562 - d_instantiate(dentry, inode);
2563 - T(YAFFS_TRACE_OS,
2564 - ("yaffs_mknod created object %d count = %d\n",
2565 - obj->objectId, atomic_read(&inode->i_count)));
2566 - error = 0;
2567 - } else {
2568 - T(YAFFS_TRACE_OS,
2569 - ("yaffs_mknod failed making object\n"));
2570 - error = -ENOMEM;
2571 - }
2572 -
2573 - return error;
2574 -}
2575 -
2576 -static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
2577 -{
2578 - int retVal;
2579 - T(YAFFS_TRACE_OS, ("yaffs_mkdir\n"));
2580 - retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
2581 - return retVal;
2582 -}
2583 -
2584 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2585 -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
2586 - struct nameidata *n)
2587 -#else
2588 -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
2589 -#endif
2590 -{
2591 - T(YAFFS_TRACE_OS, ("yaffs_create\n"));
2592 - return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
2593 -}
2594 -
2595 -static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
2596 -{
2597 - int retVal;
2598 -
2599 - yaffs_Device *dev;
2600 -
2601 - T(YAFFS_TRACE_OS,
2602 - ("yaffs_unlink %d:%s\n", (int)(dir->i_ino),
2603 - dentry->d_name.name));
2604 -
2605 - dev = yaffs_InodeToObject(dir)->myDev;
2606 -
2607 - yaffs_GrossLock(dev);
2608 -
2609 - retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name);
2610 -
2611 - if (retVal == YAFFS_OK) {
2612 - dentry->d_inode->i_nlink--;
2613 - dir->i_version++;
2614 - yaffs_GrossUnlock(dev);
2615 - mark_inode_dirty(dentry->d_inode);
2616 - return 0;
2617 - }
2618 - yaffs_GrossUnlock(dev);
2619 - return -ENOTEMPTY;
2620 -}
2621 -
2622 -/*
2623 - * Create a link...
2624 - */
2625 -static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
2626 - struct dentry *dentry)
2627 -{
2628 - struct inode *inode = old_dentry->d_inode;
2629 - yaffs_Object *obj = NULL;
2630 - yaffs_Object *link = NULL;
2631 - yaffs_Device *dev;
2632 -
2633 - T(YAFFS_TRACE_OS, ("yaffs_link\n"));
2634 -
2635 - obj = yaffs_InodeToObject(inode);
2636 - dev = obj->myDev;
2637 -
2638 - yaffs_GrossLock(dev);
2639 -
2640 - if (!S_ISDIR(inode->i_mode)) /* Don't link directories */
2641 - link = yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name,
2642 - obj);
2643 -
2644 - if (link) {
2645 - old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj);
2646 - d_instantiate(dentry, old_dentry->d_inode);
2647 - atomic_inc(&old_dentry->d_inode->i_count);
2648 - T(YAFFS_TRACE_OS,
2649 - ("yaffs_link link count %d i_count %d\n",
2650 - old_dentry->d_inode->i_nlink,
2651 - atomic_read(&old_dentry->d_inode->i_count)));
2652 - }
2653 -
2654 - yaffs_GrossUnlock(dev);
2655 -
2656 - if (link)
2657 - return 0;
2658 -
2659 - return -EPERM;
2660 -}
2661 -
2662 -static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
2663 - const char *symname)
2664 -{
2665 - yaffs_Object *obj;
2666 - yaffs_Device *dev;
2667 - uid_t uid = YCRED(current)->fsuid;
2668 - gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
2669 -
2670 - T(YAFFS_TRACE_OS, ("yaffs_symlink\n"));
2671 -
2672 - dev = yaffs_InodeToObject(dir)->myDev;
2673 - yaffs_GrossLock(dev);
2674 - obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name,
2675 - S_IFLNK | S_IRWXUGO, uid, gid, symname);
2676 - yaffs_GrossUnlock(dev);
2677 -
2678 - if (obj) {
2679 - struct inode *inode;
2680 -
2681 - inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
2682 - d_instantiate(dentry, inode);
2683 - T(YAFFS_TRACE_OS, ("symlink created OK\n"));
2684 - return 0;
2685 - } else {
2686 - T(YAFFS_TRACE_OS, ("symlink not created\n"));
2687 - }
2688 -
2689 - return -ENOMEM;
2690 -}
2691 -
2692 -static int yaffs_sync_object(struct file *file, struct dentry *dentry,
2693 - int datasync)
2694 -{
2695 -
2696 - yaffs_Object *obj;
2697 - yaffs_Device *dev;
2698 -
2699 - obj = yaffs_DentryToObject(dentry);
2700 -
2701 - dev = obj->myDev;
2702 -
2703 - T(YAFFS_TRACE_OS, ("yaffs_sync_object\n"));
2704 - yaffs_GrossLock(dev);
2705 - yaffs_FlushFile(obj, 1);
2706 - yaffs_GrossUnlock(dev);
2707 - return 0;
2708 -}
2709 -
2710 -/*
2711 - * The VFS layer already does all the dentry stuff for rename.
2712 - *
2713 - * NB: POSIX says you can rename an object over an old object of the same name
2714 - */
2715 -static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
2716 - struct inode *new_dir, struct dentry *new_dentry)
2717 -{
2718 - yaffs_Device *dev;
2719 - int retVal = YAFFS_FAIL;
2720 - yaffs_Object *target;
2721 -
2722 - T(YAFFS_TRACE_OS, ("yaffs_rename\n"));
2723 - dev = yaffs_InodeToObject(old_dir)->myDev;
2724 -
2725 - yaffs_GrossLock(dev);
2726 -
2727 - /* Check if the target is an existing directory that is not empty. */
2728 - target = yaffs_FindObjectByName(yaffs_InodeToObject(new_dir),
2729 - new_dentry->d_name.name);
2730 -
2731 -
2732 -
2733 - if (target && target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
2734 - !ylist_empty(&target->variant.directoryVariant.children)) {
2735 -
2736 - T(YAFFS_TRACE_OS, ("target is non-empty dir\n"));
2737 -
2738 - retVal = YAFFS_FAIL;
2739 - } else {
2740 - /* Now does unlinking internally using shadowing mechanism */
2741 - T(YAFFS_TRACE_OS, ("calling yaffs_RenameObject\n"));
2742 -
2743 - retVal = yaffs_RenameObject(yaffs_InodeToObject(old_dir),
2744 - old_dentry->d_name.name,
2745 - yaffs_InodeToObject(new_dir),
2746 - new_dentry->d_name.name);
2747 - }
2748 - yaffs_GrossUnlock(dev);
2749 -
2750 - if (retVal == YAFFS_OK) {
2751 - if (target) {
2752 - new_dentry->d_inode->i_nlink--;
2753 - mark_inode_dirty(new_dentry->d_inode);
2754 - }
2755 -
2756 - return 0;
2757 - } else {
2758 - return -ENOTEMPTY;
2759 - }
2760 -}
2761 -
2762 -static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
2763 -{
2764 - struct inode *inode = dentry->d_inode;
2765 - int error;
2766 - yaffs_Device *dev;
2767 -
2768 - T(YAFFS_TRACE_OS,
2769 - ("yaffs_setattr of object %d\n",
2770 - yaffs_InodeToObject(inode)->objectId));
2771 -
2772 - error = inode_change_ok(inode, attr);
2773 - if (error == 0) {
2774 - dev = yaffs_InodeToObject(inode)->myDev;
2775 - yaffs_GrossLock(dev);
2776 - if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) ==
2777 - YAFFS_OK) {
2778 - error = 0;
2779 - } else {
2780 - error = -EPERM;
2781 - }
2782 - yaffs_GrossUnlock(dev);
2783 - if (!error)
2784 - error = inode_setattr(inode, attr);
2785 - }
2786 - return error;
2787 -}
2788 -
2789 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2790 -static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
2791 -{
2792 - yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
2793 - struct super_block *sb = dentry->d_sb;
2794 -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
2795 -static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
2796 -{
2797 - yaffs_Device *dev = yaffs_SuperToDevice(sb);
2798 -#else
2799 -static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
2800 -{
2801 - yaffs_Device *dev = yaffs_SuperToDevice(sb);
2802 -#endif
2803 -
2804 - T(YAFFS_TRACE_OS, ("yaffs_statfs\n"));
2805 -
2806 - yaffs_GrossLock(dev);
2807 -
2808 - buf->f_type = YAFFS_MAGIC;
2809 - buf->f_bsize = sb->s_blocksize;
2810 - buf->f_namelen = 255;
2811 -
2812 - if (dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)) {
2813 - /* Do this if chunk size is not a power of 2 */
2814 -
2815 - uint64_t bytesInDev;
2816 - uint64_t bytesFree;
2817 -
2818 - bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock + 1))) *
2819 - ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
2820 -
2821 - do_div(bytesInDev, sb->s_blocksize); /* bytesInDev becomes the number of blocks */
2822 - buf->f_blocks = bytesInDev;
2823 -
2824 - bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
2825 - ((uint64_t)(dev->nDataBytesPerChunk));
2826 -
2827 - do_div(bytesFree, sb->s_blocksize);
2828 -
2829 - buf->f_bfree = bytesFree;
2830 -
2831 - } else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
2832 -
2833 - buf->f_blocks =
2834 - (dev->endBlock - dev->startBlock + 1) *
2835 - dev->nChunksPerBlock /
2836 - (sb->s_blocksize / dev->nDataBytesPerChunk);
2837 - buf->f_bfree =
2838 - yaffs_GetNumberOfFreeChunks(dev) /
2839 - (sb->s_blocksize / dev->nDataBytesPerChunk);
2840 - } else {
2841 - buf->f_blocks =
2842 - (dev->endBlock - dev->startBlock + 1) *
2843 - dev->nChunksPerBlock *
2844 - (dev->nDataBytesPerChunk / sb->s_blocksize);
2845 -
2846 - buf->f_bfree =
2847 - yaffs_GetNumberOfFreeChunks(dev) *
2848 - (dev->nDataBytesPerChunk / sb->s_blocksize);
2849 - }
2850 -
2851 - buf->f_files = 0;
2852 - buf->f_ffree = 0;
2853 - buf->f_bavail = buf->f_bfree;
2854 -
2855 - yaffs_GrossUnlock(dev);
2856 - return 0;
2857 -}
2858 -
2859 -
2860 -static int yaffs_do_sync_fs(struct super_block *sb)
2861 -{
2862 -
2863 - yaffs_Device *dev = yaffs_SuperToDevice(sb);
2864 - T(YAFFS_TRACE_OS, ("yaffs_do_sync_fs\n"));
2865 -
2866 - if (sb->s_dirt) {
2867 - yaffs_GrossLock(dev);
2868 -
2869 - if (dev) {
2870 - yaffs_FlushEntireDeviceCache(dev);
2871 - yaffs_CheckpointSave(dev);
2872 - }
2873 -
2874 - yaffs_GrossUnlock(dev);
2875 -
2876 - sb->s_dirt = 0;
2877 - }
2878 - return 0;
2879 -}
2880 -
2881 -
2882 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2883 -static void yaffs_write_super(struct super_block *sb)
2884 -#else
2885 -static int yaffs_write_super(struct super_block *sb)
2886 -#endif
2887 -{
2888 -
2889 - T(YAFFS_TRACE_OS, ("yaffs_write_super\n"));
2890 - if (yaffs_auto_checkpoint >= 2)
2891 - yaffs_do_sync_fs(sb);
2892 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
2893 - return 0;
2894 -#endif
2895 -}
2896 -
2897 -
2898 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
2899 -static int yaffs_sync_fs(struct super_block *sb, int wait)
2900 -#else
2901 -static int yaffs_sync_fs(struct super_block *sb)
2902 -#endif
2903 -{
2904 - T(YAFFS_TRACE_OS, ("yaffs_sync_fs\n"));
2905 -
2906 - if (yaffs_auto_checkpoint >= 1)
2907 - yaffs_do_sync_fs(sb);
2908 -
2909 - return 0;
2910 -}
2911 -
2912 -#ifdef YAFFS_USE_OWN_IGET
2913 -
2914 -static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
2915 -{
2916 - struct inode *inode;
2917 - yaffs_Object *obj;
2918 - yaffs_Device *dev = yaffs_SuperToDevice(sb);
2919 -
2920 - T(YAFFS_TRACE_OS,
2921 - ("yaffs_iget for %lu\n", ino));
2922 -
2923 - inode = iget_locked(sb, ino);
2924 - if (!inode)
2925 - return ERR_PTR(-ENOMEM);
2926 - if (!(inode->i_state & I_NEW))
2927 - return inode;
2928 -
2929 - /* NB This is called as a side effect of other functions, but
2930 - * we had to release the lock to prevent deadlocks, so
2931 - * need to lock again.
2932 - */
2933 -
2934 - yaffs_GrossLock(dev);
2935 -
2936 - obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
2937 -
2938 - yaffs_FillInodeFromObject(inode, obj);
2939 -
2940 - yaffs_GrossUnlock(dev);
2941 -
2942 - unlock_new_inode(inode);
2943 - return inode;
2944 -}
2945 -
2946 -#else
2947 -
2948 -static void yaffs_read_inode(struct inode *inode)
2949 -{
2950 - /* NB This is called as a side effect of other functions, but
2951 - * we had to release the lock to prevent deadlocks, so
2952 - * need to lock again.
2953 - */
2954 -
2955 - yaffs_Object *obj;
2956 - yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb);
2957 -
2958 - T(YAFFS_TRACE_OS,
2959 - ("yaffs_read_inode for %d\n", (int)inode->i_ino));
2960 -
2961 - yaffs_GrossLock(dev);
2962 -
2963 - obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
2964 -
2965 - yaffs_FillInodeFromObject(inode, obj);
2966 -
2967 - yaffs_GrossUnlock(dev);
2968 -}
2969 -
2970 -#endif
2971 -
2972 -static YLIST_HEAD(yaffs_dev_list);
2973 -
2974 -#if 0 /* not used */
2975 -static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
2976 -{
2977 - yaffs_Device *dev = yaffs_SuperToDevice(sb);
2978 -
2979 - if (*flags & MS_RDONLY) {
2980 - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice;
2981 -
2982 - T(YAFFS_TRACE_OS,
2983 - ("yaffs_remount_fs: %s: RO\n", dev->name));
2984 -
2985 - yaffs_GrossLock(dev);
2986 -
2987 - yaffs_FlushEntireDeviceCache(dev);
2988 -
2989 - yaffs_CheckpointSave(dev);
2990 -
2991 - if (mtd->sync)
2992 - mtd->sync(mtd);
2993 -
2994 - yaffs_GrossUnlock(dev);
2995 - } else {
2996 - T(YAFFS_TRACE_OS,
2997 - ("yaffs_remount_fs: %s: RW\n", dev->name));
2998 - }
2999 -
3000 - return 0;
3001 -}
3002 -#endif
3003 -
3004 -static void yaffs_put_super(struct super_block *sb)
3005 -{
3006 - yaffs_Device *dev = yaffs_SuperToDevice(sb);
3007 -
3008 - T(YAFFS_TRACE_OS, ("yaffs_put_super\n"));
3009 -
3010 - yaffs_GrossLock(dev);
3011 -
3012 - yaffs_FlushEntireDeviceCache(dev);
3013 -
3014 - yaffs_CheckpointSave(dev);
3015 -
3016 - if (dev->putSuperFunc)
3017 - dev->putSuperFunc(sb);
3018 -
3019 - yaffs_Deinitialise(dev);
3020 -
3021 - yaffs_GrossUnlock(dev);
3022 -
3023 - /* we assume this is protected by lock_kernel() in mount/umount */
3024 - ylist_del(&dev->devList);
3025 -
3026 - if (dev->spareBuffer) {
3027 - YFREE(dev->spareBuffer);
3028 - dev->spareBuffer = NULL;
3029 - }
3030 -
3031 - kfree(dev);
3032 -}
3033 -
3034 -
3035 -static void yaffs_MTDPutSuper(struct super_block *sb)
3036 -{
3037 - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice;
3038 -
3039 - if (mtd->sync)
3040 - mtd->sync(mtd);
3041 -
3042 - put_mtd_device(mtd);
3043 -}
3044 -
3045 -
3046 -static void yaffs_MarkSuperBlockDirty(void *vsb)
3047 -{
3048 - struct super_block *sb = (struct super_block *)vsb;
3049 -
3050 - T(YAFFS_TRACE_OS, ("yaffs_MarkSuperBlockDirty() sb = %p\n", sb));
3051 - if (sb)
3052 - sb->s_dirt = 1;
3053 -}
3054 -
3055 -typedef struct {
3056 - int inband_tags;
3057 - int skip_checkpoint_read;
3058 - int skip_checkpoint_write;
3059 - int no_cache;
3060 -} yaffs_options;
3061 -
3062 -#define MAX_OPT_LEN 20
3063 -static int yaffs_parse_options(yaffs_options *options, const char *options_str)
3064 -{
3065 - char cur_opt[MAX_OPT_LEN + 1];
3066 - int p;
3067 - int error = 0;
3068 -
3069 - /* Parse through the options which is a comma seperated list */
3070 -
3071 - while (options_str && *options_str && !error) {
3072 - memset(cur_opt, 0, MAX_OPT_LEN + 1);
3073 - p = 0;
3074 -
3075 - while (*options_str && *options_str != ',') {
3076 - if (p < MAX_OPT_LEN) {
3077 - cur_opt[p] = *options_str;
3078 - p++;
3079 - }
3080 - options_str++;
3081 - }
3082 -
3083 - if (!strcmp(cur_opt, "inband-tags"))
3084 - options->inband_tags = 1;
3085 - else if (!strcmp(cur_opt, "no-cache"))
3086 - options->no_cache = 1;
3087 - else if (!strcmp(cur_opt, "no-checkpoint-read"))
3088 - options->skip_checkpoint_read = 1;
3089 - else if (!strcmp(cur_opt, "no-checkpoint-write"))
3090 - options->skip_checkpoint_write = 1;
3091 - else if (!strcmp(cur_opt, "no-checkpoint")) {
3092 - options->skip_checkpoint_read = 1;
3093 - options->skip_checkpoint_write = 1;
3094 - } else {
3095 - printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",
3096 - cur_opt);
3097 - error = 1;
3098 - }
3099 - }
3100 -
3101 - return error;
3102 -}
3103 -
3104 -static struct super_block *yaffs_internal_read_super(int yaffsVersion,
3105 - struct super_block *sb,
3106 - void *data, int silent)
3107 -{
3108 - int nBlocks;
3109 - struct inode *inode = NULL;
3110 - struct dentry *root;
3111 - yaffs_Device *dev = 0;
3112 - char devname_buf[BDEVNAME_SIZE + 1];
3113 - struct mtd_info *mtd;
3114 - int err;
3115 - char *data_str = (char *)data;
3116 -
3117 - yaffs_options options;
3118 -
3119 - sb->s_magic = YAFFS_MAGIC;
3120 - sb->s_op = &yaffs_super_ops;
3121 - sb->s_flags |= MS_NOATIME;
3122 -
3123 - if (!sb)
3124 - printk(KERN_INFO "yaffs: sb is NULL\n");
3125 - else if (!sb->s_dev)
3126 - printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
3127 - else if (!yaffs_devname(sb, devname_buf))
3128 - printk(KERN_INFO "yaffs: devname is NULL\n");
3129 - else
3130 - printk(KERN_INFO "yaffs: dev is %d name is \"%s\"\n",
3131 - sb->s_dev,
3132 - yaffs_devname(sb, devname_buf));
3133 -
3134 - if (!data_str)
3135 - data_str = "";
3136 -
3137 - printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str);
3138 -
3139 - memset(&options, 0, sizeof(options));
3140 -
3141 - if (yaffs_parse_options(&options, data_str)) {
3142 - /* Option parsing failed */
3143 - return NULL;
3144 - }
3145 -
3146 -
3147 - sb->s_blocksize = PAGE_CACHE_SIZE;
3148 - sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
3149 - T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion));
3150 - T(YAFFS_TRACE_OS,
3151 - ("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize)));
3152 -
3153 -#ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
3154 - T(YAFFS_TRACE_OS,
3155 - ("yaffs: Write verification disabled. All guarantees "
3156 - "null and void\n"));
3157 -#endif
3158 -
3159 - T(YAFFS_TRACE_ALWAYS, ("yaffs: Attempting MTD mount on %u.%u, "
3160 - "\"%s\"\n",
3161 - MAJOR(sb->s_dev), MINOR(sb->s_dev),
3162 - yaffs_devname(sb, devname_buf)));
3163 -
3164 - /* Check it's an mtd device..... */
3165 - if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR)
3166 - return NULL; /* This isn't an mtd device */
3167 -
3168 - /* Get the device */
3169 - mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
3170 - if (!mtd) {
3171 - T(YAFFS_TRACE_ALWAYS,
3172 - ("yaffs: MTD device #%u doesn't appear to exist\n",
3173 - MINOR(sb->s_dev)));
3174 - return NULL;
3175 - }
3176 - /* Check it's NAND */
3177 - if (mtd->type != MTD_NANDFLASH) {
3178 - T(YAFFS_TRACE_ALWAYS,
3179 - ("yaffs: MTD device is not NAND it's type %d\n", mtd->type));
3180 - return NULL;
3181 - }
3182 -
3183 - T(YAFFS_TRACE_OS, (" erase %p\n", mtd->erase));
3184 - T(YAFFS_TRACE_OS, (" read %p\n", mtd->read));
3185 - T(YAFFS_TRACE_OS, (" write %p\n", mtd->write));
3186 - T(YAFFS_TRACE_OS, (" readoob %p\n", mtd->read_oob));
3187 - T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob));
3188 - T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad));
3189 - T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad));
3190 - T(YAFFS_TRACE_OS, (" %s %d\n", WRITE_SIZE_STR, WRITE_SIZE(mtd)));
3191 - T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize));
3192 - T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize));
3193 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
3194 - T(YAFFS_TRACE_OS, (" size %u\n", mtd->size));
3195 -#else
3196 - T(YAFFS_TRACE_OS, (" size %lld\n", mtd->size));
3197 -#endif
3198 -
3199 -#ifdef CONFIG_YAFFS_AUTO_YAFFS2
3200 -
3201 - if (yaffsVersion == 1 && WRITE_SIZE(mtd) >= 2048) {
3202 - T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs2\n"));
3203 - yaffsVersion = 2;
3204 - }
3205 -
3206 - /* Added NCB 26/5/2006 for completeness */
3207 - if (yaffsVersion == 2 && !options.inband_tags && WRITE_SIZE(mtd) == 512) {
3208 - T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs1\n"));
3209 - yaffsVersion = 1;
3210 - }
3211 -
3212 -#endif
3213 -
3214 - if (yaffsVersion == 2) {
3215 - /* Check for version 2 style functions */
3216 - if (!mtd->erase ||
3217 - !mtd->block_isbad ||
3218 - !mtd->block_markbad ||
3219 - !mtd->read ||
3220 - !mtd->write ||
3221 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3222 - !mtd->read_oob || !mtd->write_oob) {
3223 -#else
3224 - !mtd->write_ecc ||
3225 - !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
3226 -#endif
3227 - T(YAFFS_TRACE_ALWAYS,
3228 - ("yaffs: MTD device does not support required "
3229 - "functions\n"));;
3230 - return NULL;
3231 - }
3232 -
3233 - if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
3234 - mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
3235 - !options.inband_tags) {
3236 - T(YAFFS_TRACE_ALWAYS,
3237 - ("yaffs: MTD device does not have the "
3238 - "right page sizes\n"));
3239 - return NULL;
3240 - }
3241 - } else {
3242 - /* Check for V1 style functions */
3243 - if (!mtd->erase ||
3244 - !mtd->read ||
3245 - !mtd->write ||
3246 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3247 - !mtd->read_oob || !mtd->write_oob) {
3248 -#else
3249 - !mtd->write_ecc ||
3250 - !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
3251 -#endif
3252 - T(YAFFS_TRACE_ALWAYS,
3253 - ("yaffs: MTD device does not support required "
3254 - "functions\n"));;
3255 - return NULL;
3256 - }
3257 -
3258 - if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK ||
3259 - mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
3260 - T(YAFFS_TRACE_ALWAYS,
3261 - ("yaffs: MTD device does not support have the "
3262 - "right page sizes\n"));
3263 - return NULL;
3264 - }
3265 - }
3266 -
3267 - /* OK, so if we got here, we have an MTD that's NAND and looks
3268 - * like it has the right capabilities
3269 - * Set the yaffs_Device up for mtd
3270 - */
3271 -
3272 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
3273 - sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);
3274 -#else
3275 - sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);
3276 -#endif
3277 - if (!dev) {
3278 - /* Deep shit could not allocate device structure */
3279 - T(YAFFS_TRACE_ALWAYS,
3280 - ("yaffs_read_super: Failed trying to allocate "
3281 - "yaffs_Device. \n"));
3282 - return NULL;
3283 - }
3284 -
3285 - memset(dev, 0, sizeof(yaffs_Device));
3286 - dev->genericDevice = mtd;
3287 - dev->name = mtd->name;
3288 -
3289 - /* Set up the memory size parameters.... */
3290 -
3291 - nBlocks = YCALCBLOCKS(mtd->size, (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK));
3292 -
3293 - dev->startBlock = 0;
3294 - dev->endBlock = nBlocks - 1;
3295 - dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
3296 - dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
3297 - dev->nReservedBlocks = 5;
3298 - dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
3299 - dev->inbandTags = options.inband_tags;
3300 -
3301 - /* ... and the functions. */
3302 - if (yaffsVersion == 2) {
3303 - dev->writeChunkWithTagsToNAND =
3304 - nandmtd2_WriteChunkWithTagsToNAND;
3305 - dev->readChunkWithTagsFromNAND =
3306 - nandmtd2_ReadChunkWithTagsFromNAND;
3307 - dev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad;
3308 - dev->queryNANDBlock = nandmtd2_QueryNANDBlock;
3309 - dev->spareBuffer = YMALLOC(mtd->oobsize);
3310 - dev->isYaffs2 = 1;
3311 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3312 - dev->totalBytesPerChunk = mtd->writesize;
3313 - dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
3314 -#else
3315 - dev->totalBytesPerChunk = mtd->oobblock;
3316 - dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
3317 -#endif
3318 - nBlocks = YCALCBLOCKS(mtd->size, mtd->erasesize);
3319 -
3320 - dev->startBlock = 0;
3321 - dev->endBlock = nBlocks - 1;
3322 - } else {
3323 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3324 - /* use the MTD interface in yaffs_mtdif1.c */
3325 - dev->writeChunkWithTagsToNAND =
3326 - nandmtd1_WriteChunkWithTagsToNAND;
3327 - dev->readChunkWithTagsFromNAND =
3328 - nandmtd1_ReadChunkWithTagsFromNAND;
3329 - dev->markNANDBlockBad = nandmtd1_MarkNANDBlockBad;
3330 - dev->queryNANDBlock = nandmtd1_QueryNANDBlock;
3331 -#else
3332 - dev->writeChunkToNAND = nandmtd_WriteChunkToNAND;
3333 - dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND;
3334 -#endif
3335 - dev->isYaffs2 = 0;
3336 - }
3337 - /* ... and common functions */
3338 - dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
3339 - dev->initialiseNAND = nandmtd_InitialiseNAND;
3340 -
3341 - dev->putSuperFunc = yaffs_MTDPutSuper;
3342 -
3343 - dev->superBlock = (void *)sb;
3344 - dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty;
3345 -
3346 -
3347 -#ifndef CONFIG_YAFFS_DOES_ECC
3348 - dev->useNANDECC = 1;
3349 -#endif
3350 -
3351 -#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
3352 - dev->wideTnodesDisabled = 1;
3353 -#endif
3354 -
3355 - dev->skipCheckpointRead = options.skip_checkpoint_read;
3356 - dev->skipCheckpointWrite = options.skip_checkpoint_write;
3357 -
3358 - /* we assume this is protected by lock_kernel() in mount/umount */
3359 - ylist_add_tail(&dev->devList, &yaffs_dev_list);
3360 -
3361 - init_MUTEX(&dev->grossLock);
3362 -
3363 - yaffs_GrossLock(dev);
3364 -
3365 - err = yaffs_GutsInitialise(dev);
3366 -
3367 - T(YAFFS_TRACE_OS,
3368 - ("yaffs_read_super: guts initialised %s\n",
3369 - (err == YAFFS_OK) ? "OK" : "FAILED"));
3370 -
3371 - /* Release lock before yaffs_get_inode() */
3372 - yaffs_GrossUnlock(dev);
3373 -
3374 - /* Create root inode */
3375 - if (err == YAFFS_OK)
3376 - inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,
3377 - yaffs_Root(dev));
3378 -
3379 - if (!inode)
3380 - return NULL;
3381 -
3382 - inode->i_op = &yaffs_dir_inode_operations;
3383 - inode->i_fop = &yaffs_dir_operations;
3384 -
3385 - T(YAFFS_TRACE_OS, ("yaffs_read_super: got root inode\n"));
3386 -
3387 - root = d_alloc_root(inode);
3388 -
3389 - T(YAFFS_TRACE_OS, ("yaffs_read_super: d_alloc_root done\n"));
3390 -
3391 - if (!root) {
3392 - iput(inode);
3393 - return NULL;
3394 - }
3395 - sb->s_root = root;
3396 - sb->s_dirt = !dev->isCheckpointed;
3397 - T(YAFFS_TRACE_ALWAYS,
3398 - ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed));
3399 -
3400 - T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));
3401 - return sb;
3402 -}
3403 -
3404 -
3405 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
3406 -static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
3407 - int silent)
3408 -{
3409 - return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
3410 -}
3411 -
3412 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
3413 -static int yaffs_read_super(struct file_system_type *fs,
3414 - int flags, const char *dev_name,
3415 - void *data, struct vfsmount *mnt)
3416 -{
3417 -
3418 - return get_sb_bdev(fs, flags, dev_name, data,
3419 - yaffs_internal_read_super_mtd, mnt);
3420 -}
3421 -#else