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