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