Changeset 5591477 in freewrt for target/linux
- Timestamp:
- Dec 10, 2006, 5:33:25 AM (19 years ago)
- Children:
- 29e4d6d
- Parents:
- 8808337
- File:
-
- 1 edited
-
target/linux/rb-2.6/patches/140-yaffs2.patch (modified) (200 diffs)
Legend:
- Unmodified
- Added
- Removed
-
target/linux/rb-2.6/patches/140-yaffs2.patch
r8808337 r5591477 1 diff -NaurB linux-2.6.18.2/fs/Kconfig linux-2.6.18.2.patched/fs/Kconfig2 --- linux-2.6.18.2/fs/Kconfig 2006-11-04 02:33:58.000000000 +01003 +++ linux-2.6 .18.2.patched/fs/Kconfig 2006-11-25 00:15:31.000000000 +01004 @@ -1045,6 +1045,1 0@@1 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Kconfig linux-2.6-rb/linux-2.6.18.2/fs/Kconfig 2 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Kconfig 2006-11-04 02:33:58.000000000 +0100 3 +++ linux-2.6-rb/linux-2.6.18.2/fs/Kconfig 2006-12-10 03:57:50.000000000 +0100 4 @@ -1045,6 +1045,15 @@ 5 5 To compile the EFS file system support as a module, choose M here: the 6 6 module will be called efs. 7 7 8 + 9 +# Patched by YAFFS 10 +source "fs/yaffs2/Kconfig" 8 +config YAFFS_FS 9 + tristate "Yet Another Flash File System (YAFFS) support" 10 + depends on MTD 11 + help 12 + JFFS is the Journaling Flash File System developed by Axis 13 + Communications in Sweden, aimed at providing a crash/powerdown-safe 14 + file system for disk-less embedded devices. Further information is 15 + available at (<http://developer.axis.com/software/jffs/>). 11 16 + 12 17 config JFFS_FS 13 18 tristate "Journalling Flash File System (JFFS) support" 14 19 depends on MTD 15 diff -NaurB linux-2.6.18.2/fs/Makefile linux-2.6.18.2.patched/fs/Makefile 16 --- linux-2.6.18.2/fs/Makefile 2006-11-04 02:33:58.000000000 +0100 17 +++ linux-2.6.18.2.patched/fs/Makefile 2006-11-25 00:15:31.000000000 +0100 18 @@ -102,3 +102,6 @@ 19 obj-$(CONFIG_HPPFS) += hppfs/ 20 obj-$(CONFIG_DEBUG_FS) += debugfs/ 21 obj-$(CONFIG_OCFS2_FS) += ocfs2/ 22 + 23 +# Patched by YAFFS 24 +obj-$(CONFIG_YAFFS_FS) += yaffs2/ 25 diff -NaurB linux-2.6.18.2/fs/yaffs2/devextras.h linux-2.6.18.2.patched/fs/yaffs2/devextras.h 26 --- linux-2.6.18.2/fs/yaffs2/devextras.h 1970-01-01 01:00:00.000000000 +0100 27 +++ linux-2.6.18.2.patched/fs/yaffs2/devextras.h 2006-11-25 00:15:32.000000000 +0100 28 @@ -0,0 +1,265 @@ 20 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Makefile linux-2.6-rb/linux-2.6.18.2/fs/Makefile 21 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Makefile 2006-11-04 02:33:58.000000000 +0100 22 +++ linux-2.6-rb/linux-2.6.18.2/fs/Makefile 2006-12-10 03:57:50.000000000 +0100 23 @@ -84,6 +84,7 @@ 24 obj-$(CONFIG_EFS_FS) += efs/ 25 obj-$(CONFIG_JFFS_FS) += jffs/ 26 obj-$(CONFIG_JFFS2_FS) += jffs2/ 27 +obj-$(CONFIG_YAFFS_FS) += yaffs/ 28 obj-$(CONFIG_AFFS_FS) += affs/ 29 obj-$(CONFIG_ROMFS_FS) += romfs/ 30 obj-$(CONFIG_QNX4FS_FS) += qnx4/ 31 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h 32 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h 1970-01-01 01:00:00.000000000 +0100 33 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h 2006-12-10 03:57:50.000000000 +0100 34 @@ -0,0 +1,271 @@ 29 35 +/* 30 36 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 46 52 + * applications. 47 53 + * 48 + * $Id: devextras.h,v 1. 2 2005/08/11 02:37:49 martyExp $54 + * $Id: devextras.h,v 1.1 2004/11/03 08:14:07 charles Exp $ 49 55 + * 50 56 + */ 51 + 57 + 52 58 +#ifndef __EXTRAS_H__ 53 59 +#define __EXTRAS_H__ … … 60 66 +#if !(defined __KERNEL__) || (defined WIN32) 61 67 + 62 +/* User space defines */ 63 + 64 +typedef unsigned char __u8; 65 +typedef unsigned short __u16; 66 +typedef unsigned __u32; 68 +// User space defines 69 + 70 +typedef unsigned char __u8; 71 +typedef unsigned short __u16; 72 +typedef unsigned __u32; 73 + 67 74 + 68 75 +/* … … 75 82 + * using the generic single-entry routines. 76 83 + */ 77 + 78 +#define prefetch(x) 1 84 + 85 + #define prefetch(x) 1 86 + 79 87 + 80 88 +struct list_head { … … 97 105 + * the prev/next entries already! 98 106 + */ 99 +static __inline__ void __list_add(struct list_head * new,100 + struct list_head *prev,101 + struct list_head *next)107 +static __inline__ void __list_add(struct list_head * new, 108 + struct list_head * prev, 109 + struct list_head * next) 102 110 +{ 103 111 + next->prev = new; … … 128 136 + * This is useful for implementing queues. 129 137 + */ 130 +static __inline__ void list_add_tail(struct list_head *new, 131 + struct list_head *head) 138 +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) 132 139 +{ 133 140 + __list_add(new, head->prev, head); … … 141 148 + * the prev/next entries already! 142 149 + */ 143 +static __inline__ void __list_del(struct list_head * prev,144 + struct list_head * next)150 +static __inline__ void __list_del(struct list_head * prev, 151 + struct list_head * next) 145 152 +{ 146 153 + next->prev = prev; … … 151 158 + * list_del - deletes entry from list. 152 159 + * @entry: the element to delete from the list. 153 + * Note: list_empty on entry does not return true after this, the entry is 154 + * in an undefined state. 160 + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. 155 161 + */ 156 162 +static __inline__ void list_del(struct list_head *entry) … … 183 189 + * @head: the place to add it in the first list. 184 190 + */ 185 +static __inline__ void list_splice(struct list_head *list, 186 + struct list_head *head) 191 +static __inline__ void list_splice(struct list_head *list, struct list_head *head) 187 192 +{ 188 193 + struct list_head *first = list->next; … … 219 224 + 220 225 +/** 221 + * list_for_each_safe - iterate over a list safe against removal 222 + * of list entry 226 + * list_for_each_safe - iterate over a list safe against removal of list entry 223 227 + * @pos: the &struct list_head to use as a loop counter. 224 228 + * @n: another &struct list_head to use as temporary storage … … 228 232 + for (pos = (head)->next, n = pos->next; pos != (head); \ 229 233 + pos = n, n = pos->next) 234 + 235 + 236 + 230 237 + 231 238 +/* … … 262 269 +#define ATTR_ATTR_FLAG 1024 263 270 + 271 + 264 272 +struct iattr { 265 + unsigned int ia_valid;266 + unsigned ia_mode;267 + unsigned ia_uid;268 + unsigned ia_gid;269 + unsigned ia_size;270 + unsigned ia_atime;271 + unsigned ia_mtime;272 + unsigned ia_ctime;273 + unsigned int ia_attr_flags;273 + unsigned int ia_valid; 274 + unsigned ia_mode; 275 + unsigned ia_uid; 276 + unsigned ia_gid; 277 + unsigned ia_size; 278 + unsigned ia_atime; 279 + unsigned ia_mtime; 280 + unsigned ia_ctime; 281 + unsigned int ia_attr_flags; 274 282 +}; 275 283 + 276 284 +#define KERN_DEBUG 285 + 277 286 + 278 287 +#else … … 287 296 +#endif 288 297 + 298 + 299 + 289 300 +#if defined WIN32 290 301 +#undef new 291 +#endif 292 + 293 +#endif 294 diff -NaurB linux-2.6.18.2/fs/yaffs2/Kconfig linux-2.6.18.2.patched/fs/yaffs2/Kconfig 295 --- linux-2.6.18.2/fs/yaffs2/Kconfig 1970-01-01 01:00:00.000000000 +0100 296 +++ linux-2.6.18.2.patched/fs/yaffs2/Kconfig 2006-11-25 00:15:31.000000000 +0100 297 @@ -0,0 +1,135 @@ 302 +#endif 303 + 304 +#endif 305 + 306 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile 307 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile 1970-01-01 01:00:00.000000000 +0100 308 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile 2006-12-10 03:57:50.000000000 +0100 309 @@ -0,0 +1,18 @@ 298 310 +# 299 +# YAFFS file system configurations311 +# Makefile for the Linux msdos filesystem routines. 300 312 +# 301 + 302 +config YAFFS_FS 303 + tristate "YAFFS2 file system support" 304 + default n 305 + depends on MTD 306 + select YAFFS_YAFFS1 307 + select YAFFS_YAFFS2 308 + help 309 + YAFFS2, or Yet Another Flash Filing System, is a filing system 310 + optimised for NAND Flash chips. 311 + 312 + To compile the YAFFS2 file system support as a module, choose M here: 313 + the module will be called yaffs2. 314 + 315 + If unsure, say N. 316 + 317 + Further information on YAFFS2 is available at 318 + <http://www.aleph1.co.uk/yaffs/>. 319 + 320 +config YAFFS_YAFFS1 321 + bool "512 byte / page devices" 322 + depends on YAFFS_FS 323 + default y 324 + help 325 + Enable YAFFS1 support -- yaffs for 512 byte / page devices 326 + 327 + If unsure, say Y. 328 + 329 +config YAFFS_DOES_ECC 330 + bool "Lets Yaffs do its own ECC" 331 + depends on YAFFS_FS && YAFFS_YAFFS1 332 + default n 333 + help 334 + This enables Yaffs to use its own ECC functions instead of using 335 + the ones from the generic MTD-NAND driver. 336 + 337 + If unsure, say N. 338 + 339 +config YAFFS_ECC_WRONG_ORDER 340 + bool "Use the same ecc byte order as Steven Hill's nand_ecc.c" 341 + depends on YAFFS_FS && YAFFS_DOES_ECC 342 + default n 343 + help 344 + This makes yaffs_ecc.c use the same ecc byte order as 345 + Steven Hill's nand_ecc.c. If not set, then you get the 346 + same ecc byte order as SmartMedia. 347 + 348 + If unsure, say N. 349 + 350 +config YAFFS_YAFFS2 351 + bool "2048 byte (or larger) / page devices" 352 + depends on YAFFS_FS 353 + default y 354 + help 355 + Enable YAFFS2 support -- yaffs for >= 2048 byte / page larger devices 356 + 357 + If unsure, say Y. 358 + 359 +config YAFFS_AUTO_YAFFS2 360 + bool "Autoselect yaffs2 format" 361 + depends on YAFFS_YAFFS2 362 + default y 363 + help 364 + Without this, you need to explicitely use yaffs2 as the file 365 + system type. With this, you can say "yaffs" and yaffs or yaffs2 366 + will be used depending on the device page size. 367 + 368 + If unsure, say Y. 369 + 370 +config YAFFS_DISABLE_LAZY_LOAD 371 + bool "Disable lazy loading" 372 + depends on YAFFS_YAFFS2 373 + default n 374 + help 375 + "Lazy loading" defers loading file details until they are 376 + required. This saves mount time, but makes the first look-up 377 + a bit longer. 378 + 379 + Lazy loading will only happen if enabled by this option being 'n' 380 + and if the appropriate tags are available, else yaffs2 will 381 + automatically fall back to immediate loading and do the right 382 + thing. 383 + 384 + Lazy laoding will be required by checkpointing. 385 + 386 + Setting this to 'y' will disable lazy loading. 387 + 388 + If unsure, say N. 389 + 390 +config YAFFS_DISABLE_WIDE_TNODES 391 + bool "Turn off wide tnodes" 392 + depends on YAFFS_FS 393 + default n 394 + help 395 + Wide tnodes are only used for large NAND arrays (>=32MB for 396 + 512-byte page devices and >=128MB for 2k page devices). They use 397 + slightly more RAM but are faster since they eliminate chunk group 398 + searching. 399 + 400 + Setting this to 'y' will force tnode width to 16 bits and make 401 + large arrays slower. 402 + 403 + If unsure, say N. 404 + 405 +config YAFFS_ALWAYS_CHECK_CHUNK_ERASED 406 + bool "Force chunk erase check" 407 + depends on YAFFS_FS 408 + default n 409 + help 410 + Normally YAFFS only checks chunks before writing until an erased 411 + chunk is found. This helps to detect any partially written chunks 412 + that might have happened due to power loss. 413 + 414 + Enabling this forces on the test that chunks are erased in flash 415 + before writing to them. This takes more time but is potentially a 416 + bit more secure. 417 + 418 + Suggest setting Y during development and ironing out driver issues 419 + etc. Suggest setting to N if you want faster writing. 420 + 421 + If unsure, say Y. 422 + 423 +config YAFFS_SHORT_NAMES_IN_RAM 424 + bool "Cache short names in RAM" 425 + depends on YAFFS_FS 426 + default y 427 + help 428 + If this config is set, then short names are stored with the 429 + yaffs_Object. This costs an extra 16 bytes of RAM per object, 430 + but makes look-ups faster. 431 + 432 + If unsure, say Y. 433 diff -NaurB linux-2.6.18.2/fs/yaffs2/Makefile linux-2.6.18.2.patched/fs/yaffs2/Makefile 434 --- linux-2.6.18.2/fs/yaffs2/Makefile 1970-01-01 01:00:00.000000000 +0100 435 +++ linux-2.6.18.2.patched/fs/yaffs2/Makefile 2006-11-25 00:15:31.000000000 +0100 436 @@ -0,0 +1,10 @@ 313 +# Note! Dependencies are done automagically by 'make dep', which also 314 +# removes any old dependencies. DON'T put your own dependencies here 315 +# unless it's something special (ie not a .c file). 437 316 +# 438 +# Makefile for the linux YAFFS filesystem routines. 439 +# 317 +# Note 2! The CFLAGS definitions are now in the main makefile. 318 + 319 + 320 +EXTRA_CFLAGS += -DCONFIG_YAFFS_YAFFS1 -DCONFIG_YAFFS_YAFFS2 321 + 440 322 + 441 323 +obj-$(CONFIG_YAFFS_FS) += yaffs.o 442 324 + 443 +yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o 444 +yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o 445 +yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o 446 +yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o 447 diff -NaurB linux-2.6.18.2/fs/yaffs2/moduleconfig.h linux-2.6.18.2.patched/fs/yaffs2/moduleconfig.h 448 --- linux-2.6.18.2/fs/yaffs2/moduleconfig.h 1970-01-01 01:00:00.000000000 +0100 449 +++ linux-2.6.18.2.patched/fs/yaffs2/moduleconfig.h 2006-11-25 00:15:32.000000000 +0100 450 @@ -0,0 +1,32 @@ 451 +#ifndef __YAFFS_CONFIG_H__ 452 +#define __YAFFS_CONFIG_H__ 453 + 454 +#ifdef YAFFS_OUT_OF_TREE 455 + 456 +/* DO NOT UNSET THESE THREE. YAFFS2 will not compile if you do. */ 457 +#define CONFIG_YAFFS_FS 458 +#define CONFIG_YAFFS_YAFFS1 459 +#define CONFIG_YAFFS_YAFFS2 460 + 461 +/* These options are independent of each other. Select those that matter. */ 462 + 463 +/* Default: Not selected */ 464 +/* Meaning: Yaffs does its own ECC, rather than using MTD ECC */ 465 +//#define CONFIG_YAFFS_DOES_ECC 466 + 467 +/* Default: Not selected */ 468 +/* Meaning: ECC byte order is 'wrong'. Only meaningful if */ 469 +/* CONFIG_YAFFS_DOES_ECC is set */ 470 +//#define CONFIG_YAFFS_ECC_WRONG_ORDER 471 + 472 +/* Default: Selected */ 473 +/* Meaning: Disables testing whether chunks are erased before writing to them*/ 474 +#define CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK 475 + 476 +/* Default: Selected */ 477 +/* Meaning: Cache short names, taking more RAM, but faster look-ups */ 478 +#define CONFIG_YAFFS_SHORT_NAMES_IN_RAM 479 + 480 +#endif /* YAFFS_OUT_OF_TREE */ 481 + 482 +#endif /* __YAFFS_CONFIG_H__ */ 483 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.c 484 --- linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.c 1970-01-01 01:00:00.000000000 +0100 485 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.c 2006-11-25 00:15:31.000000000 +0100 486 @@ -0,0 +1,384 @@ 487 +/* YAFFS: Yet another FFS. A NAND-flash specific file system. 488 + * 489 + * Copyright (C) 2002 Aleph One Ltd. 490 + * for Toby Churchill Ltd and Brightstar Engineering 491 + * 492 + * Created by Charles Manning <charles@aleph1.co.uk> 493 + * 494 + * This program is free software; you can redistribute it and/or modify 495 + * it under the terms of the GNU General Public License version 2 as 496 + * published by the Free Software Foundation. 497 + * 498 + */ 499 + 500 +const char *yaffs_checkptrw_c_version = 501 + "$Id: yaffs_checkptrw.c,v 1.11 2006/11/11 23:27:04 charles Exp $"; 502 + 503 + 504 +#include "yaffs_checkptrw.h" 505 + 506 + 507 +static int yaffs_CheckpointSpaceOk(yaffs_Device *dev) 508 +{ 509 + 510 + int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks; 511 + 512 + T(YAFFS_TRACE_CHECKPOINT, 513 + (TSTR("checkpt blocks available = %d" TENDSTR), 514 + blocksAvailable)); 515 + 516 + 517 + return (blocksAvailable <= 0) ? 0 : 1; 518 +} 519 + 520 + 521 + 522 +static int yaffs_CheckpointErase(yaffs_Device *dev) 523 +{ 524 + 525 + int i; 526 + 527 + 528 + if(!dev->eraseBlockInNAND) 529 + return 0; 530 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR), 531 + dev->internalStartBlock,dev->internalEndBlock)); 532 + 533 + for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { 534 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); 535 + if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){ 536 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt block %d"TENDSTR),i)); 537 + if(dev->eraseBlockInNAND(dev,i- dev->blockOffset /* realign */)){ 538 + bi->blockState = YAFFS_BLOCK_STATE_EMPTY; 539 + dev->nErasedBlocks++; 540 + dev->nFreeChunks += dev->nChunksPerBlock; 541 + } 542 + else { 543 + dev->markNANDBlockBad(dev,i); 544 + bi->blockState = YAFFS_BLOCK_STATE_DEAD; 545 + } 546 + } 547 + } 548 + 549 + dev->blocksInCheckpoint = 0; 550 + 551 + return 1; 552 +} 553 + 554 + 555 +static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev) 556 +{ 557 + int i; 558 + int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks; 559 + T(YAFFS_TRACE_CHECKPOINT, 560 + (TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR), 561 + dev->nErasedBlocks,dev->nReservedBlocks,blocksAvailable,dev->checkpointNextBlock)); 562 + 563 + if(dev->checkpointNextBlock >= 0 && 564 + dev->checkpointNextBlock <= dev->internalEndBlock && 565 + blocksAvailable > 0){ 566 + 567 + for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ 568 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); 569 + if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){ 570 + dev->checkpointNextBlock = i + 1; 571 + dev->checkpointCurrentBlock = i; 572 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("allocating checkpt block %d"TENDSTR),i)); 573 + return; 574 + } 575 + } 576 + } 577 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR))); 578 + 579 + dev->checkpointNextBlock = -1; 580 + dev->checkpointCurrentBlock = -1; 581 +} 582 + 583 +static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev) 584 +{ 585 + int i; 586 + yaffs_ExtendedTags tags; 587 + 588 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: start: blocks %d next %d" TENDSTR), 589 + dev->blocksInCheckpoint, dev->checkpointNextBlock)); 590 + 591 + if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks) 592 + for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ 593 + int chunk = i * dev->nChunksPerBlock; 594 + int realignedChunk = chunk - dev->chunkOffset; 595 + 596 + dev->readChunkWithTagsFromNAND(dev,realignedChunk,NULL,&tags); 597 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR), 598 + i, tags.objectId,tags.sequenceNumber,tags.eccResult)); 599 + 600 + if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){ 601 + /* Right kind of block */ 602 + dev->checkpointNextBlock = tags.objectId; 603 + dev->checkpointCurrentBlock = i; 604 + dev->checkpointBlockList[dev->blocksInCheckpoint] = i; 605 + dev->blocksInCheckpoint++; 606 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("found checkpt block %d"TENDSTR),i)); 607 + return; 608 + } 609 + } 610 + 611 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("found no more checkpt blocks"TENDSTR))); 612 + 613 + dev->checkpointNextBlock = -1; 614 + dev->checkpointCurrentBlock = -1; 615 +} 616 + 617 + 618 +int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting) 619 +{ 620 + 621 + /* Got the functions we need? */ 622 + if (!dev->writeChunkWithTagsToNAND || 623 + !dev->readChunkWithTagsFromNAND || 624 + !dev->eraseBlockInNAND || 625 + !dev->markNANDBlockBad) 626 + return 0; 627 + 628 + if(forWriting && !yaffs_CheckpointSpaceOk(dev)) 629 + return 0; 630 + 631 + if(!dev->checkpointBuffer) 632 + dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk); 633 + if(!dev->checkpointBuffer) 634 + return 0; 635 + 636 + 637 + dev->checkpointPageSequence = 0; 638 + 639 + dev->checkpointOpenForWrite = forWriting; 640 + 641 + dev->checkpointByteCount = 0; 642 + dev->checkpointCurrentBlock = -1; 643 + dev->checkpointCurrentChunk = -1; 644 + dev->checkpointNextBlock = dev->internalStartBlock; 645 + 646 + /* Erase all the blocks in the checkpoint area */ 647 + if(forWriting){ 648 + memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); 649 + dev->checkpointByteOffset = 0; 650 + return yaffs_CheckpointErase(dev); 651 + 652 + 653 + } else { 654 + int i; 655 + /* Set to a value that will kick off a read */ 656 + dev->checkpointByteOffset = dev->nDataBytesPerChunk; 657 + /* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully) 658 + * going to be way more than we need */ 659 + dev->blocksInCheckpoint = 0; 660 + dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2; 661 + dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks); 662 + for(i = 0; i < dev->checkpointMaxBlocks; i++) 663 + dev->checkpointBlockList[i] = -1; 664 + } 665 + 666 + return 1; 667 +} 668 + 669 +static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev) 670 +{ 671 + 672 + int chunk; 673 + int realignedChunk; 674 + 675 + yaffs_ExtendedTags tags; 676 + 677 + if(dev->checkpointCurrentBlock < 0){ 678 + yaffs_CheckpointFindNextErasedBlock(dev); 679 + dev->checkpointCurrentChunk = 0; 680 + } 681 + 682 + if(dev->checkpointCurrentBlock < 0) 683 + return 0; 684 + 685 + tags.chunkDeleted = 0; 686 + tags.objectId = dev->checkpointNextBlock; /* Hint to next place to look */ 687 + tags.chunkId = dev->checkpointPageSequence + 1; 688 + tags.sequenceNumber = YAFFS_SEQUENCE_CHECKPOINT_DATA; 689 + tags.byteCount = dev->nDataBytesPerChunk; 690 + if(dev->checkpointCurrentChunk == 0){ 691 + /* First chunk we write for the block? Set block state to 692 + checkpoint */ 693 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointCurrentBlock); 694 + bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT; 695 + dev->blocksInCheckpoint++; 696 + } 697 + 698 + chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk; 699 + 700 + 701 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR), 702 + chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId)); 703 + 704 + realignedChunk = chunk - dev->chunkOffset; 705 + 706 + dev->writeChunkWithTagsToNAND(dev,realignedChunk,dev->checkpointBuffer,&tags); 707 + dev->checkpointByteOffset = 0; 708 + dev->checkpointPageSequence++; 709 + dev->checkpointCurrentChunk++; 710 + if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){ 711 + dev->checkpointCurrentChunk = 0; 712 + dev->checkpointCurrentBlock = -1; 713 + } 714 + memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); 715 + 716 + return 1; 717 +} 718 + 719 + 720 +int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes) 721 +{ 722 + int i=0; 723 + int ok = 1; 724 + 725 + 726 + __u8 * dataBytes = (__u8 *)data; 727 + 728 + 729 + 730 + if(!dev->checkpointBuffer) 731 + return 0; 732 + 733 + while(i < nBytes && ok) { 734 + 735 + 736 + 737 + dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ; 738 + dev->checkpointByteOffset++; 739 + i++; 740 + dataBytes++; 741 + dev->checkpointByteCount++; 742 + 743 + 744 + if(dev->checkpointByteOffset < 0 || 745 + dev->checkpointByteOffset >= dev->nDataBytesPerChunk) 746 + ok = yaffs_CheckpointFlushBuffer(dev); 747 + 748 + } 749 + 750 + return i; 751 +} 752 + 753 +int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes) 754 +{ 755 + int i=0; 756 + int ok = 1; 757 + yaffs_ExtendedTags tags; 758 + 759 + 760 + int chunk; 761 + int realignedChunk; 762 + 763 + __u8 *dataBytes = (__u8 *)data; 764 + 765 + if(!dev->checkpointBuffer) 766 + return 0; 767 + 768 + while(i < nBytes && ok) { 769 + 770 + 771 + if(dev->checkpointByteOffset < 0 || 772 + dev->checkpointByteOffset >= dev->nDataBytesPerChunk) { 773 + 774 + if(dev->checkpointCurrentBlock < 0){ 775 + yaffs_CheckpointFindNextCheckpointBlock(dev); 776 + dev->checkpointCurrentChunk = 0; 777 + } 778 + 779 + if(dev->checkpointCurrentBlock < 0) 780 + ok = 0; 781 + else { 782 + 783 + chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + 784 + dev->checkpointCurrentChunk; 785 + 786 + realignedChunk = chunk - dev->chunkOffset; 787 + 788 + /* read in the next chunk */ 789 + /* printf("read checkpoint page %d\n",dev->checkpointPage); */ 790 + dev->readChunkWithTagsFromNAND(dev, realignedChunk, 791 + dev->checkpointBuffer, 792 + &tags); 793 + 794 + if(tags.chunkId != (dev->checkpointPageSequence + 1) || 795 + tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) 796 + ok = 0; 797 + 798 + dev->checkpointByteOffset = 0; 799 + dev->checkpointPageSequence++; 800 + dev->checkpointCurrentChunk++; 801 + 802 + if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock) 803 + dev->checkpointCurrentBlock = -1; 804 + } 805 + } 806 + 807 + if(ok){ 808 + *dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset]; 809 + dev->checkpointByteOffset++; 810 + i++; 811 + dataBytes++; 812 + dev->checkpointByteCount++; 813 + } 814 + } 815 + 816 + return i; 817 +} 818 + 819 +int yaffs_CheckpointClose(yaffs_Device *dev) 820 +{ 821 + 822 + if(dev->checkpointOpenForWrite){ 823 + if(dev->checkpointByteOffset != 0) 824 + yaffs_CheckpointFlushBuffer(dev); 825 + } else { 826 + int i; 827 + for(i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++){ 828 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointBlockList[i]); 829 + if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY) 830 + bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT; 831 + else { 832 + // Todo this looks odd... 833 + } 834 + } 835 + YFREE(dev->checkpointBlockList); 836 + dev->checkpointBlockList = NULL; 837 + } 838 + 839 + dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock; 840 + dev->nErasedBlocks -= dev->blocksInCheckpoint; 841 + 842 + 843 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR), 844 + dev->checkpointByteCount)); 845 + 846 + if(dev->checkpointBuffer){ 847 + /* free the buffer */ 848 + YFREE(dev->checkpointBuffer); 849 + dev->checkpointBuffer = NULL; 850 + return 1; 851 + } 852 + else 853 + return 0; 854 + 855 +} 856 + 857 +int yaffs_CheckpointInvalidateStream(yaffs_Device *dev) 858 +{ 859 + /* Erase the first checksum block */ 860 + 861 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR))); 862 + 863 + if(!yaffs_CheckpointSpaceOk(dev)) 864 + return 0; 865 + 866 + return yaffs_CheckpointErase(dev); 867 +} 868 + 869 + 870 + 871 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.h 872 --- linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.h 1970-01-01 01:00:00.000000000 +0100 873 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.h 2006-11-25 00:15:32.000000000 +0100 874 @@ -0,0 +1,18 @@ 875 +#ifndef __YAFFS_CHECKPTRW_H__ 876 +#define __YAFFS_CHECKPTRW_H__ 877 + 878 +#include "yaffs_guts.h" 879 + 880 +int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting); 881 + 882 +int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes); 883 + 884 +int yaffs_CheckpointRead(yaffs_Device *dev,void *data, int nBytes); 885 + 886 +int yaffs_CheckpointClose(yaffs_Device *dev); 887 + 888 +int yaffs_CheckpointInvalidateStream(yaffs_Device *dev); 889 + 890 + 891 +#endif 892 + 893 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_ecc.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.c 894 --- linux-2.6.18.2/fs/yaffs2/yaffs_ecc.c 1970-01-01 01:00:00.000000000 +0100 895 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.c 2006-11-25 00:15:31.000000000 +0100 896 @@ -0,0 +1,333 @@ 325 +yaffs-y = yaffs_fs.o yaffs_guts.o yaffs_mtdif.o yaffs_tagscompat.o \ 326 + yaffs_packedtags2.o yaffs_mtdif2.o yaffs_tagsvalidity.o \ 327 + yaffs_ecc.o 328 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c 329 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c 1970-01-01 01:00:00.000000000 +0100 330 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c 2006-12-10 03:57:50.000000000 +0100 331 @@ -0,0 +1,287 @@ 897 332 +/* 898 333 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 909 344 + * version 2.1 as published by the Free Software Foundation. 910 345 + */ 911 + 346 + 912 347 + /* 913 + * This code implements the ECC algorithm used in SmartMedia. 914 + * 915 + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. 916 + * The two unused bit are set to 1. 917 + * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC 918 + * blocks are used on a 512-byte NAND page. 919 + * 920 + */ 921 + 922 +/* Table generated by gen-ecc.c 923 + * Using a table means we do not have to calculate p1..p4 and p1'..p4' 924 + * for each byte of data. These are instead provided in a table in bits7..2. 925 + * Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore 926 + * this bytes influence on the line parity. 348 + * This code implements the ECC algorithm used in SmartMedia. 349 + * 350 + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. 351 + * The two unused bit are set to 1. 352 + * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC 353 + * blocks are used on a 512-byte NAND page. 354 + * 927 355 + */ 928 356 + 929 +const char *yaffs_ecc_c_version = 930 + "$Id: yaffs_ecc.c,v 1.7 2006/09/14 22:02:46 charles Exp $"; 357 +// Table generated by gen-ecc.c 358 +// Using a table means we do not have to calculate p1..p4 and p1'..p4' 359 +// for each byte of data. These are instead provided in a table in bits7..2. 360 +// Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore 361 +// this bytes influence on the line parity. 362 + 363 +const char *yaffs_ecc_c_version = "$Id: yaffs_ecc.c,v 1.4 2005/07/31 00:28:04 charles Exp $"; 931 364 + 932 365 +#include "yportenv.h" … … 935 368 + 936 369 +static const unsigned char column_parity_table[] = { 937 + 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 938 + 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, 939 + 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 940 + 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, 941 + 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 942 + 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, 943 + 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 944 + 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, 945 + 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 946 + 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, 947 + 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 948 + 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, 949 + 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 950 + 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, 951 + 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 952 + 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, 953 + 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 954 + 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, 955 + 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 956 + 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, 957 + 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 958 + 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, 959 + 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 960 + 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, 961 + 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 962 + 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, 963 + 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 964 + 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, 965 + 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 966 + 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, 967 + 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 968 + 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, 370 +0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, 371 +0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, 372 +0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, 373 +0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, 374 +0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, 375 +0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, 376 +0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, 377 +0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, 378 +0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, 379 +0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, 380 +0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, 381 +0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, 382 +0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, 383 +0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, 384 +0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, 385 +0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, 969 386 +}; 970 387 + 971 +/* Count the bits in an unsigned char or a U32 */972 388 + 973 389 +static int yaffs_CountBits(unsigned char x) 974 390 +{ 975 391 + int r = 0; 976 + while (x) {977 + if (x & 1)978 + r++;392 + while(x) 393 + { 394 + if(x & 1) r++; 979 395 + x >>= 1; 980 396 + } … … 982 398 +} 983 399 + 984 +static int yaffs_CountBits32(unsigned x)400 +static int yaffs_CountBits32(unsigned x) 985 401 +{ 986 402 + int r = 0; 987 + while (x) {988 + if (x & 1)989 + r++;403 + while(x) 404 + { 405 + if(x & 1) r++; 990 406 + x >>= 1; 991 407 + } … … 993 409 +} 994 410 + 995 + /* Calculate the ECC for a 256-byte block of data */996 +void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)411 + 412 +void yaffs_ECCCalculate(const unsigned char *data,unsigned char *ecc) 997 413 +{ 998 414 + unsigned int i; 999 + 415 + 1000 416 + unsigned char col_parity = 0; 1001 417 + unsigned char line_parity = 0; … … 1003 419 + unsigned char t; 1004 420 + unsigned char b; 1005 + 1006 + for (i = 0; i < 256; i++) { 421 + 422 + for(i = 0; i < 256; i++) 423 + { 1007 424 + b = column_parity_table[*data++]; 1008 425 + col_parity ^= b; 1009 426 + 1010 + if (b & 0x01)// odd number of bits in the byte427 + if(b & 0x01) // odd number of bits in the byte 1011 428 + { 1012 429 + line_parity ^= i; 1013 430 + line_parity_prime ^= ~i; 1014 431 + } 1015 + 1016 + } 1017 + 432 + 433 + } 434 + 1018 435 + ecc[2] = (~col_parity) | 0x03; 1019 + 436 + 1020 437 + t = 0; 1021 + if (line_parity & 0x80) 1022 + t |= 0x80; 1023 + if (line_parity_prime & 0x80) 1024 + t |= 0x40; 1025 + if (line_parity & 0x40) 1026 + t |= 0x20; 1027 + if (line_parity_prime & 0x40) 1028 + t |= 0x10; 1029 + if (line_parity & 0x20) 1030 + t |= 0x08; 1031 + if (line_parity_prime & 0x20) 1032 + t |= 0x04; 1033 + if (line_parity & 0x10) 1034 + t |= 0x02; 1035 + if (line_parity_prime & 0x10) 1036 + t |= 0x01; 438 + if(line_parity & 0x80) t |= 0x80; 439 + if(line_parity_prime & 0x80) t |= 0x40; 440 + if(line_parity & 0x40) t |= 0x20; 441 + if(line_parity_prime & 0x40) t |= 0x10; 442 + if(line_parity & 0x20) t |= 0x08; 443 + if(line_parity_prime & 0x20) t |= 0x04; 444 + if(line_parity & 0x10) t |= 0x02; 445 + if(line_parity_prime & 0x10) t |= 0x01; 1037 446 + ecc[1] = ~t; 1038 + 447 + 1039 448 + t = 0; 1040 + if (line_parity & 0x08) 1041 + t |= 0x80; 1042 + if (line_parity_prime & 0x08) 1043 + t |= 0x40; 1044 + if (line_parity & 0x04) 1045 + t |= 0x20; 1046 + if (line_parity_prime & 0x04) 1047 + t |= 0x10; 1048 + if (line_parity & 0x02) 1049 + t |= 0x08; 1050 + if (line_parity_prime & 0x02) 1051 + t |= 0x04; 1052 + if (line_parity & 0x01) 1053 + t |= 0x02; 1054 + if (line_parity_prime & 0x01) 1055 + t |= 0x01; 449 + if(line_parity & 0x08) t |= 0x80; 450 + if(line_parity_prime & 0x08) t |= 0x40; 451 + if(line_parity & 0x04) t |= 0x20; 452 + if(line_parity_prime & 0x04) t |= 0x10; 453 + if(line_parity & 0x02) t |= 0x08; 454 + if(line_parity_prime & 0x02) t |= 0x04; 455 + if(line_parity & 0x01) t |= 0x02; 456 + if(line_parity_prime & 0x01) t |= 0x01; 1056 457 + ecc[0] = ~t; 1057 458 + … … 1061 462 + ecc[0] = ecc[1]; 1062 463 + ecc[1] = t; 1063 +#endif 1064 +} 1065 + 1066 + 1067 +/* Correct the ECC on a 256 byte block of data */ 1068 + 1069 +int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, 1070 + const unsigned char *test_ecc) 1071 +{ 1072 + unsigned char d0, d1, d2; /* deltas */ 464 +#endif 465 +} 466 + 467 +int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, const unsigned char *test_ecc) 468 +{ 469 + unsigned char d0, d1, d2; // deltas 1073 470 + 1074 471 + d0 = read_ecc[0] ^ test_ecc[0]; 1075 472 + d1 = read_ecc[1] ^ test_ecc[1]; 1076 473 + d2 = read_ecc[2] ^ test_ecc[2]; 1077 + 1078 + if ((d0 | d1 | d2) == 0) 1079 + return 0; /* no error */ 1080 + 1081 + if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 && 474 + 475 + 476 + 477 + if((d0 | d1 | d2) == 0) 478 + { 479 + // no error 480 + return 0; 481 + } 482 + 483 + if( ((d0 ^ (d0 >> 1)) & 0x55) == 0x55 && 1082 484 + ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 && 1083 + ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) { 1084 + /* Single bit (recoverable) error in data */ 485 + ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) 486 + { 487 + // Single bit (recoverable) error in data 1085 488 + 1086 489 + unsigned byte; … … 1090 493 + // swap the bytes to correct for the wrong order 1091 494 + unsigned char t; 1092 + 495 + 1093 496 + t = d0; 1094 497 + d0 = d1; 1095 498 + d1 = t; 1096 499 +#endif 1097 + 500 + 1098 501 + bit = byte = 0; 1099 + 1100 + if (d1 & 0x80) 1101 + byte |= 0x80; 1102 + if (d1 & 0x20) 1103 + byte |= 0x40; 1104 + if (d1 & 0x08) 1105 + byte |= 0x20; 1106 + if (d1 & 0x02) 1107 + byte |= 0x10; 1108 + if (d0 & 0x80) 1109 + byte |= 0x08; 1110 + if (d0 & 0x20) 1111 + byte |= 0x04; 1112 + if (d0 & 0x08) 1113 + byte |= 0x02; 1114 + if (d0 & 0x02) 1115 + byte |= 0x01; 1116 + 1117 + if (d2 & 0x80) 1118 + bit |= 0x04; 1119 + if (d2 & 0x20) 1120 + bit |= 0x02; 1121 + if (d2 & 0x08) 1122 + bit |= 0x01; 502 + 503 + 504 + if(d1 & 0x80) byte |= 0x80; 505 + if(d1 & 0x20) byte |= 0x40; 506 + if(d1 & 0x08) byte |= 0x20; 507 + if(d1 & 0x02) byte |= 0x10; 508 + if(d0 & 0x80) byte |= 0x08; 509 + if(d0 & 0x20) byte |= 0x04; 510 + if(d0 & 0x08) byte |= 0x02; 511 + if(d0 & 0x02) byte |= 0x01; 512 + 513 + if(d2 & 0x80) bit |= 0x04; 514 + if(d2 & 0x20) bit |= 0x02; 515 + if(d2 & 0x08) bit |= 0x01; 1123 516 + 1124 517 + data[byte] ^= (1 << bit); 1125 + 1126 + return 1; /* Corrected the error */ 1127 + } 1128 + 1129 + if ((yaffs_CountBits(d0) + 1130 + yaffs_CountBits(d1) + 1131 + yaffs_CountBits(d2)) == 1) { 1132 + /* Reccoverable error in ecc */ 1133 + 518 + 519 + return 1; 520 + } 521 + 522 + if((yaffs_CountBits(d0)+yaffs_CountBits(d1)+yaffs_CountBits(d2)) == 1) 523 + { 524 + // Reccoverable error in ecc 525 + 1134 526 + read_ecc[0] = test_ecc[0]; 1135 527 + read_ecc[1] = test_ecc[1]; 1136 528 + read_ecc[2] = test_ecc[2]; 1137 + 1138 + return 1; /* Corrected the error */1139 + } 1140 + 1141 + / * Unrecoverable error */1142 + 529 + 530 + return 1; 531 + } 532 + 533 + // Unrecoverable error 534 + 1143 535 + return -1; 1144 + 1145 +} 1146 + 1147 + 1148 +/* 1149 + * ECCxxxOther does ECC calcs on arbitrary n bytes of data 1150 + */ 1151 +void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, 1152 + yaffs_ECCOther * eccOther) 536 + 537 + 538 +} 539 + 540 + 541 + 542 +void yaffs_ECCCalculateOther(const unsigned char *data,unsigned nBytes, yaffs_ECCOther *eccOther) 1153 543 +{ 1154 544 + unsigned int i; 1155 + 545 + 1156 546 + unsigned char col_parity = 0; 1157 547 + unsigned line_parity = 0; 1158 548 + unsigned line_parity_prime = 0; 1159 549 + unsigned char b; 1160 + 1161 + for (i = 0; i < nBytes; i++) { 550 + 551 + for(i = 0; i < nBytes; i++) 552 + { 1162 553 + b = column_parity_table[*data++]; 1163 554 + col_parity ^= b; 1164 555 + 1165 + if (b & 0x01) {1166 + /* odd number of bits in the byte */556 + if(b & 0x01) // odd number of bits in the byte 557 + { 1167 558 + line_parity ^= i; 1168 559 + line_parity_prime ^= ~i; 1169 560 + } 1170 + 1171 + } 1172 + 561 + 562 + } 563 + 1173 564 + eccOther->colParity = (col_parity >> 2) & 0x3f; 1174 565 + eccOther->lineParity = line_parity; … … 1176 567 +} 1177 568 + 1178 +int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, 1179 + yaffs_ECCOther * read_ecc, 1180 + const yaffs_ECCOther * test_ecc) 1181 +{ 1182 + unsigned char cDelta; /* column parity delta */ 1183 + unsigned lDelta; /* line parity delta */ 1184 + unsigned lDeltaPrime; /* line parity delta */ 569 +int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, yaffs_ECCOther *read_ecc, const yaffs_ECCOther *test_ecc) 570 +{ 571 + unsigned char cDelta; // column parity delta 572 + unsigned lDelta; // line parity delta 573 + unsigned lDeltaPrime; // line parity delta 1185 574 + unsigned bit; 1186 575 + 1187 576 + cDelta = read_ecc->colParity ^ test_ecc->colParity; 1188 + lDelta = read_ecc->lineParity ^ test_ecc->lineParity; 577 + lDelta = read_ecc->lineParity ^ test_ecc->lineParity; 1189 578 + lDeltaPrime = read_ecc->lineParityPrime ^ test_ecc->lineParityPrime; 1190 + 1191 + if ((cDelta | lDelta | lDeltaPrime) == 0) 1192 + return 0; /* no error */ 1193 + 1194 + if (lDelta == ~lDeltaPrime && 1195 + (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) 1196 + { 1197 + /* Single bit (recoverable) error in data */ 579 + 580 + if((cDelta | lDelta | lDeltaPrime) == 0) 581 + { 582 + // no error 583 + return 0; 584 + } 585 + 586 + if( lDelta == ~lDeltaPrime && 587 + (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) // Not correct 588 + { 589 + // Single bit (recoverable) error in data 1198 590 + 1199 591 + bit = 0; 1200 592 + 1201 + if (cDelta & 0x20) 1202 + bit |= 0x04; 1203 + if (cDelta & 0x08) 1204 + bit |= 0x02; 1205 + if (cDelta & 0x02) 1206 + bit |= 0x01; 1207 + 1208 + if(lDelta >= nBytes) 1209 + return -1; 1210 + 593 + if(cDelta & 0x20) bit |= 0x04; 594 + if(cDelta & 0x08) bit |= 0x02; 595 + if(cDelta & 0x02) bit |= 0x01; 596 + 1211 597 + data[lDelta] ^= (1 << bit); 1212 + 1213 + return 1; /* corrected */1214 + } 1215 + 1216 + if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +1217 + yaffs_CountBits(cDelta)) == 1){1218 + / * Reccoverable error in ecc */1219 + 1220 + *read_ecc = *test_ecc;1221 + return 1; /* corrected */1222 + } 1223 + 1224 + / * Unrecoverable error */1225 + 598 + 599 + return 1; 600 + } 601 + 602 + if((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) + yaffs_CountBits(cDelta)) == 1) 603 + { 604 + // Reccoverable error in ecc 605 + 606 + *read_ecc = *test_ecc; 607 + return 1; 608 + } 609 + 610 + // Unrecoverable error 611 + 1226 612 + return -1; 1227 + 1228 +} 1229 + 1230 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_ecc.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.h 1231 --- linux-2.6.18.2/fs/yaffs2/yaffs_ecc.h 1970-01-01 01:00:00.000000000 +0100 1232 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.h 2006-11-25 00:15:32.000000000 +0100 1233 @@ -0,0 +1,44 @@ 613 + 614 + 615 +} 616 + 617 + 618 + 619 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h 620 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h 1970-01-01 01:00:00.000000000 +0100 621 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h 2006-12-10 03:57:50.000000000 +0100 622 @@ -0,0 +1,41 @@ 1234 623 +/* 1235 624 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 1246 635 + * 1247 636 + */ 1248 + 637 + 1249 638 + /* 1250 + * This code implements the ECC algorithm used in SmartMedia.1251 + *1252 + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.1253 + * The two unused bit are set to 1.1254 + * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC1255 + * blocks are used on a 512-byte NAND page.1256 + *1257 + */639 + * This code implements the ECC algorithm used in SmartMedia. 640 + * 641 + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. 642 + * The two unused bit are set to 1. 643 + * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC 644 + * blocks are used on a 512-byte NAND page. 645 + * 646 + */ 1258 647 + 1259 648 +#ifndef __YAFFS_ECC_H__ 1260 649 +#define __YAFFS_ECC_H__ 1261 650 + 1262 +typedef struct { 651 +typedef struct 652 +{ 1263 653 + unsigned char colParity; 1264 654 + unsigned lineParity; … … 1266 656 +} yaffs_ECCOther; 1267 657 + 1268 +void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc); 1269 +int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, 1270 + const unsigned char *test_ecc); 1271 + 1272 +void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, 1273 + yaffs_ECCOther * ecc); 1274 +int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, 1275 + yaffs_ECCOther * read_ecc, 1276 + const yaffs_ECCOther * test_ecc); 1277 +#endif 1278 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_fs.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_fs.c 1279 --- linux-2.6.18.2/fs/yaffs2/yaffs_fs.c 1970-01-01 01:00:00.000000000 +0100 1280 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_fs.c 2006-11-25 00:15:31.000000000 +0100 1281 @@ -0,0 +1,2116 @@ 658 +void yaffs_ECCCalculate(const unsigned char *data,unsigned char *ecc); 659 +int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, const unsigned char *test_ecc); 660 + 661 +void yaffs_ECCCalculateOther(const unsigned char *data,unsigned nBytes, yaffs_ECCOther *ecc); 662 +int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, yaffs_ECCOther *read_ecc, const yaffs_ECCOther *test_ecc); 663 +#endif 664 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c 665 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c 1970-01-01 01:00:00.000000000 +0100 666 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c 2006-12-10 04:40:11.000000000 +0100 667 @@ -0,0 +1,1720 @@ 1282 668 +/* 1283 669 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 1297 683 + * 1298 684 + * Special notes: 1299 + * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with 1300 + * this superblock 1301 + * >> 2.6: sb->s_fs_info points to the yaffs_Device associated with this 1302 + * superblock 685 + * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with this superblock 686 + * >> 2.6: sb->s_fs_info points to the yaffs_Device associated with this superblock 1303 687 + * >> inode->u.generic_ip points to the associated yaffs_Object. 688 + * 1304 689 + * 1305 690 + * Acknowledgements: … … 1312 697 + */ 1313 698 + 1314 + const char *yaffs_fs_c_version =1315 + "$Id: yaffs_fs.c,v 1.54 2006/10/24 18:09:15 charlesExp $";699 + 700 +const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.27 2005/08/04 22:47:36 luc Exp $"; 1316 701 +extern const char *yaffs_guts_c_version; 702 + 1317 703 + 1318 704 +#include <linux/config.h> … … 1330 716 +#include <linux/interrupt.h> 1331 717 +#include <linux/string.h> 1332 + #include <linux/ctype.h>718 + 1333 719 + 1334 720 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) … … 1338 724 +#define UnlockPage(p) unlock_page(p) 1339 725 +#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) 1340 + 1341 +/* FIXME: use sb->s_id instead ? */ 1342 +#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf) 726 +#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf) // FIXME: use sb->s_id instead ? 1343 727 + 1344 728 +#else … … 1348 732 +#define yaffs_devname(sb, buf) kdevname(sb->s_dev) 1349 733 + 1350 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))1351 +/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */1352 +#define __user1353 +#endif1354 +1355 734 +#endif 1356 735 + … … 1360 739 +#include "yaffs_guts.h" 1361 740 + 1362 +unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | 1363 + YAFFS_TRACE_BAD_BLOCKS | 1364 + YAFFS_TRACE_CHECKPOINT 1365 + /* | 0xFFFFFFFF */; 1366 + 741 + 742 + 743 + 744 +unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | YAFFS_TRACE_BAD_BLOCKS; 745 +//unsigned yaffs_traceMask = 0xFFFFFFFF; 746 + 747 + 748 +#ifdef CONFIG_YAFFS_YAFFS1 1367 749 +#include <linux/mtd/mtd.h> 1368 750 +#include "yaffs_mtdif.h" 1369 751 +#include "yaffs_mtdif2.h" 1370 + 1371 +/*#define T(x) printk x */ 752 +#endif //CONFIG_YAFFS_YAFFS1 753 + 754 +//#define T(x) printk x 755 + 756 + 1372 757 + 1373 758 +#define yaffs_InodeToObject(iptr) ((yaffs_Object *)((iptr)->u.generic_ip)) … … 1380 765 +#endif 1381 766 + 767 + 1382 768 +static void yaffs_put_super(struct super_block *sb); 1383 769 + 1384 +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, 1385 + loff_t * pos); 1386 + 1387 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 1388 +static int yaffs_file_flush(struct file *file, fl_owner_t id); 1389 +#else 1390 +static int yaffs_file_flush(struct file *file); 1391 +#endif 1392 + 1393 +static int yaffs_sync_object(struct file *file, struct dentry *dentry, 1394 + int datasync); 770 +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos); 771 + 772 +static int yaffs_file_flush(struct file* file, fl_owner_t id); 773 + 774 +static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync); 1395 775 + 1396 776 +static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir); 1397 777 + 1398 778 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 1399 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, 1400 + struct nameidata *n); 1401 +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, 1402 + struct nameidata *n); 779 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *n); 780 +static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *n); 1403 781 +#else 1404 782 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode); 1405 +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry); 1406 +#endif 1407 +static int yaffs_link(struct dentry *old_dentry, struct inode *dir, 1408 + struct dentry *dentry); 1409 +static int yaffs_unlink(struct inode *dir, struct dentry *dentry); 1410 +static int yaffs_symlink(struct inode *dir, struct dentry *dentry, 1411 + const char *symname); 1412 +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode); 783 +static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry); 784 +#endif 785 +static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry); 786 +static int yaffs_unlink(struct inode * dir, struct dentry *dentry); 787 +static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname); 788 +static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode); 1413 789 + 1414 790 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 1415 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, 1416 + dev_t dev); 791 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev); 1417 792 +#else 1418 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, 1419 + int dev); 1420 +#endif 1421 +static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, 1422 + struct inode *new_dir, struct dentry *new_dentry); 793 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev); 794 +#endif 795 +static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry); 1423 796 +static int yaffs_setattr(struct dentry *dentry, struct iattr *attr); 1424 797 + 1425 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))1426 +static int yaffs_sync_fs(struct super_block *sb, int wait);1427 +static void yaffs_write_super(struct super_block *sb);1428 +#else1429 +static int yaffs_sync_fs(struct super_block *sb);1430 +static int yaffs_write_super(struct super_block *sb);1431 +#endif1432 +1433 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))1434 798 +static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf); 1435 +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 1436 +static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf); 1437 +#else 1438 +static int yaffs_statfs(struct super_block *sb, struct statfs *buf); 1439 +#endif 1440 +static void yaffs_read_inode(struct inode *inode); 1441 + 1442 +static void yaffs_put_inode(struct inode *inode); 799 +static void yaffs_read_inode (struct inode *inode); 800 + 801 +static void yaffs_put_inode (struct inode *inode); 1443 802 +static void yaffs_delete_inode(struct inode *); 1444 803 +static void yaffs_clear_inode(struct inode *); 1445 804 + 1446 +static int yaffs_readpage(struct file *file, struct page * page);805 +static int yaffs_readpage(struct file *file, struct page * page); 1447 806 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 1448 807 +static int yaffs_writepage(struct page *page, struct writeback_control *wbc); … … 1450 809 +static int yaffs_writepage(struct page *page); 1451 810 +#endif 1452 +static int yaffs_prepare_write(struct file *f, struct page *pg, 1453 + unsigned offset, unsigned to); 1454 +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, 1455 + unsigned to); 1456 + 1457 +static int yaffs_readlink(struct dentry *dentry, char __user * buffer, 1458 + int buflen); 1459 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) 811 +static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to); 812 +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to); 813 + 814 +static int yaffs_readlink(struct dentry *dentry, char __user *buffer, int buflen); 1460 815 +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); 1461 +#else 1462 +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); 1463 +#endif 816 + 817 + 1464 818 + 1465 819 +static struct address_space_operations yaffs_file_address_operations = { 1466 + .readpage = yaffs_readpage,1467 + .writepage = yaffs_writepage,1468 + .prepare_write = yaffs_prepare_write,1469 + .commit_write = yaffs_commit_write,820 + .readpage = yaffs_readpage, 821 + .writepage = yaffs_writepage, 822 + .prepare_write = yaffs_prepare_write, 823 + .commit_write = yaffs_commit_write, 1470 824 +}; 1471 825 + 1472 826 +static struct file_operations yaffs_file_operations = { 1473 + .read = generic_file_read, 1474 + .write = generic_file_write, 1475 + .mmap = generic_file_mmap, 1476 + .flush = yaffs_file_flush, 1477 + .fsync = yaffs_sync_object, 1478 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 1479 + .sendfile = generic_file_sendfile, 1480 +#endif 1481 + 827 + .read = generic_file_read, 828 + .write = generic_file_write, 829 + .mmap = generic_file_mmap, 830 + .flush = yaffs_file_flush, 831 + .fsync = yaffs_sync_object, 1482 832 +}; 1483 833 + 1484 834 +static struct inode_operations yaffs_file_inode_operations = { 1485 + .setattr = yaffs_setattr,835 + .setattr = yaffs_setattr, 1486 836 +}; 1487 837 + 1488 +static struct inode_operations yaffs_symlink_inode_operations = { 1489 + .readlink = yaffs_readlink,1490 + .follow_link = yaffs_follow_link,1491 + .setattr = yaffs_setattr,838 +static struct inode_operations yaffs_symlink_inode_operations = { 839 + .readlink = yaffs_readlink, 840 + .follow_link = yaffs_follow_link, 841 + .setattr = yaffs_setattr, 1492 842 +}; 1493 843 + 1494 844 +static struct inode_operations yaffs_dir_inode_operations = { 1495 + .create = yaffs_create,1496 + .lookup = yaffs_lookup,1497 + .link = yaffs_link,1498 + .unlink = yaffs_unlink,1499 + .symlink = yaffs_symlink,1500 + .mkdir = yaffs_mkdir,1501 + .rmdir = yaffs_unlink,1502 + .mknod = yaffs_mknod,1503 + .rename = yaffs_rename,1504 + .setattr = yaffs_setattr,845 + .create = yaffs_create, 846 + .lookup = yaffs_lookup, 847 + .link = yaffs_link, 848 + .unlink = yaffs_unlink, 849 + .symlink = yaffs_symlink, 850 + .mkdir = yaffs_mkdir, 851 + .rmdir = yaffs_unlink, 852 + .mknod = yaffs_mknod, 853 + .rename = yaffs_rename, 854 + .setattr = yaffs_setattr, 1505 855 +}; 1506 856 + 1507 857 +static struct file_operations yaffs_dir_operations = { 1508 + .read = generic_read_dir,1509 + .readdir = yaffs_readdir,1510 + .fsync = yaffs_sync_object,858 + .read = generic_read_dir, 859 + .readdir = yaffs_readdir, 860 + .fsync = yaffs_sync_object, 1511 861 +}; 1512 862 + 1513 863 +static struct super_operations yaffs_super_ops = { 1514 + .statfs = yaffs_statfs, 1515 + .read_inode = yaffs_read_inode, 1516 + .put_inode = yaffs_put_inode, 1517 + .put_super = yaffs_put_super, 1518 + .delete_inode = yaffs_delete_inode, 1519 + .clear_inode = yaffs_clear_inode, 1520 + .sync_fs = yaffs_sync_fs, 1521 + .write_super = yaffs_write_super, 864 + .statfs = yaffs_statfs, 865 + .read_inode = yaffs_read_inode, 866 + .put_inode = yaffs_put_inode, 867 + .put_super = yaffs_put_super, 868 + .delete_inode = yaffs_delete_inode, 869 + .clear_inode = yaffs_clear_inode, 1522 870 +}; 1523 871 + 1524 +static void yaffs_GrossLock(yaffs_Device * dev) 1525 +{ 1526 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs locking\n")); 872 + 873 + 874 +static void yaffs_GrossLock(yaffs_Device *dev) 875 +{ 876 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs locking\n")); 1527 877 + 1528 878 + down(&dev->grossLock); 1529 879 +} 1530 880 + 1531 +static void yaffs_GrossUnlock(yaffs_Device * dev)1532 +{ 1533 + T(YAFFS_TRACE_OS, (KERN_DEBUG"yaffs unlocking\n"));881 +static void yaffs_GrossUnlock(yaffs_Device *dev) 882 +{ 883 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs unlocking\n")); 1534 884 + up(&dev->grossLock); 1535 885 + 1536 886 +} 1537 887 + 1538 +static int yaffs_readlink(struct dentry *dentry, char __user * buffer, 1539 + int buflen) 888 +static int yaffs_readlink(struct dentry *dentry, char __user *buffer, int buflen) 1540 889 +{ 1541 890 + unsigned char *alias; … … 1544 893 + yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; 1545 894 + 895 + 1546 896 + yaffs_GrossLock(dev); 1547 + 897 + 1548 898 + alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); 1549 + 899 + 1550 900 + yaffs_GrossUnlock(dev); 1551 + 1552 + if (!alias)901 + 902 + if(!alias) 1553 903 + return -ENOMEM; 1554 904 + … … 1558 908 +} 1559 909 + 1560 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))1561 910 +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) 1562 +#else1563 +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)1564 +#endif1565 911 +{ 1566 912 + unsigned char *alias; … … 1568 914 + yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; 1569 915 + 916 + 1570 917 + yaffs_GrossLock(dev); 1571 918 + 1572 919 + alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); 1573 + 920 + 1574 921 + yaffs_GrossUnlock(dev); 1575 + 1576 + if (!alias) 1577 + { 922 + 923 + if(!alias) 1578 924 + ret = -ENOMEM; 1579 + goto out; 1580 + } 1581 + 1582 + ret = vfs_follow_link(nd, alias); 1583 + kfree(alias); 1584 +out: 1585 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) 925 + else { 926 + ret = vfs_follow_link(nd,alias); 927 + kfree(alias); 928 + } 1586 929 + return ERR_PTR (ret); 1587 +#else 1588 + return ret; 1589 +#endif 1590 +} 1591 + 1592 +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, 1593 + yaffs_Object * obj); 930 +} 931 + 932 + 933 +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj); 1594 934 + 1595 935 +/* … … 1598 938 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 1599 939 + 1600 +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, 1601 + struct nameidata *n) 940 +static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *n) 1602 941 +#else 1603 +static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)942 +static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry) 1604 943 +#endif 1605 944 +{ 1606 945 + yaffs_Object *obj; 1607 + struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */1608 + 946 + struct inode *inode = NULL; // NCB 2.5/2.6 needs NULL here 947 + 1609 948 + yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev; 1610 949 + 950 + 1611 951 + yaffs_GrossLock(dev); 1612 952 + 1613 + T(YAFFS_TRACE_OS, 1614 + (KERN_DEBUG "yaffs_lookup for %d:%s\n", 1615 + yaffs_InodeToObject(dir)->objectId, dentry->d_name.name)); 1616 + 1617 + obj = 1618 + yaffs_FindObjectByName(yaffs_InodeToObject(dir), 1619 + dentry->d_name.name); 1620 + 1621 + obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */ 1622 + 1623 + /* Can't hold gross lock when calling yaffs_get_inode() */ 953 + 954 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_lookup for %d:%s\n",yaffs_InodeToObject(dir)->objectId,dentry->d_name.name)); 955 + 956 + obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name); 957 + 958 + obj = yaffs_GetEquivalentObject(obj); // in case it was a hardlink 959 + 960 + 961 + 962 + if(obj) 963 + { 964 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId)); 965 + 966 + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode,0,obj); 967 + 968 + if(inode) 969 + { 970 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_loookup dentry \n")); 971 +/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to d_add even if NULL inode */ 972 +#if 0 973 + //dget(dentry); // try to solve directory bug 974 + d_add(dentry,inode); 975 + 976 + yaffs_GrossUnlock(dev); 977 + 978 + // return dentry; 979 + return NULL; 980 +#endif 981 + } 982 + 983 + } 984 + else 985 + { 986 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_lookup not found\n")); 987 + 988 + } 1624 989 + yaffs_GrossUnlock(dev); 1625 990 + 1626 + if (obj) { 1627 + T(YAFFS_TRACE_OS, 1628 + (KERN_DEBUG "yaffs_lookup found %d\n", obj->objectId)); 1629 + 1630 + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); 1631 + 1632 + if (inode) { 1633 + T(YAFFS_TRACE_OS, 1634 + (KERN_DEBUG "yaffs_loookup dentry \n")); 1635 +/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to 1636 + * d_add even if NULL inode */ 1637 +#if 0 1638 + /*dget(dentry); // try to solve directory bug */ 1639 + d_add(dentry, inode); 1640 + 1641 + /* return dentry; */ 1642 + return NULL; 1643 +#endif 1644 + } 1645 + 1646 + } else { 1647 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n")); 1648 + 1649 + } 1650 + 1651 +/* added NCB for 2.5/6 compatability - forces add even if inode is 1652 + * NULL which creates dentry hash */ 1653 + d_add(dentry, inode); 1654 + 991 +/* added NCB for 2.5/6 compatability - forces add even if inode is NULL which creates dentry hash*/ 992 + d_add(dentry,inode); 993 + 1655 994 + return NULL; 1656 + /* return (ERR_PTR(-EIO)); */ 1657 + 1658 +} 1659 + 1660 +/* For now put inode is just for debugging 1661 + * Put inode is called when the inode **structure** is put. 1662 + */ 995 + // return (ERR_PTR(-EIO)); 996 + 997 +} 998 + 999 +// For now put inode is just for debugging 1000 +// Put inode is called when the inode **structure** is put. 1663 1001 +static void yaffs_put_inode(struct inode *inode) 1664 1002 +{ 1665 + T(YAFFS_TRACE_OS, 1666 + ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino, 1667 + atomic_read(&inode->i_count))); 1668 + 1669 +} 1670 + 1671 +/* clear is called to tell the fs to release any per-inode data it holds */ 1003 + T(YAFFS_TRACE_OS,("yaffs_put_inode: ino %d, count %d\n",(int)inode->i_ino, atomic_read(&inode->i_count))); 1004 + 1005 +} 1006 + 1007 +// clear is called to tell the fs to release any per-inode data it holds 1672 1008 +static void yaffs_clear_inode(struct inode *inode) 1673 1009 +{ 1674 1010 + yaffs_Object *obj; 1675 1011 + yaffs_Device *dev; 1676 + 1012 + 1677 1013 + obj = yaffs_InodeToObject(inode); 1678 + 1679 + T(YAFFS_TRACE_OS, 1680 + ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, 1681 + atomic_read(&inode->i_count), 1682 + obj ? "object exists" : "null object")); 1683 + 1684 + if (obj) { 1014 + 1015 + T(YAFFS_TRACE_OS,("yaffs_clear_inode: ino %d, count %d %s\n",(int)inode->i_ino, atomic_read(&inode->i_count), 1016 + obj ? "object exists" : "null object")); 1017 + 1018 + if(obj) 1019 + { 1685 1020 + dev = obj->myDev; 1686 1021 + yaffs_GrossLock(dev); 1687 + 1688 + /* Clear the association between the inode and 1689 + * the yaffs_Object. 1690 + */ 1022 + 1023 + // Clear the association between the inode ant the yaffs_Object. 1691 1024 + obj->myInode = NULL; 1692 1025 + inode->u.generic_ip = NULL; 1693 + 1694 + /* If the object freeing was deferred, then the real 1695 + * free happens now. 1696 + * This should fix the inode inconsistency problem. 1697 + */ 1698 + 1026 + 1027 + // If the object freeing was deferred, then the real free happens now. 1028 + // This should fix the inode inconsistency problem. 1029 + 1699 1030 + yaffs_HandleDeferedFree(obj); 1700 + 1031 + 1701 1032 + yaffs_GrossUnlock(dev); 1702 1033 + } 1703 + 1704 + }1705 + 1706 + /* delete is called when the link count is zero and the inode1707 + * is put (ie. nobody wants to know about it anymore, time to1708 + * delete the file).1709 + * NB Must call clear_inode()1710 + */1034 + 1035 + 1036 +} 1037 + 1038 +// delete is called when the link count is zero and the inode 1039 +// is put (ie. nobody wants to know about it anymore, time to 1040 +// delete the file). 1041 +// NB Must call clear_inode() 1711 1042 +static void yaffs_delete_inode(struct inode *inode) 1712 1043 +{ … … 1714 1045 + yaffs_Device *dev; 1715 1046 + 1716 + T(YAFFS_TRACE_OS, 1717 + ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, 1718 + atomic_read(&inode->i_count), 1719 + obj ? "object exists" : "null object")); 1720 + 1721 + if (obj) { 1722 + dev = obj->myDev; 1047 + T(YAFFS_TRACE_OS,("yaffs_delete_inode: ino %d, count %d %s\n",(int)inode->i_ino, atomic_read(&inode->i_count), 1048 + obj ? "object exists" : "null object")); 1049 + 1050 + if(obj) 1051 + { 1052 + dev = obj->myDev; 1723 1053 + yaffs_GrossLock(dev); 1724 1054 + yaffs_DeleteFile(obj); 1725 1055 + yaffs_GrossUnlock(dev); 1726 1056 + } 1727 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))1728 + truncate_inode_pages (&inode->i_data, 0);1729 +#endif1730 1057 + clear_inode(inode); 1731 1058 +} 1732 1059 + 1733 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 1734 +static int yaffs_file_flush(struct file *file, fl_owner_t id) 1735 +#else 1736 +static int yaffs_file_flush(struct file *file) 1737 +#endif 1060 + 1061 +static int yaffs_file_flush(struct file* file, fl_owner_t id) 1738 1062 +{ 1739 1063 + yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry); 1740 + 1064 + 1741 1065 + yaffs_Device *dev = obj->myDev; 1742 + 1743 + T(YAFFS_TRACE_OS, 1744 + (KERN_DEBUG "yaffs_file_flush object %d (%s)\n", obj->objectId, 1745 + obj->dirty ? "dirty" : "clean")); 1066 + 1067 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_flush object %d (%s)\n",obj->objectId, 1068 + obj->dirty ? "dirty" : "clean")); 1746 1069 + 1747 1070 + yaffs_GrossLock(dev); 1748 + 1749 + yaffs_FlushFile(obj,1);1071 + 1072 + yaffs_FlushFile(obj,1); 1750 1073 + 1751 1074 + yaffs_GrossUnlock(dev); 1752 1075 + 1753 + return 0; 1754 +} 1755 + 1756 +static int yaffs_readpage_nolock(struct file *f, struct page *pg) 1757 +{ 1758 + /* Lifted from jffs2 */ 1759 + 1076 + return 0; 1077 +} 1078 + 1079 + 1080 + 1081 +static int yaffs_readpage_nolock(struct file *f, struct page * pg) 1082 +{ 1083 + // Lifted from jffs2 1084 + 1760 1085 + yaffs_Object *obj; 1761 1086 + unsigned char *pg_buf; … … 1764 1089 + yaffs_Device *dev; 1765 1090 + 1766 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage at %08x, size %08x\n", 1767 + (unsigned)(pg->index << PAGE_CACHE_SHIFT), 1768 + (unsigned)PAGE_CACHE_SIZE)); 1769 + 1770 + obj = yaffs_DentryToObject(f->f_dentry); 1091 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readpage at %08x, size %08x\n", 1092 + (unsigned)(pg->index << PAGE_CACHE_SHIFT), (unsigned)PAGE_CACHE_SIZE)); 1093 + 1094 + obj = yaffs_DentryToObject(f->f_dentry); 1771 1095 + 1772 1096 + dev = obj->myDev; 1773 + 1097 + 1098 + 1774 1099 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 1775 + BUG_ON(!PageLocked(pg));1100 + BUG_ON(!PageLocked(pg)); 1776 1101 +#else 1777 1102 + if (!PageLocked(pg)) 1778 + PAGE_BUG(pg);1103 + PAGE_BUG(pg); 1779 1104 +#endif 1780 1105 + … … 1783 1108 + 1784 1109 + yaffs_GrossLock(dev); 1785 + 1786 + ret = 1787 + yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, 1788 + PAGE_CACHE_SIZE); 1110 + 1111 + ret = yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); 1789 1112 + 1790 1113 + yaffs_GrossUnlock(dev); 1791 + 1792 + if (ret >= 0) 1793 + ret = 0; 1114 + 1115 + if(ret >= 0) ret = 0; 1794 1116 + 1795 1117 + if (ret) { … … 1804 1126 + kunmap(pg); 1805 1127 + 1806 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage done\n")); 1128 + 1129 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readpage done\n")); 1807 1130 + return ret; 1808 1131 +} … … 1810 1133 +static int yaffs_readpage_unlock(struct file *f, struct page *pg) 1811 1134 +{ 1812 + int ret = yaffs_readpage_nolock(f, pg);1135 + int ret = yaffs_readpage_nolock(f,pg); 1813 1136 + UnlockPage(pg); 1814 1137 + return ret; 1815 1138 +} 1816 1139 + 1817 +static int yaffs_readpage(struct file *f, struct page *pg) 1818 +{ 1819 + return yaffs_readpage_unlock(f, pg); 1820 +} 1821 + 1822 +/* writepage inspired by/stolen from smbfs */ 1140 +static int yaffs_readpage(struct file *f, struct page * pg) 1141 +{ 1142 + return yaffs_readpage_unlock(f,pg); 1143 +} 1144 + 1145 +// writepage inspired by/stolen from smbfs 1146 +// 1823 1147 + 1824 1148 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) … … 1829 1153 +{ 1830 1154 + struct address_space *mapping = page->mapping; 1831 + loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT;1155 + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; 1832 1156 + struct inode *inode; 1833 1157 + unsigned long end_index; … … 1843 1167 + BUG(); 1844 1168 + 1845 + if (offset > inode->i_size) { 1846 + T(YAFFS_TRACE_OS, 1847 + (KERN_DEBUG 1848 + "yaffs_writepage at %08x, inode size = %08x!!!\n", 1849 + (unsigned)(page->index << PAGE_CACHE_SHIFT), 1850 + (unsigned)inode->i_size)); 1851 + T(YAFFS_TRACE_OS, 1852 + (KERN_DEBUG " -> don't care!!\n")); 1169 + if (offset > inode->i_size) 1170 + { 1171 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_writepage at %08x, inode size = %08x!!!\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), (unsigned) inode->i_size)); 1172 + T(YAFFS_TRACE_OS,(KERN_DEBUG" -> don't care!!\n")); 1853 1173 + unlock_page(page); 1854 1174 + return 0; … … 1858 1178 + 1859 1179 + /* easy case */ 1860 + if (page->index < end_index) { 1180 + if (page->index < end_index) 1181 + { 1861 1182 + nBytes = PAGE_CACHE_SIZE; 1862 + } else { 1863 + nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1); 1864 + } 1183 + } 1184 + else 1185 + { 1186 + nBytes = inode->i_size & (PAGE_CACHE_SIZE-1); 1187 + } 1188 + // What's happening here? 1189 + ///* OK, are we completely out? */ 1190 + //if (page->index >= end_index+1 || !offset) 1191 + // return -EIO; 1865 1192 + 1866 1193 + get_page(page); 1194 + 1867 1195 + 1868 1196 + buffer = kmap(page); … … 1871 1199 + yaffs_GrossLock(obj->myDev); 1872 1200 + 1873 + T(YAFFS_TRACE_OS, 1874 + (KERN_DEBUG "yaffs_writepage at %08x, size %08x\n", 1875 + (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); 1876 + T(YAFFS_TRACE_OS, 1877 + (KERN_DEBUG "writepag0: obj = %05x, ino = %05x\n", 1878 + (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); 1879 + 1880 + nWritten = 1881 + yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT, 1882 + nBytes, 0); 1883 + 1884 + T(YAFFS_TRACE_OS, 1885 + (KERN_DEBUG "writepag1: obj = %05x, ino = %05x\n", 1886 + (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); 1201 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_writepage at %08x, size %08x\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); 1202 + T(YAFFS_TRACE_OS,(KERN_DEBUG"writepag0: obj = %05x, ino = %05x\n", (int) obj->variant.fileVariant.fileSize, (int) inode->i_size)); 1203 + 1204 + nWritten = yaffs_WriteDataToFile(obj,buffer,page->index << PAGE_CACHE_SHIFT,nBytes,0); 1205 + 1206 + T(YAFFS_TRACE_OS,(KERN_DEBUG"writepag1: obj = %05x, ino = %05x\n", (int) obj->variant.fileVariant.fileSize, (int) inode->i_size)); 1887 1207 + 1888 1208 + yaffs_GrossUnlock(obj->myDev); 1889 + 1209 + 1890 1210 + kunmap(page); 1891 1211 + SetPageUptodate(page); … … 1893 1213 + put_page(page); 1894 1214 + 1895 + return (nWritten == nBytes) ? 0 : -ENOSPC; 1896 +} 1897 + 1898 +static int yaffs_prepare_write(struct file *f, struct page *pg, 1899 + unsigned offset, unsigned to) 1900 +{ 1901 + 1902 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n")); 1903 + if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) 1904 + return yaffs_readpage_nolock(f, pg); 1215 + return (nWritten == nBytes) ? 0 : -ENOSPC; 1216 +} 1217 + 1218 + 1219 + 1220 +static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to) 1221 +{ 1222 + 1223 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_prepair_write\n")); 1224 + if(!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) 1225 + return yaffs_readpage_nolock(f,pg); 1905 1226 + 1906 1227 + return 0; 1907 + 1908 +} 1909 + 1910 +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, 1911 + unsigned to) 1228 + 1229 +} 1230 + 1231 +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to) 1912 1232 +{ 1913 1233 + 1914 1234 + void *addr = page_address(pg) + offset; 1915 + loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;1235 + loff_t pos = (((loff_t)pg->index) << PAGE_CACHE_SHIFT) + offset; 1916 1236 + int nBytes = to - offset; 1917 1237 + int nWritten; 1918 + 1238 + 1919 1239 + unsigned spos = pos; 1920 1240 + unsigned saddr = (unsigned)addr; 1921 1241 + 1922 + T(YAFFS_TRACE_OS, 1923 + (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr, 1924 + spos, nBytes)); 1925 + 1926 + nWritten = yaffs_file_write(f, addr, nBytes, &pos); 1927 + 1928 + if (nWritten != nBytes) { 1929 + T(YAFFS_TRACE_OS, 1930 + (KERN_DEBUG 1931 + "yaffs_commit_write not same size nWritten %d nBytes %d\n", 1932 + nWritten, nBytes)); 1242 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_commit_write addr %x pos %x nBytes %d\n",saddr,spos,nBytes)); 1243 + 1244 + nWritten = yaffs_file_write(f,addr, nBytes, &pos); 1245 + 1246 + if(nWritten != nBytes) 1247 + { 1248 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_commit_write not same size nWritten %d nBytes %d\n",nWritten,nBytes)); 1933 1249 + SetPageError(pg); 1934 1250 + ClearPageUptodate(pg); 1935 + } else { 1251 + } 1252 + else 1253 + { 1936 1254 + SetPageUptodate(pg); 1937 1255 + } 1938 1256 + 1939 + T(YAFFS_TRACE_OS, 1940 + (KERN_DEBUG "yaffs_commit_write returning %d\n", 1941 + nWritten == nBytes ? 0 : nWritten)); 1942 + 1943 + return nWritten == nBytes ? 0 : nWritten; 1944 + 1945 +} 1946 + 1947 +static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj) 1948 +{ 1949 + if (inode && obj) { 1950 + 1951 + 1952 + /* Check mode against the variant type and attempt to repair if broken. */ 1953 + __u32 mode = obj->yst_mode; 1954 + switch( obj->variantType ){ 1955 + case YAFFS_OBJECT_TYPE_FILE : 1956 + if( ! S_ISREG(mode) ){ 1957 + obj->yst_mode &= ~S_IFMT; 1958 + obj->yst_mode |= S_IFREG; 1959 + } 1960 + 1961 + break; 1962 + case YAFFS_OBJECT_TYPE_SYMLINK : 1963 + if( ! S_ISLNK(mode) ){ 1964 + obj->yst_mode &= ~S_IFMT; 1965 + obj->yst_mode |= S_IFLNK; 1966 + } 1967 + 1968 + break; 1969 + case YAFFS_OBJECT_TYPE_DIRECTORY : 1970 + if( ! S_ISDIR(mode) ){ 1971 + obj->yst_mode &= ~S_IFMT; 1972 + obj->yst_mode |= S_IFDIR; 1973 + } 1974 + 1975 + break; 1976 + case YAFFS_OBJECT_TYPE_UNKNOWN : 1977 + case YAFFS_OBJECT_TYPE_HARDLINK : 1978 + case YAFFS_OBJECT_TYPE_SPECIAL : 1979 + default: 1980 + /* TODO? */ 1981 + break; 1982 + } 1983 + 1257 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_commit_write returning %d\n",nWritten)); 1258 + 1259 + return nWritten; 1260 + 1261 +} 1262 + 1263 + 1264 + 1265 +static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj) 1266 +{ 1267 + if (inode && obj) 1268 + { 1984 1269 + inode->i_ino = obj->objectId; 1985 1270 + inode->i_mode = obj->yst_mode; … … 1990 1275 + 1991 1276 + inode->i_rdev = old_decode_dev(obj->yst_rdev); 1992 + inode->i_atime.tv_sec = (time_t) (obj->yst_atime);1277 + inode->i_atime.tv_sec = (time_t)(obj->yst_atime); 1993 1278 + inode->i_atime.tv_nsec = 0; 1994 + inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;1995 + inode->i_mtime.tv_nsec = 0;1996 + inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;1279 + inode->i_mtime.tv_sec = (time_t)obj->yst_mtime; 1280 + inode->i_mtime.tv_nsec =0; 1281 + inode->i_ctime.tv_sec = (time_t)obj->yst_ctime; 1997 1282 + inode->i_ctime.tv_nsec = 0; 1998 1283 +#else … … 2006 1291 + 2007 1292 + inode->i_nlink = yaffs_GetObjectLinkCount(obj); 2008 + 2009 + T(YAFFS_TRACE_OS, 2010 + (KERN_DEBUG 2011 + "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", 2012 + inode->i_mode, inode->i_uid, inode->i_gid, 2013 + (int)inode->i_size, atomic_read(&inode->i_count))); 2014 + 2015 + switch (obj->yst_mode & S_IFMT) { 2016 + default: /* fifo, device or socket */ 1293 + 1294 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", 1295 + inode->i_mode, inode->i_uid, inode->i_gid, (int)inode->i_size, atomic_read(&inode->i_count))); 1296 + 1297 + switch (obj->yst_mode & S_IFMT) 1298 + { 1299 + default: // fifo, device or socket 2017 1300 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 2018 + init_special_inode(inode, obj->yst_mode, 2019 + old_decode_dev(obj->yst_rdev)); 1301 + init_special_inode(inode, obj->yst_mode,old_decode_dev(obj->yst_rdev)); 2020 1302 +#else 2021 + init_special_inode(inode, obj->yst_mode, 2022 + (dev_t) (obj->yst_rdev)); 2023 +#endif 2024 + break; 2025 + case S_IFREG: /* file */ 2026 + inode->i_op = &yaffs_file_inode_operations; 2027 + inode->i_fop = &yaffs_file_operations; 2028 + inode->i_mapping->a_ops = 2029 + &yaffs_file_address_operations; 2030 + break; 2031 + case S_IFDIR: /* directory */ 2032 + inode->i_op = &yaffs_dir_inode_operations; 2033 + inode->i_fop = &yaffs_dir_operations; 2034 + break; 2035 + case S_IFLNK: /* symlink */ 2036 + inode->i_op = &yaffs_symlink_inode_operations; 2037 + break; 2038 + } 2039 + 1303 + init_special_inode(inode, obj->yst_mode,(dev_t)(obj->yst_rdev)); 1304 +#endif 1305 + break; 1306 + case S_IFREG: // file 1307 + inode->i_op = &yaffs_file_inode_operations; 1308 + inode->i_fop = &yaffs_file_operations; 1309 + inode->i_mapping->a_ops = &yaffs_file_address_operations; 1310 + break; 1311 + case S_IFDIR: // directory 1312 + inode->i_op = &yaffs_dir_inode_operations; 1313 + inode->i_fop = &yaffs_dir_operations; 1314 + break; 1315 + case S_IFLNK: // symlink 1316 + inode->i_op = &yaffs_symlink_inode_operations; 1317 + break; 1318 + } 1319 + 1320 + 2040 1321 + inode->u.generic_ip = obj; 2041 1322 + obj->myInode = inode; 2042 + 2043 + } else { 2044 + T(YAFFS_TRACE_OS, 2045 + (KERN_DEBUG "yaffs_FileInode invalid parameters\n")); 2046 + } 2047 + 2048 +} 2049 + 2050 +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, 2051 + yaffs_Object * obj) 2052 +{ 2053 + struct inode *inode; 2054 + 2055 + if (!sb) { 2056 + T(YAFFS_TRACE_OS, 2057 + (KERN_DEBUG "yaffs_get_inode for NULL super_block!!\n")); 2058 + return NULL; 2059 + 2060 + } 2061 + 2062 + if (!obj) { 2063 + T(YAFFS_TRACE_OS, 2064 + (KERN_DEBUG "yaffs_get_inode for NULL object!!\n")); 2065 + return NULL; 2066 + 2067 + } 2068 + 2069 + T(YAFFS_TRACE_OS, 2070 + (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId)); 2071 + 2072 + inode = iget(sb, obj->objectId); 2073 + 2074 + /* NB Side effect: iget calls back to yaffs_read_inode(). */ 2075 + /* iget also increments the inode's i_count */ 2076 + /* NB You can't be holding grossLock or deadlock will happen! */ 2077 + 1323 + 1324 + } 1325 + else 1326 + { 1327 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_FileInode invalid parameters\n")); 1328 + } 1329 + 1330 +} 1331 + 1332 +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj) 1333 +{ 1334 + struct inode * inode; 1335 + 1336 + if(!sb) 1337 + { 1338 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_get_inode for NULL super_block!!\n")); 1339 + return NULL; 1340 + 1341 + } 1342 + 1343 + if(!obj) 1344 + { 1345 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_get_inode for NULL object!!\n")); 1346 + return NULL; 1347 + 1348 + } 1349 + 1350 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_get_inode for object %d\n",obj->objectId)); 1351 + 1352 + inode = iget(sb,obj->objectId); 1353 + 1354 + // NB Side effect: iget calls back to yaffs_read_inode(). 1355 + // iget also increments the inode's i_count 1356 + 2078 1357 + return inode; 2079 1358 +} 2080 1359 + 2081 +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, 2082 + loff_t * pos) 1360 +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos) 2083 1361 +{ 2084 1362 + yaffs_Object *obj; 2085 + int nWritten, ipos;1363 + int nWritten,ipos; 2086 1364 + struct inode *inode; 2087 1365 + yaffs_Device *dev; 2088 + 2089 + obj = yaffs_DentryToObject(f->f_dentry); 2090 + 1366 + 1367 + 1368 + obj = yaffs_DentryToObject(f->f_dentry); 1369 + 2091 1370 + dev = obj->myDev; 2092 + 1371 + 2093 1372 + yaffs_GrossLock(dev); 2094 1373 + 2095 1374 + inode = f->f_dentry->d_inode; 2096 1375 + 2097 + if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) { 1376 + if(!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) 1377 + { 2098 1378 + ipos = inode->i_size; 2099 + } else { 1379 + } 1380 + else 1381 + { 2100 1382 + ipos = *pos; 2101 1383 + } 2102 + 2103 + if (!obj) { 2104 + T(YAFFS_TRACE_OS, 2105 + (KERN_DEBUG "yaffs_file_write: hey obj is null!\n")); 2106 + } else { 2107 + T(YAFFS_TRACE_OS, 2108 + (KERN_DEBUG 2109 + "yaffs_file_write about to write writing %d bytes" 2110 + "to object %d at %d\n", 2111 + n, obj->objectId, ipos)); 2112 + } 2113 + 2114 + nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0); 2115 + 2116 + T(YAFFS_TRACE_OS, 2117 + (KERN_DEBUG "yaffs_file_write writing %d bytes, %d written at %d\n", 2118 + n, nWritten, ipos)); 2119 + if (nWritten > 0) { 1384 + 1385 + 1386 + if(!obj) 1387 + { 1388 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write: hey obj is null!\n")); 1389 + } 1390 + else 1391 + { 1392 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write about to write writing %d bytes to object %d at %d\n",n,obj->objectId,ipos)); 1393 + } 1394 + 1395 + nWritten = yaffs_WriteDataToFile(obj,buf,ipos,n,0); 1396 + 1397 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write writing %d bytes, %d written at %d\n",n,nWritten,ipos)); 1398 + if(nWritten > 0) 1399 + { 2120 1400 + ipos += nWritten; 2121 1401 + *pos = ipos; 2122 + if (ipos > inode->i_size) { 1402 + if(ipos > inode->i_size) 1403 + { 2123 1404 + inode->i_size = ipos; 2124 + inode->i_blocks = (ipos + 511) >> 9; 2125 + 2126 + T(YAFFS_TRACE_OS, 2127 + (KERN_DEBUG 2128 + "yaffs_file_write size updated to %d bytes, " 2129 + "%d blocks\n", 2130 + ipos, (int)(inode->i_blocks))); 2131 + } 2132 + 1405 + inode->i_blocks = (ipos + 511)>>9; 1406 + 1407 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write size updated to %d bytes, %d blocks\n",ipos,(int)(inode->i_blocks))); 1408 + } 1409 + 2133 1410 + } 2134 1411 + yaffs_GrossUnlock(dev); 2135 + return nWritten == 0 ? -ENOSPC : nWritten; 2136 +} 1412 + 1413 + return nWritten != n ? -ENOSPC : nWritten; 1414 +} 1415 + 1416 + 2137 1417 + 2138 1418 +static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) … … 2142 1422 + struct inode *inode = f->f_dentry->d_inode; 2143 1423 + unsigned long offset, curoffs; 2144 + struct list_head *i; 1424 + struct list_head *i; 2145 1425 + yaffs_Object *l; 2146 + 2147 + char name[YAFFS_MAX_NAME_LENGTH +1];2148 + 2149 + obj = yaffs_DentryToObject(f->f_dentry);1426 + 1427 + char name[YAFFS_MAX_NAME_LENGTH +1]; 1428 + 1429 + obj = yaffs_DentryToObject(f->f_dentry); 2150 1430 + dev = obj->myDev; 2151 + 1431 + 2152 1432 + yaffs_GrossLock(dev); 2153 + 1433 + 2154 1434 + offset = f->f_pos; 2155 + 2156 + T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset)); 2157 + 2158 + if (offset == 0) { 2159 + T(YAFFS_TRACE_OS, 2160 + (KERN_DEBUG "yaffs_readdir: entry . ino %d \n", 2161 + (int)inode->i_ino)); 2162 + if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) 2163 + < 0) { 1435 + 1436 + T(YAFFS_TRACE_OS,("yaffs_readdir: starting at %d\n",(int)offset)); 1437 + 1438 + if(offset == 0) 1439 + { 1440 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readdir: entry . ino %d \n",(int)inode->i_ino)); 1441 + if(filldir(dirent,".",1,offset,inode->i_ino,DT_DIR) < 0) 1442 + { 2164 1443 + goto out; 2165 1444 + } … … 2167 1446 + f->f_pos++; 2168 1447 + } 2169 + if (offset == 1) { 2170 + T(YAFFS_TRACE_OS, 2171 + (KERN_DEBUG "yaffs_readdir: entry .. ino %d \n", 2172 + (int)f->f_dentry->d_parent->d_inode->i_ino)); 2173 + if (filldir 2174 + (dirent, "..", 2, offset, 2175 + f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { 1448 + if(offset == 1) 1449 + { 1450 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readdir: entry .. ino %d \n",(int)f->f_dentry->d_parent->d_inode->i_ino)); 1451 + if(filldir(dirent,"..",2,offset,f->f_dentry->d_parent->d_inode->i_ino,DT_DIR) < 0) 1452 + { 2176 1453 + goto out; 2177 1454 + } … … 2179 1456 + f->f_pos++; 2180 1457 + } 2181 + 1458 + 2182 1459 + curoffs = 1; 2183 + 2184 + /* If the directory has changed since the open or last call to 2185 + readdir, rewind to after the 2 canned entries. */ 2186 + 2187 + if (f->f_version != inode->i_version) { 2188 + offset = 2; 2189 + f->f_pos = offset; 2190 + f->f_version = inode->i_version; 2191 + } 2192 + 2193 + list_for_each(i, &obj->variant.directoryVariant.children) { 1460 + 1461 + list_for_each(i,&obj->variant.directoryVariant.children) 1462 + { 2194 1463 + curoffs++; 2195 + if (curoffs >= offset) { 2196 + l = list_entry(i, yaffs_Object, siblings); 2197 + 2198 + yaffs_GetObjectName(l, name, 2199 + YAFFS_MAX_NAME_LENGTH + 1); 2200 + T(YAFFS_TRACE_OS, 2201 + (KERN_DEBUG "yaffs_readdir: %s inode %d\n", name, 2202 + yaffs_GetObjectInode(l))); 2203 + 2204 + if (filldir(dirent, 2205 + name, 2206 + strlen(name), 2207 + offset, 2208 + yaffs_GetObjectInode(l), 2209 + yaffs_GetObjectType(l)) 2210 + < 0) { 1464 + if(curoffs >= offset) 1465 + { 1466 + l = list_entry(i, yaffs_Object,siblings); 1467 + 1468 + yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1); 1469 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readdir: %s inode %d\n",name,yaffs_GetObjectInode(l))); 1470 + 1471 + if(filldir(dirent, 1472 + name, 1473 + strlen(name), 1474 + offset, 1475 + yaffs_GetObjectInode(l), 1476 + yaffs_GetObjectType(l)) 1477 + < 0) 1478 + { 2211 1479 + goto up_and_out; 2212 1480 + } 2213 + 1481 + 2214 1482 + offset++; 2215 + f->f_pos++; 2216 + } 2217 + } 2218 + 2219 + up_and_out:2220 + out:2221 + 2222 + yaffs_GrossUnlock(dev);2223 + 1483 + f->f_pos++; 1484 + } 1485 + } 1486 + 1487 + up_and_out: 1488 + out: 1489 + 1490 + yaffs_GrossUnlock(dev); 1491 + 2224 1492 + return 0; 2225 1493 +} 1494 + 2226 1495 + 2227 1496 +/* … … 2229 1498 + */ 2230 1499 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 2231 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, 2232 + dev_t rdev) 1500 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) 2233 1501 +#else 2234 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, 2235 + int rdev) 1502 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) 2236 1503 +#endif 2237 1504 +{ 2238 1505 + struct inode *inode; 2239 + 1506 + 2240 1507 + yaffs_Object *obj = NULL; 2241 1508 + yaffs_Device *dev; 2242 + 1509 + 2243 1510 + yaffs_Object *parent = yaffs_InodeToObject(dir); 2244 + 1511 + 2245 1512 + int error = -ENOSPC; 2246 1513 + uid_t uid = current->fsuid; 2247 1514 + gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; 2248 + 2249 + if((dir->i_mode & S_ISGID) && S_ISDIR(mode)) 2250 + mode |= S_ISGID; 2251 + 2252 + if (parent) { 2253 + T(YAFFS_TRACE_OS, 2254 + (KERN_DEBUG "yaffs_mknod: parent object %d type %d\n", 2255 + parent->objectId, parent->variantType)); 2256 + } else { 2257 + T(YAFFS_TRACE_OS, 2258 + (KERN_DEBUG "yaffs_mknod: could not get parent object\n")); 1515 + 1516 + if(parent) 1517 + { 1518 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: parent object %d type %d\n", 1519 + parent->objectId,parent->variantType)); 1520 + } 1521 + else 1522 + { 1523 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: could not get parent object\n")); 2259 1524 + return -EPERM; 2260 1525 + } 2261 + 2262 + T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, " 2263 + "mode %x dev %x\n", 2264 + dentry->d_name.name, mode, rdev)); 1526 + 1527 + T(YAFFS_TRACE_OS,("yaffs_mknod: making oject for %s, mode %x dev %x\n", 1528 + dentry->d_name.name, mode,rdev)); 2265 1529 + 2266 1530 + dev = parent->myDev; 2267 + 1531 + 2268 1532 + yaffs_GrossLock(dev); 2269 1533 + 2270 + switch (mode & S_IFMT) {2271 + default:2272 + /* Special (socket, fifo, device...) */2273 + T(YAFFS_TRACE_OS, (KERN_DEBUG2274 + "yaffs_mknod: making special\n"));1534 + switch (mode & S_IFMT) 1535 + { 1536 + default: 1537 + // Special (socket, fifo, device...) 1538 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making special\n")); 2275 1539 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 2276 + obj = 2277 + yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, 2278 + gid, old_encode_dev(rdev)); 1540 + obj = yaffs_MknodSpecial(parent,dentry->d_name.name,mode,uid, gid,old_encode_dev(rdev)); 2279 1541 +#else 2280 + obj = 2281 + yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, 2282 + gid, rdev); 2283 +#endif 2284 + break; 2285 + case S_IFREG: /* file */ 2286 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); 2287 + obj = 2288 + yaffs_MknodFile(parent, dentry->d_name.name, mode, uid, 2289 + gid); 2290 + break; 2291 + case S_IFDIR: /* directory */ 2292 + T(YAFFS_TRACE_OS, 2293 + (KERN_DEBUG "yaffs_mknod: making directory\n")); 2294 + obj = 2295 + yaffs_MknodDirectory(parent, dentry->d_name.name, mode, 2296 + uid, gid); 2297 + break; 2298 + case S_IFLNK: /* symlink */ 2299 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); 2300 + obj = NULL; /* Do we ever get here? */ 2301 + break; 2302 + } 2303 + 2304 + /* Can not call yaffs_get_inode() with gross lock held */ 2305 + yaffs_GrossUnlock(dev); 2306 + 2307 + if (obj) { 1542 + obj = yaffs_MknodSpecial(parent,dentry->d_name.name,mode,uid, gid,rdev); 1543 +#endif 1544 + break; 1545 + case S_IFREG: // file 1546 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making file\n")); 1547 + obj = yaffs_MknodFile(parent,dentry->d_name.name,mode,uid, gid); 1548 + break; 1549 + case S_IFDIR: // directory 1550 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making directory\n")); 1551 + obj = yaffs_MknodDirectory(parent,dentry->d_name.name,mode,uid, gid); 1552 + break; 1553 + case S_IFLNK: // symlink 1554 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making file\n")); 1555 + obj = NULL; // Do we ever get here? 1556 + break; 1557 + } 1558 + 1559 + if(obj) 1560 + { 2308 1561 + inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); 2309 1562 + d_instantiate(dentry, inode); 2310 + T(YAFFS_TRACE_OS, 2311 + (KERN_DEBUG "yaffs_mknod created object %d count = %d\n", 2312 + obj->objectId, atomic_read(&inode->i_count))); 1563 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count))); 2313 1564 + error = 0; 2314 + } else { 2315 + T(YAFFS_TRACE_OS, 2316 + (KERN_DEBUG "yaffs_mknod failed making object\n")); 1565 + } 1566 + else 1567 + { 1568 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod failed making object\n")); 2317 1569 + error = -ENOMEM; 2318 1570 + } 2319 1571 + 1572 + yaffs_GrossUnlock(dev); 1573 + 2320 1574 + return error; 2321 1575 +} 2322 1576 + 2323 +static int yaffs_mkdir(struct inode * dir, struct dentry *dentry, int mode)1577 +static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode) 2324 1578 +{ 2325 1579 + int retVal; 2326 + T(YAFFS_TRACE_OS, (KERN_DEBUG"yaffs_mkdir\n"));2327 + retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);1580 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mkdir\n")); 1581 + retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0); 2328 1582 +#if 0 2329 + /* attempt to fix dir bug - didn't work */ 2330 + if (!retVal) { 1583 + // attempt to fix dir bug - didn't work 1584 + if(!retVal) 1585 + { 2331 1586 + dget(dentry); 2332 1587 + } … … 2336 1591 + 2337 1592 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 2338 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, 2339 + struct nameidata *n) 1593 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *n) 2340 1594 +#else 2341 1595 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode) 2342 1596 +#endif 2343 1597 +{ 2344 + T(YAFFS_TRACE_OS, (KERN_DEBUG"yaffs_create\n"));1598 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_create\n")); 2345 1599 + return yaffs_mknod(dir, dentry, mode | S_IFREG, 0); 2346 1600 +} 2347 1601 + 2348 +static int yaffs_unlink(struct inode *dir, struct dentry *dentry) 1602 + 1603 +static int yaffs_unlink(struct inode * dir, struct dentry *dentry) 2349 1604 +{ 2350 1605 + int retVal; 2351 + 1606 + 2352 1607 + yaffs_Device *dev; 2353 + 2354 + T(YAFFS_TRACE_OS, 2355 + (KERN_DEBUG "yaffs_unlink %d:%s\n", (int)(dir->i_ino), 2356 + dentry->d_name.name)); 2357 + 1608 + 1609 + 1610 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_unlink %d:%s\n",(int)(dir->i_ino),dentry->d_name.name)); 1611 + 2358 1612 + dev = yaffs_InodeToObject(dir)->myDev; 2359 + 1613 + 2360 1614 + yaffs_GrossLock(dev); 2361 + 2362 + retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name); 2363 + 2364 + if (retVal == YAFFS_OK) { 1615 + 1616 + 1617 + retVal = yaffs_Unlink(yaffs_InodeToObject(dir),dentry->d_name.name); 1618 + 1619 + 1620 + yaffs_GrossUnlock(dev); 1621 + 1622 + if( retVal == YAFFS_OK) 1623 + { 2365 1624 + dentry->d_inode->i_nlink--; 2366 + dir->i_version++;2367 + yaffs_GrossUnlock(dev);2368 1625 + mark_inode_dirty(dentry->d_inode); 2369 1626 + return 0; 2370 1627 + } 2371 + yaffs_GrossUnlock(dev); 2372 + return -ENOTEMPTY; 2373 +} 1628 + else 1629 + { 1630 + return -ENOTEMPTY; 1631 + } 1632 +} 1633 + 2374 1634 + 2375 1635 +/* 2376 1636 + * Create a link... 2377 1637 + */ 2378 +static int yaffs_link(struct dentry *old_dentry, struct inode *dir, 2379 + struct dentry *dentry) 1638 +static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry) 2380 1639 +{ 2381 1640 + struct inode *inode = old_dentry->d_inode; 2382 1641 + yaffs_Object *obj = NULL; 2383 + yaffs_Object *link =NULL;1642 + yaffs_Object *link=NULL; 2384 1643 + yaffs_Device *dev; 2385 + 2386 + T(YAFFS_TRACE_OS, (KERN_DEBUG"yaffs_link\n"));2387 + 1644 + 1645 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_link\n")); 1646 + 2388 1647 + obj = yaffs_InodeToObject(inode); 2389 1648 + dev = obj->myDev; 2390 + 1649 + 2391 1650 + yaffs_GrossLock(dev); 2392 1651 + 2393 + if (!S_ISDIR(inode->i_mode)) / * Don't link directories */2394 + { 2395 + link = 2396 + yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name,2397 + obj);2398 + }2399 + 2400 + if (link){2401 + old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj);1652 + if (!S_ISDIR(inode->i_mode)) // Don't link directories 1653 + { 1654 + link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj); 1655 + } 1656 + 1657 + 1658 + if(link) 1659 + { 1660 + old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj); 2402 1661 + d_instantiate(dentry, old_dentry->d_inode); 2403 1662 + atomic_inc(&old_dentry->d_inode->i_count); 2404 + T(YAFFS_TRACE_OS, 2405 + (KERN_DEBUG "yaffs_link link count %d i_count %d\n", 2406 + old_dentry->d_inode->i_nlink, 2407 + atomic_read(&old_dentry->d_inode->i_count))); 2408 + 2409 + } 2410 + 1663 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_link link count %d i_count %d\n", 1664 + old_dentry->d_inode->i_nlink,atomic_read(&old_dentry->d_inode->i_count))); 1665 + 1666 + } 1667 + 2411 1668 + yaffs_GrossUnlock(dev); 2412 + 2413 + if (link) { 2414 + 1669 + 1670 + 1671 + if(link) 1672 + { 1673 + 2415 1674 + return 0; 2416 1675 + } 2417 + 2418 + return -EPERM; 2419 +} 2420 + 2421 +static int yaffs_symlink(struct inode *dir, struct dentry *dentry, 2422 + const char *symname) 1676 + 1677 + 1678 + return -EPERM; 1679 +} 1680 + 1681 + 1682 +static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) 2423 1683 +{ 2424 1684 + yaffs_Object *obj; … … 2426 1686 + uid_t uid = current->fsuid; 2427 1687 + gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; 2428 + 2429 + T(YAFFS_TRACE_OS, (KERN_DEBUG"yaffs_symlink\n"));2430 + 1688 + 1689 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_symlink\n")); 1690 + 2431 1691 + dev = yaffs_InodeToObject(dir)->myDev; 2432 1692 + yaffs_GrossLock(dev); 2433 + obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, 2434 + S_IFLNK | S_IRWXUGO, uid, gid, symname); 1693 + obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, 1694 + S_IFLNK | S_IRWXUGO, uid, gid, 1695 + symname); 2435 1696 + yaffs_GrossUnlock(dev); 2436 1697 + 2437 + if (obj) { 2438 + 2439 + struct inode *inode; 2440 + 1698 + if(obj) 1699 + { 1700 + 1701 + struct inode* inode; 1702 + 2441 1703 + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); 2442 1704 + d_instantiate(dentry, inode); 2443 + T(YAFFS_TRACE_OS, (KERN_DEBUG"symlink created OK\n"));1705 + T(YAFFS_TRACE_OS,(KERN_DEBUG"symlink created OK\n")); 2444 1706 + return 0; 2445 + } else { 2446 + T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink not created\n")); 2447 + 2448 + } 2449 + 1707 + } 1708 + else 1709 + { 1710 + T(YAFFS_TRACE_OS,(KERN_DEBUG"symlink not created\n")); 1711 + 1712 + } 1713 + 2450 1714 + return -ENOMEM; 2451 1715 +} 2452 1716 + 2453 +static int yaffs_sync_object(struct file *file, struct dentry *dentry, 2454 + int datasync) 1717 +static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync) 2455 1718 +{ 2456 1719 + 2457 1720 + yaffs_Object *obj; 2458 1721 + yaffs_Device *dev; 2459 + 1722 + 2460 1723 + obj = yaffs_DentryToObject(dentry); 2461 1724 + 2462 1725 + dev = obj->myDev; 2463 + 2464 + T(YAFFS_TRACE_OS, (KERN_DEBUG"yaffs_sync_object\n"));1726 + 1727 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_sync_object\n")); 2465 1728 + yaffs_GrossLock(dev); 2466 + yaffs_FlushFile(obj, 1);1729 + yaffs_FlushFile(obj,1); 2467 1730 + yaffs_GrossUnlock(dev); 2468 1731 + return 0; … … 2474 1737 + * NB: POSIX says you can rename an object over an old object of the same name 2475 1738 + */ 2476 +static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, 2477 + struct inode *new_dir, struct dentry *new_dentry) 1739 +static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry) 2478 1740 +{ 2479 1741 + yaffs_Device *dev; 2480 1742 + int retVal = YAFFS_FAIL; 1743 + int removed = 0; 2481 1744 + yaffs_Object *target; 2482 + 2483 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_rename\n")); 1745 + 2484 1746 + dev = yaffs_InodeToObject(old_dir)->myDev; 2485 1747 + 2486 1748 + yaffs_GrossLock(dev); 2487 + 2488 + /* Check if the target is an existing directory that is not empty. */ 2489 + target = 2490 + yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), 2491 + new_dentry->d_name.name); 2492 + 2493 + 2494 + 2495 + if (target && 2496 + target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && 2497 + !list_empty(&target->variant.directoryVariant.children)) { 2498 + 2499 + T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n")); 2500 + 1749 + 1750 + // Check if the target is an existing directory that is not empty. 1751 + target = yaffs_FindObjectByName(yaffs_InodeToObject(new_dir),new_dentry->d_name.name); 1752 + 1753 + if(target && 1754 + target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && 1755 + !list_empty(&target->variant.directoryVariant.children)) 1756 + { 2501 1757 + retVal = YAFFS_FAIL; 2502 + } else {2503 + 2504 + /* Now does unlinking internally using shadowing mechanism */2505 + T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n"));2506 + 2507 + re tVal =2508 + yaffs_RenameObject(yaffs_InodeToObject(old_dir),2509 + old_dentry->d_name.name,2510 + yaffs_InodeToObject(new_dir),2511 + new_dentry->d_name.name);2512 + 1758 + } 1759 + else 1760 + { 1761 + 1762 + // Unlink the target if it exists 1763 + removed = yaffs_Unlink(yaffs_InodeToObject(new_dir),new_dentry->d_name.name); 1764 + 1765 + 1766 + retVal = yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name, 1767 + yaffs_InodeToObject(new_dir),new_dentry->d_name.name); 1768 + 2513 1769 + } 2514 1770 + yaffs_GrossUnlock(dev); 2515 + 2516 + if (retVal == YAFFS_OK) { 2517 + if(target) { 1771 + 1772 + if(retVal == YAFFS_OK) 1773 + { 1774 + if(removed == YAFFS_OK) 1775 + { 2518 1776 + new_dentry->d_inode->i_nlink--; 2519 1777 + mark_inode_dirty(new_dentry->d_inode); 2520 1778 + } 2521 + 1779 + 2522 1780 + return 0; 2523 + } else { 1781 + } 1782 + else 1783 + { 2524 1784 + return -ENOTEMPTY; 2525 1785 + } 1786 + 2526 1787 + 2527 1788 +} … … 2532 1793 + int error; 2533 1794 + yaffs_Device *dev; 2534 + 2535 + T(YAFFS_TRACE_OS, 2536 + (KERN_DEBUG "yaffs_setattr of object %d\n", 2537 + yaffs_InodeToObject(inode)->objectId)); 2538 + 2539 + if ((error = inode_change_ok(inode, attr)) == 0) { 2540 + 1795 + 1796 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_setattr of object %d\n",yaffs_InodeToObject(inode)->objectId)); 1797 + 1798 + if((error = inode_change_ok(inode,attr)) == 0) 1799 + { 1800 + 2541 1801 + dev = yaffs_InodeToObject(inode)->myDev; 2542 1802 + yaffs_GrossLock(dev); 2543 + if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) ==2544 + YAFFS_OK){1803 + if(yaffs_SetAttributes(yaffs_InodeToObject(inode),attr) == YAFFS_OK) 1804 + { 2545 1805 + error = 0; 2546 + } else { 1806 + } 1807 + else 1808 + { 2547 1809 + error = -EPERM; 2548 1810 + } 2549 1811 + yaffs_GrossUnlock(dev); 2550 1812 + if (!error) 2551 + error = inode_setattr(inode, attr);1813 + error = inode_setattr(inode,attr); 2552 1814 + } 2553 1815 + return error; 2554 1816 +} 2555 1817 + 2556 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))2557 1818 +static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) 2558 1819 +{ 1820 + 1821 + 2559 1822 + yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; 2560 1823 + struct super_block *sb = dentry->d_sb; 2561 +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 2562 +static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf) 2563 +{ 2564 + yaffs_Device *dev = yaffs_SuperToDevice(sb); 2565 +#else 2566 +static int yaffs_statfs(struct super_block *sb, struct statfs *buf) 2567 +{ 2568 + yaffs_Device *dev = yaffs_SuperToDevice(sb); 2569 +#endif 2570 + 2571 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n")); 1824 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_statfs\n")); 2572 1825 + 2573 1826 + yaffs_GrossLock(dev); 2574 + 1827 + 1828 + 2575 1829 + buf->f_type = YAFFS_MAGIC; 2576 1830 + buf->f_bsize = sb->s_blocksize; 2577 1831 + buf->f_namelen = 255; 2578 + if (sb->s_blocksize > dev->nDataBytesPerChunk) { 2579 + 2580 + buf->f_blocks = 2581 + (dev->endBlock - dev->startBlock + 2582 + 1) * dev->nChunksPerBlock / (sb->s_blocksize / 2583 + dev->nDataBytesPerChunk); 2584 + buf->f_bfree = 2585 + yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize / 2586 + dev->nDataBytesPerChunk); 2587 + } else { 2588 + 2589 + buf->f_blocks = 2590 + (dev->endBlock - dev->startBlock + 2591 + 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk / 2592 + sb->s_blocksize); 2593 + buf->f_bfree = 2594 + yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk / 2595 + sb->s_blocksize); 1832 + if(sb->s_blocksize > dev->nBytesPerChunk) 1833 + { 1834 + 1835 + buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock/ 1836 + (sb->s_blocksize/dev->nBytesPerChunk); 1837 + buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev)/ 1838 + (sb->s_blocksize/dev->nBytesPerChunk); 1839 + } 1840 + else 1841 + { 1842 + 1843 + buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock * 1844 + (dev->nBytesPerChunk/sb->s_blocksize); 1845 + buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev) * 1846 + (dev->nBytesPerChunk/sb->s_blocksize); 2596 1847 + } 2597 1848 + buf->f_files = 0; 2598 1849 + buf->f_ffree = 0; 2599 + buf->f_bavail = buf->f_bfree;2600 + 1850 + buf->f_bavail = buf->f_bfree; 1851 + 2601 1852 + yaffs_GrossUnlock(dev); 2602 1853 + return 0; 2603 1854 +} 2604 1855 + 2605 + 2606 + 2607 +static int yaffs_do_sync_fs(struct super_block *sb) 2608 +{ 2609 + 1856 +static void yaffs_read_inode (struct inode *inode) 1857 +{ 1858 + // NB This is called as a side effect of other functions and 1859 + // thus gross locking should always be in place already. 1860 + 1861 + yaffs_Object *obj ; 1862 + yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb); 1863 + 1864 + T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_read_inode for %d\n",(int)inode->i_ino)); 1865 + 1866 + obj = yaffs_FindObjectByNumber(dev,inode->i_ino); 1867 + 1868 + yaffs_FillInodeFromObject(inode,obj); 1869 + 1870 +} 1871 + 1872 +static LIST_HEAD(yaffs_dev_list); 1873 + 1874 +static void yaffs_put_super(struct super_block *sb) 1875 +{ 2610 1876 + yaffs_Device *dev = yaffs_SuperToDevice(sb); 2611 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n")); 2612 + 2613 + if(sb->s_dirt) { 2614 + yaffs_GrossLock(dev); 2615 + 2616 + if(dev) 2617 + yaffs_CheckpointSave(dev); 2618 + 2619 + yaffs_GrossUnlock(dev); 2620 + 2621 + sb->s_dirt = 0; 2622 + } 2623 + return 0; 2624 +} 2625 + 2626 + 2627 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2628 +static void yaffs_write_super(struct super_block *sb) 2629 +#else 2630 +static int yaffs_write_super(struct super_block *sb) 2631 +#endif 2632 +{ 2633 + 2634 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n")); 2635 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) 2636 + return 0; /* yaffs_do_sync_fs(sb);*/ 2637 +#endif 2638 +} 2639 + 2640 + 2641 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2642 +static int yaffs_sync_fs(struct super_block *sb, int wait) 2643 +#else 2644 +static int yaffs_sync_fs(struct super_block *sb) 2645 +#endif 2646 +{ 2647 + 2648 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); 2649 + 2650 + return 0; /* yaffs_do_sync_fs(sb);*/ 2651 + 2652 +} 2653 + 2654 + 2655 +static void yaffs_read_inode(struct inode *inode) 2656 +{ 2657 + /* NB This is called as a side effect of other functions, but 2658 + * we had to release the lock to prevent deadlocks, so 2659 + * need to lock again. 2660 + */ 2661 + 2662 + yaffs_Object *obj; 2663 + yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb); 2664 + 2665 + T(YAFFS_TRACE_OS, 2666 + (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); 2667 + 1877 + 2668 1878 + yaffs_GrossLock(dev); 2669 + 2670 + obj = yaffs_FindObjectByNumber(dev, inode->i_ino); 2671 + 2672 + yaffs_FillInodeFromObject(inode, obj); 2673 + 2674 + yaffs_GrossUnlock(dev); 2675 +} 2676 + 2677 +static LIST_HEAD(yaffs_dev_list); 2678 + 2679 +static void yaffs_put_super(struct super_block *sb) 2680 +{ 2681 + yaffs_Device *dev = yaffs_SuperToDevice(sb); 2682 + 2683 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n")); 2684 + 2685 + yaffs_GrossLock(dev); 2686 + 2687 + yaffs_FlushEntireDeviceCache(dev); 2688 + 2689 + if (dev->putSuperFunc) { 2690 + dev->putSuperFunc(sb); 2691 + } 2692 + 2693 + yaffs_CheckpointSave(dev); 1879 + if(dev->putSuperFunc) 1880 + { 1881 + dev->putSuperFunc(sb); 1882 + } 2694 1883 + yaffs_Deinitialise(dev); 2695 +2696 1884 + yaffs_GrossUnlock(dev); 2697 1885 + 2698 1886 + /* we assume this is protected by lock_kernel() in mount/umount */ 2699 1887 + list_del(&dev->devList); 2700 +2701 + if(dev->spareBuffer){2702 + YFREE(dev->spareBuffer);2703 + dev->spareBuffer = NULL;2704 + }2705 1888 + 2706 1889 + kfree(dev); … … 2708 1891 + 2709 1892 + 2710 +static void yaffs_MTDPutSuper(struct super_block *sb) 2711 +{ 2712 + 1893 +#ifdef CONFIG_YAFFS_YAFFS1 1894 + 1895 +static void yaffs_MTDPutSuper(struct super_block *sb) 1896 +{ 1897 + 2713 1898 + struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; 2714 + 2715 + if (mtd->sync) { 1899 + 1900 + if(mtd->sync) 1901 + { 2716 1902 + mtd->sync(mtd); 2717 1903 + } 2718 + 1904 + 2719 1905 + put_mtd_device(mtd); 2720 1906 +} 2721 1907 + 2722 + 2723 +static void yaffs_MarkSuperBlockDirty(void *vsb) 2724 +{ 2725 + struct super_block *sb = (struct super_block *)vsb; 2726 + 2727 + T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb)); 2728 +// if(sb) 2729 +// sb->s_dirt = 1; 2730 +} 2731 + 2732 +static struct super_block *yaffs_internal_read_super(int yaffsVersion, 2733 + struct super_block *sb, 2734 + void *data, int silent) 1908 +#endif 1909 + 1910 + 1911 +static struct super_block *yaffs_internal_read_super(int yaffsVersion, struct super_block * sb, void * data, int silent) 2735 1912 +{ 2736 1913 + int nBlocks; 2737 + struct inode * inode = NULL;2738 + struct dentry * root;1914 + struct inode * inode = NULL; 1915 + struct dentry * root; 2739 1916 + yaffs_Device *dev = 0; 2740 + char devname_buf[BDEVNAME_SIZE +1];1917 + char devname_buf[BDEVNAME_SIZE+1]; 2741 1918 + struct mtd_info *mtd; 2742 1919 + int err; 2743 + 1920 + 2744 1921 + sb->s_magic = YAFFS_MAGIC; 2745 1922 + sb->s_op = &yaffs_super_ops; 2746 + 2747 + if (!sb)2748 + printk(KERN_INFO "yaffs: sb is NULL\n");2749 + else if (!sb->s_dev)2750 + printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");2751 + else if (!yaffs_devname(sb, devname_buf))2752 + printk(KERN_INFO "yaffs: devname is NULL\n");1923 + 1924 + if(!sb) 1925 + printk(KERN_INFO"yaffs: sb is NULL\n"); 1926 + else if(!sb->s_dev) 1927 + printk(KERN_INFO"yaffs: sb->s_dev is NULL\n"); 1928 + else if(!yaffs_devname(sb, devname_buf)) 1929 + printk(KERN_INFO"yaffs: devname is NULL\n"); 2753 1930 + else 2754 + printk(KERN_INFO "yaffs: dev is %d name is \"%s\"\n",2755 + sb->s_dev,2756 + yaffs_devname(sb, devname_buf));1931 + printk(KERN_INFO"yaffs: dev is %d name is \"%s\"\n", sb->s_dev, yaffs_devname(sb, devname_buf)); 1932 + 1933 + 2757 1934 + 2758 1935 + sb->s_blocksize = PAGE_CACHE_SIZE; 2759 1936 + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 2760 + T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion)); 2761 + T(YAFFS_TRACE_OS, 2762 + ("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize))); 1937 + T(YAFFS_TRACE_OS,("yaffs_read_super: Using yaffs%d\n",yaffsVersion)); 1938 + T(YAFFS_TRACE_OS,("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize))); 2763 1939 + 2764 1940 +#ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY 2765 + T(YAFFS_TRACE_OS, 2766 + ("yaffs: Write verification disabled. All guarantees " 2767 + "null and void\n")); 2768 +#endif 2769 + 2770 + T(YAFFS_TRACE_ALWAYS, ("yaffs: Attempting MTD mount on %u.%u, " 2771 + "\"%s\"\n", 2772 + MAJOR(sb->s_dev), MINOR(sb->s_dev), 2773 + yaffs_devname(sb, devname_buf))); 2774 + 2775 + /* Check it's an mtd device..... */ 2776 + if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { 2777 + return NULL; /* This isn't an mtd device */ 2778 + } 2779 + /* Get the device */ 1941 + T(YAFFS_TRACE_OS,("yaffs: Write verification disabled. All guarantees null and void\n")); 1942 +#endif 1943 + 1944 + 1945 + T(YAFFS_TRACE_ALWAYS,("yaffs: Attempting MTD mount on %u.%u, \"%s\"\n", 1946 + MAJOR(sb->s_dev),MINOR(sb->s_dev), yaffs_devname(sb, devname_buf))); 1947 + 1948 + // Check it's an mtd device..... 1949 + if(MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) 1950 + { 1951 + return NULL; // This isn't an mtd device 1952 + } 1953 + 1954 + // Get the device 2780 1955 + mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); 2781 + if (!mtd) { 2782 + T(YAFFS_TRACE_ALWAYS, 2783 + ("yaffs: MTD device #%u doesn't appear to exist\n", 2784 + MINOR(sb->s_dev))); 1956 + if (!mtd) 1957 + { 1958 + T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev))); 2785 1959 + return NULL; 2786 1960 + } 2787 + /* Check it's NAND */ 2788 + if (mtd->type != MTD_NANDFLASH) { 2789 + T(YAFFS_TRACE_ALWAYS, 2790 + ("yaffs: MTD device is not NAND it's type %d\n", mtd->type)); 1961 + 1962 + // Check it's NAND 1963 + if(mtd->type != MTD_NANDFLASH) 1964 + { 1965 + T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device is not NAND it's type %d\n", mtd->type)); 2791 1966 + return NULL; 2792 1967 + } 2793 1968 + 2794 + T(YAFFS_TRACE_OS, (" erase %p\n", mtd->erase)); 2795 + T(YAFFS_TRACE_OS, (" read %p\n", mtd->read)); 2796 + T(YAFFS_TRACE_OS, (" write %p\n", mtd->write)); 2797 + T(YAFFS_TRACE_OS, (" readoob %p\n", mtd->read_oob)); 2798 + T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob)); 2799 + T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad)); 2800 + T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad)); 2801 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2802 + T(YAFFS_TRACE_OS, (" writesize %d\n", mtd->writesize)); 1969 + T(YAFFS_TRACE_OS,(" erase %p\n",mtd->erase)); 1970 + T(YAFFS_TRACE_OS,(" read %p\n",mtd->read)); 1971 + T(YAFFS_TRACE_OS,(" write %p\n",mtd->write)); 1972 + T(YAFFS_TRACE_OS,(" readoob %p\n",mtd->read_oob)); 1973 + T(YAFFS_TRACE_OS,(" writeoob %p\n",mtd->write_oob)); 1974 +// T(YAFFS_TRACE_OS,(" block_isbad %p\n",mtd->block_isbad)); 1975 +// T(YAFFS_TRACE_OS,(" block_markbad %p\n",mtd->block_markbad)); 1976 + T(YAFFS_TRACE_OS,(" writesize %d\n",mtd->writesize)); 1977 + T(YAFFS_TRACE_OS,(" oobsize %d\n",mtd->oobsize)); 1978 + T(YAFFS_TRACE_OS,(" erasesize %d\n",mtd->erasesize)); 1979 + T(YAFFS_TRACE_OS,(" size %d\n",mtd->size)); 1980 + 1981 + if(yaffsVersion == 2) 1982 + { 1983 + // Check for version 2 style functions 1984 + if(!mtd->erase || 1985 +// !mtd->block_isbad || 1986 +// !mtd->block_markbad || 1987 + !mtd->read || 1988 + !mtd->write || 1989 +// !mtd->write_ecc || 1990 +// !mtd->read_ecc || 1991 + !mtd->read_oob || 1992 + !mtd->write_oob ) 1993 + { 1994 + T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support required functions\n"));; 1995 + return NULL; 1996 + } 1997 + 1998 + if(mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE || 1999 + mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) 2000 + { 2001 + T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support have the right page sizes\n")); 2002 + return NULL; 2003 + } } 2004 + else 2005 + { 2006 + // Check for V1 style functions 2007 + if(!mtd->erase || 2008 + !mtd->read || 2009 + !mtd->write || 2010 +// !mtd->write_ecc || 2011 +// !mtd->read_ecc || 2012 + !mtd->read_oob || 2013 + !mtd->write_oob ) 2014 + { 2015 + T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support required functions\n"));; 2016 + return NULL; 2017 + } 2018 + 2019 + if(mtd->writesize != YAFFS_BYTES_PER_CHUNK || 2020 + mtd->oobsize != YAFFS_BYTES_PER_SPARE) 2021 + { 2022 + T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support have the right page sizes\n")); 2023 + return NULL; 2024 + } 2025 + } 2026 + 2027 + 2028 + // OK, so if we got here, we have an MTD that's NAND and looks 2029 + // like it has the right capabilities 2030 + // Set the yaffs_Device up for mtd 2031 + 2032 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 2033 + sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL); 2803 2034 +#else 2804 + T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock)); 2805 +#endif 2806 + T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); 2807 + T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); 2808 + T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); 2809 + 2810 +#ifdef CONFIG_YAFFS_AUTO_YAFFS2 2811 + 2812 + if (yaffsVersion == 1 && 2813 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2814 + mtd->writesize >= 2048) { 2815 +#else 2816 + mtd->oobblock >= 2048) { 2817 +#endif 2818 + T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); 2819 + yaffsVersion = 2; 2820 + } 2821 + 2822 + /* Added NCB 26/5/2006 for completeness */ 2823 + if (yaffsVersion == 2 && 2824 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2825 + mtd->writesize == 512) { 2826 +#else 2827 + mtd->oobblock == 512) { 2828 +#endif 2829 + T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); 2830 + yaffsVersion = 1; 2831 + } 2832 + 2833 +#endif 2834 + 2835 + if (yaffsVersion == 2) { 2836 + /* Check for version 2 style functions */ 2837 + if (!mtd->erase || 2838 + !mtd->block_isbad || 2839 + !mtd->block_markbad || 2840 + !mtd->read || 2841 + !mtd->write || 2842 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2843 + !mtd->read_oob || !mtd->write_oob) { 2844 +#else 2845 + !mtd->write_ecc || 2846 + !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { 2847 +#endif 2848 + T(YAFFS_TRACE_ALWAYS, 2849 + ("yaffs: MTD device does not support required " 2850 + "functions\n"));; 2851 + return NULL; 2852 + } 2853 + 2854 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2855 + if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE || 2856 +#else 2857 + if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE || 2858 +#endif 2859 + mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) { 2860 + T(YAFFS_TRACE_ALWAYS, 2861 + ("yaffs: MTD device does not have the " 2862 + "right page sizes\n")); 2863 + return NULL; 2864 + } 2865 + } else { 2866 + /* Check for V1 style functions */ 2867 + if (!mtd->erase || 2868 + !mtd->read || 2869 + !mtd->write || 2870 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2871 + !mtd->read_oob || !mtd->write_oob) { 2872 +#else 2873 + !mtd->write_ecc || 2874 + !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { 2875 +#endif 2876 + T(YAFFS_TRACE_ALWAYS, 2877 + ("yaffs: MTD device does not support required " 2878 + "functions\n"));; 2879 + return NULL; 2880 + } 2881 + 2882 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2883 + if (mtd->writesize < YAFFS_BYTES_PER_CHUNK || 2884 +#else 2885 + if (mtd->oobblock < YAFFS_BYTES_PER_CHUNK || 2886 +#endif 2887 + mtd->oobsize != YAFFS_BYTES_PER_SPARE) { 2888 + T(YAFFS_TRACE_ALWAYS, 2889 + ("yaffs: MTD device does not support have the " 2890 + "right page sizes\n")); 2891 + return NULL; 2892 + } 2893 + } 2894 + 2895 + /* OK, so if we got here, we have an MTD that's NAND and looks 2896 + * like it has the right capabilities 2897 + * Set the yaffs_Device up for mtd 2898 + */ 2899 + 2900 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 2901 + sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); 2902 +#else 2903 + sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); 2904 +#endif 2905 + if (!dev) { 2906 + /* Deep shit could not allocate device structure */ 2907 + T(YAFFS_TRACE_ALWAYS, 2908 + ("yaffs_read_super: Failed trying to allocate " 2909 + "yaffs_Device. \n")); 2035 + sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL); 2036 +#endif 2037 + if(!dev) 2038 + { 2039 + // Deep shit could not allocate device structure 2040 + T(YAFFS_TRACE_ALWAYS,("yaffs_read_super: Failed trying to allocate yaffs_Device. \n")); 2910 2041 + return NULL; 2911 2042 + } 2912 2043 + 2913 + memset(dev, 0,sizeof(yaffs_Device));2914 + dev->genericDevice = mtd; 2044 + memset(dev,0,sizeof(yaffs_Device)); 2045 + dev->genericDevice = mtd; 2915 2046 + dev->name = mtd->name; 2916 2047 + 2917 + / * Set up the memory size parameters.... */2918 + 2048 + // Set up the memory size parameters.... 2049 + 2919 2050 + nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); 2920 2051 + dev->startBlock = 0; 2921 2052 + dev->endBlock = nBlocks - 1; 2922 2053 + dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; 2923 + dev->n DataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;2054 + dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK; 2924 2055 + dev->nReservedBlocks = 5; 2925 + dev->nShortOpCaches = 10; /* Enable short op caching */2926 + 2927 + /* ... and the functions. */2928 + if (yaffsVersion == 2) {2929 + dev->writeChunkWithTagsToNAND =2930 + nandmtd2_WriteChunkWithTagsToNAND;2931 + dev-> readChunkWithTagsFromNAND =2932 + nandmtd2_ReadChunkWithTagsFromNAND;2056 + dev->nShortOpCaches = 10; // Enable short op caching 2057 + 2058 + 2059 + // ... and the functions. 2060 + if(yaffsVersion == 2) 2061 + { 2062 + dev->writeChunkWithTagsToNAND = nandmtd2_WriteChunkWithTagsToNAND; 2063 + dev->readChunkWithTagsFromNAND = nandmtd2_ReadChunkWithTagsFromNAND; 2933 2064 + dev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad; 2934 2065 + dev->queryNANDBlock = nandmtd2_QueryNANDBlock; 2935 2066 + dev->spareBuffer = YMALLOC(mtd->oobsize); 2936 2067 + dev->isYaffs2 = 1; 2937 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 2938 + dev->nDataBytesPerChunk = mtd->writesize; 2068 + dev->nBytesPerChunk = mtd->writesize; 2939 2069 + dev->nChunksPerBlock = mtd->erasesize / mtd->writesize; 2940 +#else2941 + dev->nDataBytesPerChunk = mtd->oobblock;2942 + dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;2943 +#endif2944 2070 + nBlocks = mtd->size / mtd->erasesize; 2945 +2946 + dev->nCheckpointReservedBlocks = 10;2947 2071 + dev->startBlock = 0; 2948 2072 + dev->endBlock = nBlocks - 1; 2949 + } else { 2073 + } 2074 + else 2075 + { 2950 2076 + dev->writeChunkToNAND = nandmtd_WriteChunkToNAND; 2951 2077 + dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND; 2952 2078 + dev->isYaffs2 = 0; 2953 2079 + } 2954 + / * ... and common functions */2080 + // ... and common functions 2955 2081 + dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; 2956 2082 + dev->initialiseNAND = nandmtd_InitialiseNAND; 2957 + 2083 + 2958 2084 + dev->putSuperFunc = yaffs_MTDPutSuper; 2959 2085 + 2960 + dev->superBlock = (void *)sb;2961 + dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty;2962 +2963 +2964 2086 +#ifndef CONFIG_YAFFS_DOES_ECC 2965 2087 + dev->useNANDECC = 1; 2966 2088 +#endif 2967 2089 + 2968 +#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES2969 + dev->wideTnodesDisabled = 1;2970 +#endif2971 +2972 2090 + /* we assume this is protected by lock_kernel() in mount/umount */ 2973 2091 + list_add_tail(&dev->devList, &yaffs_dev_list); 2974 2092 + 2975 2093 + init_MUTEX(&dev->grossLock); 2976 + 2094 + 2095 + 2977 2096 + yaffs_GrossLock(dev); 2978 + 2097 + 2979 2098 + err = yaffs_GutsInitialise(dev); 2980 2099 + 2981 + T(YAFFS_TRACE_OS, 2982 + ("yaffs_read_super: guts initialised %s\n", 2983 + (err == YAFFS_OK) ? "OK" : "FAILED")); 2984 + 2985 + /* Release lock before yaffs_get_inode() */ 2100 + T(YAFFS_TRACE_OS,("yaffs_read_super: guts initialised %s\n", (err == YAFFS_OK) ? "OK" : "FAILED")); 2101 + 2102 + // Create root inode 2103 + if(err == YAFFS_OK) 2104 + inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,yaffs_Root(dev)); 2105 + 2986 2106 + yaffs_GrossUnlock(dev); 2987 +2988 + /* Create root inode */2989 + if (err == YAFFS_OK)2990 + inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,2991 + yaffs_Root(dev));2992 2107 + 2993 2108 + if (!inode) 2994 2109 + return NULL; 2995 + 2996 + inode->i_op = &yaffs_dir_inode_operations; 2997 + inode->i_fop = &yaffs_dir_operations; 2998 + 2999 + T(YAFFS_TRACE_OS, ("yaffs_read_super: got root inode\n")); 2110 + 2111 +// added NCB 2112 + inode->i_op = & yaffs_dir_inode_operations; 2113 + inode->i_fop = & yaffs_dir_operations; 2114 + 2115 + T(YAFFS_TRACE_OS,("yaffs_read_super: got root inode\n")); 2116 + 3000 2117 + 3001 2118 + root = d_alloc_root(inode); 3002 2119 + 3003 + T(YAFFS_TRACE_OS, ("yaffs_read_super: d_alloc_root done\n"));2120 + T(YAFFS_TRACE_OS,("yaffs_read_super: d_alloc_root done\n")); 3004 2121 + 3005 2122 + if (!root) { … … 3009 2126 + sb->s_root = root; 3010 2127 + 3011 + T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));2128 + T(YAFFS_TRACE_OS,("yaffs_read_super: done\n")); 3012 2129 + return sb; 3013 2130 +} 3014 2131 + 3015 2132 + 2133 + 2134 +#ifdef CONFIG_YAFFS_YAFFS1 2135 + 3016 2136 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 3017 +static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, 3018 + int silent) 3019 +{ 3020 + return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; 3021 +} 3022 + 3023 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 3024 +static int yaffs_read_super(struct file_system_type *fs, 3025 + int flags, const char *dev_name, 3026 + void *data, struct vfsmount *mnt) 3027 +{ 3028 + 3029 + return get_sb_bdev(fs, flags, dev_name, data, 3030 + yaffs_internal_read_super_mtd, mnt); 3031 +} 3032 +#else 3033 +static struct super_block *yaffs_read_super(struct file_system_type *fs, 3034 + int flags, const char *dev_name, 3035 + void *data) 3036 +{ 3037 + 3038 + return get_sb_bdev(fs, flags, dev_name, data, 3039 + yaffs_internal_read_super_mtd); 3040 +} 3041 +#endif 2137 +static int yaffs_internal_read_super_mtd(struct super_block * sb, void * data, int silent) 2138 +{ 2139 + return yaffs_internal_read_super(1,sb,data,silent) ? 0 : -1; 2140 +} 2141 + 2142 +static struct super_block *yaffs_read_super(struct file_system_type * fs, int flags, const char *dev_name, void *data, struct vfsmount *mnt) 2143 +{ 2144 + 2145 + return get_sb_bdev(fs, flags, dev_name, data, yaffs_internal_read_super_mtd, mnt); 2146 +} 3042 2147 + 3043 2148 +static struct file_system_type yaffs_fs_type = { 3044 + .owner = THIS_MODULE,3045 + .name = "yaffs",3046 + .get_sb = yaffs_read_super,3047 + .kill_sb = kill_block_super,3048 + .fs_flags = FS_REQUIRES_DEV,2149 + .owner = THIS_MODULE, 2150 + .name = "yaffs", 2151 + .get_sb = yaffs_read_super, 2152 + .kill_sb = kill_block_super, 2153 + .fs_flags = FS_REQUIRES_DEV, 3049 2154 +}; 3050 2155 +#else 3051 +static struct super_block *yaffs_read_super(struct super_block *sb, void *data, 3052 + int silent) 3053 +{ 3054 + return yaffs_internal_read_super(1, sb, data, silent); 3055 +} 3056 + 3057 +static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, 3058 + FS_REQUIRES_DEV); 3059 +#endif 3060 + 2156 +static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent) 2157 +{ 2158 + return yaffs_internal_read_super(1,sb,data,silent); 2159 +} 2160 + 2161 +static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV); 2162 +#endif 2163 + 2164 +#endif // CONFIG_YAFFS_YAFFS1 3061 2165 + 3062 2166 +#ifdef CONFIG_YAFFS_YAFFS2 3063 2167 + 3064 2168 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 3065 +static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, 3066 + int silent) 3067 +{ 3068 + return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; 3069 +} 3070 + 3071 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 3072 +static int yaffs2_read_super(struct file_system_type *fs, 3073 + int flags, const char *dev_name, void *data, 3074 + struct vfsmount *mnt) 3075 +{ 3076 + return get_sb_bdev(fs, flags, dev_name, data, 3077 + yaffs2_internal_read_super_mtd, mnt); 3078 +} 3079 +#else 3080 +static struct super_block *yaffs2_read_super(struct file_system_type *fs, 3081 + int flags, const char *dev_name, 3082 + void *data) 3083 +{ 3084 + 3085 + return get_sb_bdev(fs, flags, dev_name, data, 3086 + yaffs2_internal_read_super_mtd); 3087 +} 3088 +#endif 2169 +static int yaffs2_internal_read_super_mtd(struct super_block * sb, void * data, int silent) 2170 +{ 2171 + return yaffs_internal_read_super(2,sb,data,silent) ? 0 : -1; 2172 +} 2173 + 2174 +static struct super_block *yaffs2_read_super(struct file_system_type * fs, int flags, const char *dev_name, void *data, struct vfsmount *mnt) 2175 +{ 2176 + 2177 + return get_sb_bdev(fs, flags, dev_name, data, yaffs2_internal_read_super_mtd, mnt); 2178 +} 3089 2179 + 3090 2180 +static struct file_system_type yaffs2_fs_type = { 3091 + .owner = THIS_MODULE,3092 + .name = "yaffs2",3093 + .get_sb = yaffs2_read_super,3094 + .kill_sb = kill_block_super,3095 + .fs_flags = FS_REQUIRES_DEV,2181 + .owner = THIS_MODULE, 2182 + .name = "yaffs2", 2183 + .get_sb = yaffs2_read_super, 2184 + .kill_sb = kill_block_super, 2185 + .fs_flags = FS_REQUIRES_DEV, 3096 2186 +}; 3097 2187 +#else 3098 +static struct super_block *yaffs2_read_super(struct super_block *sb, 3099 + void *data, int silent) 3100 +{ 3101 + return yaffs_internal_read_super(2, sb, data, silent); 3102 +} 3103 + 3104 +static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, 3105 + FS_REQUIRES_DEV); 3106 +#endif 3107 + 3108 +#endif /* CONFIG_YAFFS_YAFFS2 */ 2188 +static struct super_block *yaffs2_read_super(struct super_block * sb, void * data, int silent) 2189 +{ 2190 + return yaffs_internal_read_super(2,sb,data,silent); 2191 +} 2192 + 2193 +static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, FS_REQUIRES_DEV); 2194 +#endif 2195 + 2196 +#endif // CONFIG_YAFFS_YAFFS2 2197 + 2198 + 2199 + 3109 2200 + 3110 2201 +static struct proc_dir_entry *my_proc_entry; 3111 2202 + 3112 +static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) 3113 +{ 3114 + buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); 3115 + buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); 3116 + buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits); 3117 + buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize); 3118 + buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks); 3119 + buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated); 3120 + buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes); 3121 + buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated); 3122 + buf += sprintf(buf, "nFreeObjects....... %d\n", dev->nFreeObjects); 3123 + buf += sprintf(buf, "nFreeChunks........ %d\n", dev->nFreeChunks); 3124 + buf += sprintf(buf, "nPageWrites........ %d\n", dev->nPageWrites); 3125 + buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads); 3126 + buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures); 3127 + buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies); 3128 + buf += 3129 + sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); 3130 + buf += 3131 + sprintf(buf, "passiveGCs......... %d\n", 3132 + dev->passiveGarbageCollections); 3133 + buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites); 3134 + buf += sprintf(buf, "nRetireBlocks...... %d\n", dev->nRetiredBlocks); 3135 + buf += sprintf(buf, "eccFixed........... %d\n", dev->eccFixed); 3136 + buf += sprintf(buf, "eccUnfixed......... %d\n", dev->eccUnfixed); 3137 + buf += sprintf(buf, "tagsEccFixed....... %d\n", dev->tagsEccFixed); 3138 + buf += sprintf(buf, "tagsEccUnfixed..... %d\n", dev->tagsEccUnfixed); 3139 + buf += sprintf(buf, "cacheHits.......... %d\n", dev->cacheHits); 3140 + buf += sprintf(buf, "nDeletedFiles...... %d\n", dev->nDeletedFiles); 3141 + buf += sprintf(buf, "nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles); 3142 + buf += 3143 + sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); 3144 + buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC); 3145 + buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); 3146 + 3147 + return buf; 3148 +} 3149 + 3150 +static int yaffs_proc_read(char *page, 3151 + char **start, 3152 + off_t offset, int count, int *eof, void *data) 2203 +static char * yaffs_dump_dev(char *buf,yaffs_Device *dev) 2204 +{ 2205 + buf +=sprintf(buf,"startBlock......... %d\n",dev->startBlock); 2206 + buf +=sprintf(buf,"endBlock........... %d\n",dev->endBlock); 2207 + buf +=sprintf(buf,"chunkGroupBits..... %d\n",dev->chunkGroupBits); 2208 + buf +=sprintf(buf,"chunkGroupSize..... %d\n",dev->chunkGroupSize); 2209 + buf +=sprintf(buf,"nErasedBlocks...... %d\n",dev->nErasedBlocks); 2210 + buf +=sprintf(buf,"nTnodesCreated..... %d\n",dev->nTnodesCreated); 2211 + buf +=sprintf(buf,"nFreeTnodes........ %d\n",dev->nFreeTnodes); 2212 + buf +=sprintf(buf,"nObjectsCreated.... %d\n",dev->nObjectsCreated); 2213 + buf +=sprintf(buf,"nFreeObjects....... %d\n",dev->nFreeObjects); 2214 + buf +=sprintf(buf,"nFreeChunks........ %d\n",dev->nFreeChunks); 2215 + buf +=sprintf(buf,"nPageWrites........ %d\n",dev->nPageWrites); 2216 + buf +=sprintf(buf,"nPageReads......... %d\n",dev->nPageReads); 2217 + buf +=sprintf(buf,"nBlockErasures..... %d\n",dev->nBlockErasures); 2218 + buf +=sprintf(buf,"nGCCopies.......... %d\n",dev->nGCCopies); 2219 + buf +=sprintf(buf,"garbageCollections. %d\n",dev->garbageCollections); 2220 + buf +=sprintf(buf,"passiveGCs......... %d\n",dev->passiveGarbageCollections); 2221 + buf +=sprintf(buf,"nRetriedWrites..... %d\n",dev->nRetriedWrites); 2222 + buf +=sprintf(buf,"nRetireBlocks...... %d\n",dev->nRetiredBlocks); 2223 + buf +=sprintf(buf,"eccFixed........... %d\n",dev->eccFixed); 2224 + buf +=sprintf(buf,"eccUnfixed......... %d\n",dev->eccUnfixed); 2225 + buf +=sprintf(buf,"tagsEccFixed....... %d\n",dev->tagsEccFixed); 2226 + buf +=sprintf(buf,"tagsEccUnfixed..... %d\n",dev->tagsEccUnfixed); 2227 + buf +=sprintf(buf,"cacheHits.......... %d\n",dev->cacheHits); 2228 + buf +=sprintf(buf,"nDeletedFiles...... %d\n",dev->nDeletedFiles); 2229 + buf +=sprintf(buf,"nUnlinkedFiles..... %d\n",dev->nUnlinkedFiles); 2230 + buf +=sprintf(buf,"nBackgroudDeletions %d\n",dev->nBackgroundDeletions); 2231 + buf +=sprintf(buf,"useNANDECC......... %d\n",dev->useNANDECC); 2232 + buf +=sprintf(buf,"isYaffs2........... %d\n",dev->isYaffs2); 2233 + 2234 + return buf; 2235 +} 2236 + 2237 +static int yaffs_proc_read( 2238 + char *page, 2239 + char **start, 2240 + off_t offset, 2241 + int count, 2242 + int *eof, 2243 + void *data 2244 + ) 3153 2245 +{ 3154 2246 + struct list_head *item; … … 3167 2259 + /* Print header first */ 3168 2260 + if (step == 0) { 3169 + buf += sprintf(buf, "YAFFS built:" __DATE__ " " __TIME__ 3170 + "\n%s\n%s\n", yaffs_fs_c_version, 3171 + yaffs_guts_c_version); 2261 + buf += sprintf(buf, "YAFFS built:" __DATE__ " "__TIME__ 2262 + "\n%s\n%s\n", yaffs_fs_c_version, yaffs_guts_c_version); 3172 2263 + } 3173 2264 + … … 3182 2273 + continue; 3183 2274 + } 3184 + buf += sprintf(buf, "\nDevice %d \"%s\"\n", n, dev->name);2275 + buf += sprintf(buf,"\nDevice %d \"%s\"\n", n, dev->name); 3185 2276 + buf = yaffs_dump_dev(buf, dev); 3186 2277 + break; … … 3188 2279 + unlock_kernel(); 3189 2280 + 3190 + return buf - page < count ? buf - page : count; 3191 +} 3192 + 3193 +/** 3194 + * Set the verbosity of the warnings and error messages. 3195 + * 3196 + */ 3197 + 3198 +static struct { 3199 + char *mask_name; 3200 + unsigned mask_bitfield; 3201 +} mask_flags[] = { 3202 + {"allocate", YAFFS_TRACE_ALLOCATE}, 3203 + {"always", YAFFS_TRACE_ALWAYS}, 3204 + {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, 3205 + {"buffers", YAFFS_TRACE_BUFFERS}, 3206 + {"bug", YAFFS_TRACE_BUG}, 3207 + {"deletion", YAFFS_TRACE_DELETION}, 3208 + {"erase", YAFFS_TRACE_ERASE}, 3209 + {"error", YAFFS_TRACE_ERROR}, 3210 + {"gc_detail", YAFFS_TRACE_GC_DETAIL}, 3211 + {"gc", YAFFS_TRACE_GC}, 3212 + {"mtd", YAFFS_TRACE_MTD}, 3213 + {"nandaccess", YAFFS_TRACE_NANDACCESS}, 3214 + {"os", YAFFS_TRACE_OS}, 3215 + {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, 3216 + {"scan", YAFFS_TRACE_SCAN}, 3217 + {"tracing", YAFFS_TRACE_TRACING}, 3218 + {"write", YAFFS_TRACE_WRITE}, 3219 + {"all", 0xffffffff}, 3220 + {"none", 0}, 3221 + {NULL, 0}, 2281 + return buf-page < count ? buf-page : count; 2282 +} 2283 + 2284 +// Stuff to handle installation of file systems 2285 +struct file_system_to_install 2286 +{ 2287 + struct file_system_type *fst; 2288 + int installed; 3222 2289 +}; 3223 2290 + 3224 +static int yaffs_proc_write(struct file *file, const char *buf, 3225 + unsigned long count, void *data) 3226 +{ 3227 + unsigned rg = 0, mask_bitfield; 3228 + char *end, *mask_name; 3229 + int i; 3230 + int done = 0; 3231 + int add, len; 3232 + int pos = 0; 3233 + 3234 + rg = yaffs_traceMask; 3235 + 3236 + while (!done && (pos < count)) { 3237 + done = 1; 3238 + while ((pos < count) && isspace(buf[pos])) { 3239 + pos++; 3240 + } 3241 + 3242 + switch (buf[pos]) { 3243 + case '+': 3244 + case '-': 3245 + case '=': 3246 + add = buf[pos]; 3247 + pos++; 3248 + break; 3249 + 3250 + default: 3251 + add = ' '; 3252 + break; 3253 + } 3254 + mask_name = NULL; 3255 + mask_bitfield = simple_strtoul(buf + pos, &end, 0); 3256 + if (end > buf + pos) { 3257 + mask_name = "numeral"; 3258 + len = end - (buf + pos); 3259 + done = 0; 3260 + } else { 3261 + 3262 + for (i = 0; mask_flags[i].mask_name != NULL; i++) { 3263 + len = strlen(mask_flags[i].mask_name); 3264 + if (strncmp(buf + pos, mask_flags[i].mask_name, len) == 0) { 3265 + mask_name = mask_flags[i].mask_name; 3266 + mask_bitfield = mask_flags[i].mask_bitfield; 3267 + done = 0; 3268 + break; 3269 + } 3270 + } 3271 + } 3272 + 3273 + if (mask_name != NULL) { 3274 + pos += len; 3275 + done = 0; 3276 + switch(add) { 3277 + case '-': 3278 + rg &= ~mask_bitfield; 3279 + break; 3280 + case '+': 3281 + rg |= mask_bitfield; 3282 + break; 3283 + case '=': 3284 + rg = mask_bitfield; 3285 + break; 3286 + default: 3287 + rg |= mask_bitfield; 3288 + break; 3289 + } 3290 + } 3291 + } 3292 + 3293 + yaffs_traceMask = rg; 3294 + if (rg & YAFFS_TRACE_ALWAYS) { 3295 + for (i = 0; mask_flags[i].mask_name != NULL; i++) { 3296 + char flag; 3297 + flag = ((rg & mask_flags[i].mask_bitfield) == mask_flags[i].mask_bitfield) ? '+' : '-'; 3298 + printk("%c%s\n", flag, mask_flags[i].mask_name); 3299 + } 3300 + } 3301 + 3302 + return count; 3303 +} 3304 + 3305 +/* Stuff to handle installation of file systems */ 3306 +struct file_system_to_install { 3307 + struct file_system_type *fst; 3308 + int installed; 2291 +static struct file_system_to_install fs_to_install[] = 2292 +{ 2293 +#ifdef CONFIG_YAFFS_YAFFS1 2294 + { &yaffs_fs_type,0}, 2295 +#endif 2296 +#ifdef CONFIG_YAFFS_YAFFS2 2297 + { &yaffs2_fs_type,0}, 2298 +#endif 2299 + { NULL,0} 3309 2300 +}; 3310 2301 + 3311 +static struct file_system_to_install fs_to_install[] = {3312 +//#ifdef CONFIG_YAFFS_YAFFS13313 + {&yaffs_fs_type, 0},3314 +//#endif3315 +//#ifdef CONFIG_YAFFS_YAFFS23316 + {&yaffs2_fs_type, 0},3317 +//#endif3318 + {NULL, 0}3319 +};3320 +3321 2302 +static int __init init_yaffs_fs(void) 3322 2303 +{ 3323 2304 + int error = 0; 3324 + struct file_system_to_install *fsinst; 3325 + 3326 + T(YAFFS_TRACE_ALWAYS, 3327 + ("yaffs " __DATE__ " " __TIME__ " Installing. \n")); 3328 + 3329 + /* Install the proc_fs entry */ 3330 + my_proc_entry = create_proc_entry("yaffs", 3331 + S_IRUGO | S_IFREG, 3332 + &proc_root); 3333 + 3334 + if (my_proc_entry) { 3335 + my_proc_entry->write_proc = yaffs_proc_write; 3336 + my_proc_entry->read_proc = yaffs_proc_read; 3337 + my_proc_entry->data = NULL; 3338 + } else { 3339 + return -ENOMEM; 3340 + } 3341 + 3342 + /* Now add the file system entries */ 3343 + 3344 + fsinst = fs_to_install; 3345 + 3346 + while (fsinst->fst && !error) { 3347 + error = register_filesystem(fsinst->fst); 3348 + if (!error) { 3349 + fsinst->installed = 1; 3350 + } 3351 + fsinst++; 3352 + } 3353 + 3354 + /* Any errors? uninstall */ 3355 + if (error) { 3356 + fsinst = fs_to_install; 3357 + 3358 + while (fsinst->fst) { 3359 + if (fsinst->installed) { 3360 + unregister_filesystem(fsinst->fst); 3361 + fsinst->installed = 0; 3362 + } 3363 + fsinst++; 3364 + } 3365 + } 3366 + 3367 + return error; 2305 + struct file_system_to_install *fsinst; 2306 + 2307 + T(YAFFS_TRACE_ALWAYS,("yaffs " __DATE__ " " __TIME__ " Installing. \n")); 2308 + 2309 + 2310 + 2311 + /* Install the proc_fs entry */ 2312 + my_proc_entry = create_proc_read_entry("yaffs", 2313 + S_IRUGO | S_IFREG, 2314 + &proc_root, 2315 + yaffs_proc_read, 2316 + NULL); 2317 + if(!my_proc_entry) 2318 + { 2319 + return -ENOMEM; 2320 + } 2321 + 2322 + 2323 + 2324 + // Now add the file system entries 2325 + 2326 + fsinst = fs_to_install; 2327 + 2328 + while(fsinst->fst && !error) 2329 + { 2330 + error = register_filesystem(fsinst->fst); 2331 + if(!error) 2332 + { 2333 + fsinst->installed = 1; 2334 + } 2335 + fsinst++; 2336 + } 2337 + 2338 + // Any errors? uninstall 2339 + if(error) 2340 + { 2341 + fsinst = fs_to_install; 2342 + 2343 + while(fsinst->fst) 2344 + { 2345 + if(fsinst->installed) 2346 + { 2347 + unregister_filesystem(fsinst->fst); 2348 + fsinst->installed = 0; 2349 + } 2350 + fsinst++; 2351 + } 2352 + } 2353 + 2354 + return error; 3368 2355 +} 3369 2356 + … … 3371 2358 +{ 3372 2359 + 3373 + struct file_system_to_install *fsinst; 3374 + 3375 + T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__ 3376 + " removing. \n")); 3377 + 3378 + remove_proc_entry("yaffs", &proc_root); 3379 + 3380 + fsinst = fs_to_install; 3381 + 3382 + while (fsinst->fst) { 3383 + if (fsinst->installed) { 3384 + unregister_filesystem(fsinst->fst); 3385 + fsinst->installed = 0; 3386 + } 3387 + fsinst++; 3388 + } 2360 + struct file_system_to_install *fsinst; 2361 + 2362 + T(YAFFS_TRACE_ALWAYS,("yaffs " __DATE__ " " __TIME__ " removing. \n")); 2363 + 2364 + remove_proc_entry("yaffs",&proc_root); 2365 + 2366 + fsinst = fs_to_install; 2367 + 2368 + while(fsinst->fst) 2369 + { 2370 + if(fsinst->installed) 2371 + { 2372 + unregister_filesystem(fsinst->fst); 2373 + fsinst->installed = 0; 2374 + } 2375 + fsinst++; 2376 + } 3389 2377 + 3390 2378 +} … … 3394 2382 + 3395 2383 +MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system"); 3396 +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002 -2006");2384 +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002,2003,2004"); 3397 2385 +MODULE_LICENSE("GPL"); 3398 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_guts.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.c 3399 --- linux-2.6.18.2/fs/yaffs2/yaffs_guts.c 1970-01-01 01:00:00.000000000 +0100 3400 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.c 2006-11-25 00:15:31.000000000 +0100 3401 @@ -0,0 +1,6675 @@ 2386 + 2387 + 2388 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c 2389 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c 1970-01-01 01:00:00.000000000 +0100 2390 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c 2006-12-10 03:57:50.000000000 +0100 2391 @@ -0,0 +1,6346 @@ 3402 2392 +/* 3403 + * YAFFS: Yet another FFS. A NAND-flash specific file system. 2393 + * YAFFS: Yet another FFS. A NAND-flash specific file system. 3404 2394 + * 3405 2395 + * Copyright (C) 2002 Aleph One Ltd. … … 3413 2403 + * 3414 2404 + */ 3415 + 3416 + const char *yaffs_guts_c_version =3417 + "$Id: yaffs_guts.c,v 1.45 2006/11/14 03:07:17charles Exp $";2405 + //yaffs_guts.c 2406 + 2407 +const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.15 2005/08/02 04:24:22 charles Exp $"; 3418 2408 + 3419 2409 +#include "yportenv.h" … … 3423 2413 +#include "yaffs_tagsvalidity.h" 3424 2414 + 2415 + 3425 2416 +#include "yaffs_tagscompat.h" 3426 +#ifndef CONFIG_YAFFS_OWN_SORT3427 +#include "yaffs_qsort.h"3428 +#endif3429 +#include "yaffs_nand.h"3430 +3431 +#include "yaffs_checkptrw.h"3432 +3433 +#include "yaffs_nand.h"3434 +#include "yaffs_packedtags2.h"3435 +3436 2417 + 3437 2418 +#ifdef CONFIG_YAFFS_WINCE … … 3442 2423 +#define YAFFS_PASSIVE_GC_CHUNKS 2 3443 2424 + 2425 +#if 0 2426 +// Use Steven Hill's ECC struff instead 2427 +// External functions for ECC on data 2428 +void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); 2429 +int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); 2430 +#define yaffs_ECCCalculate(data,ecc) nand_calculate_ecc(data,ecc) 2431 +#define yaffs_ECCCorrect(data,read_ecc,calc_ecc) nand_correct_ecc(data,read_ecc,calc_ecc) 2432 +#else 3444 2433 +#include "yaffs_ecc.h" 3445 + 3446 + 3447 +/* Robustification (if it ever comes about...) */ 3448 +static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND); 3449 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk); 3450 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, 3451 + const __u8 * data, 3452 + const yaffs_ExtendedTags * tags); 3453 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, 3454 + const yaffs_ExtendedTags * tags); 3455 + 3456 +/* Other local prototypes */ 3457 +static int yaffs_UnlinkObject( yaffs_Object *obj); 3458 +static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj); 3459 + 3460 +static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList); 3461 + 3462 +static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev, 3463 + const __u8 * buffer, 3464 + yaffs_ExtendedTags * tags, 3465 + int useReserve); 3466 +static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, 3467 + int chunkInNAND, int inScan); 3468 + 3469 +static yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, 3470 + yaffs_ObjectType type); 3471 +static void yaffs_AddObjectToDirectory(yaffs_Object * directory, 3472 + yaffs_Object * obj); 3473 +static int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, 3474 + int force, int isShrink, int shadows); 3475 +static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj); 2434 +#endif 2435 + 2436 +#if 0 2437 +// countBits is a quick way of counting the number of bits in a byte. 2438 +// ie. countBits[n] holds the number of 1 bits in a byte with the value n. 2439 + 2440 +static const char yaffs_countBitsTable[256] = 2441 +{ 2442 +0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, 2443 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2444 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2445 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2446 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2447 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2448 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2449 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2450 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2451 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2452 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2453 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2454 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2455 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2456 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2457 +4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 2458 +}; 2459 + 2460 +static int yaffs_CountBits(__u8 x) 2461 +{ 2462 + int retVal; 2463 + retVal = yaffs_countBitsTable[x]; 2464 + return retVal; 2465 +} 2466 + 2467 +#endif 2468 + 2469 + 2470 +#if 0 2471 +// Stuff using yea olde tags 2472 +static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr); 2473 +static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr); 2474 + 2475 +static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_Tags *tags, int *chunkDeleted); 2476 +static int yaffs_TagsMatch(const yaffs_Tags *tags, int objectId, int chunkInObject, int chunkDeleted); 2477 +#else 2478 +#endif 2479 + 2480 +// NAND access 2481 + 2482 + 2483 +static Y_INLINE int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *buffer, yaffs_ExtendedTags *tags); 2484 +static Y_INLINE int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *data, yaffs_ExtendedTags *tags); 2485 +static Y_INLINE int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo); 2486 +static Y_INLINE int yaffs_QueryInitialBlockState(yaffs_Device *dev,int blockNo, yaffs_BlockState *state,unsigned *sequenceNumber); 2487 +// Local prototypes 2488 +static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_ExtendedTags *tags, int useReserve); 2489 +#if 0 2490 +static int yaffs_CheckObjectHashSanity(yaffs_Device *dev); 2491 +#endif 2492 +static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkInNAND, int inScan); 2493 + 2494 +static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type); 2495 +static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj); 2496 +static int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink, int shadows); 2497 +static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj); 3476 2498 +static int yaffs_CheckStructures(void); 3477 +static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, 3478 + int chunkOffset, int *limit); 3479 +static int yaffs_DoGenericObjectDeletion(yaffs_Object * in); 3480 + 3481 +static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo); 3482 + 3483 +static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo); 3484 +static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, 3485 + int lineNo); 3486 + 3487 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, 3488 + int chunkInNAND); 3489 + 3490 +static int yaffs_UnlinkWorker(yaffs_Object * obj); 3491 +static void yaffs_DestroyObject(yaffs_Object * obj); 3492 + 3493 +static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId, 3494 + int chunkInObject); 3495 + 3496 +loff_t yaffs_GetFileSize(yaffs_Object * obj); 3497 + 3498 +static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr); 3499 + 3500 +static void yaffs_VerifyFreeChunks(yaffs_Device * dev); 2499 +static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit); 2500 +static int yaffs_DoGenericObjectDeletion(yaffs_Object *in); 2501 + 2502 +static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device *dev,int blockNo); 2503 + 2504 +static __u8 *yaffs_GetTempBuffer(yaffs_Device *dev,int lineNo); 2505 +static void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo); 2506 + 2507 + 2508 +// Robustification (if it ever comes about...) 2509 +static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND); 2510 +#if 0 2511 +static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND); 2512 +#endif 2513 +static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND); 2514 +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags); 2515 +static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_ExtendedTags *tags); 2516 + 2517 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND); 2518 + 2519 +static int yaffs_UnlinkWorker(yaffs_Object *obj); 2520 +static void yaffs_DestroyObject(yaffs_Object *obj); 2521 + 2522 +#if 0 2523 +static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1,int dataSize); 2524 +#endif 2525 + 2526 +static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, int chunkInObject); 2527 + 2528 + 2529 +loff_t yaffs_GetFileSize(yaffs_Object *obj); 2530 + 2531 + 2532 +static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve); 2533 + 2534 +static void yaffs_VerifyFreeChunks(yaffs_Device *dev); 3501 2535 + 3502 2536 +#ifdef YAFFS_PARANOID 3503 +static int yaffs_CheckFileSanity(yaffs_Object * in);2537 +static int yaffs_CheckFileSanity(yaffs_Object *in); 3504 2538 +#else 3505 2539 +#define yaffs_CheckFileSanity(in) 3506 2540 +#endif 3507 2541 + 3508 +static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in); 3509 +static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId); 3510 + 3511 +static void yaffs_InvalidateCheckpoint(yaffs_Device *dev); 3512 + 3513 + 3514 + 3515 +/* Function to calculate chunk and offset */ 3516 + 3517 +static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset) 3518 +{ 3519 + if(dev->chunkShift){ 3520 + /* Easy-peasy power of 2 case */ 3521 + *chunk = (__u32)(addr >> dev->chunkShift); 3522 + *offset = (__u32)(addr & dev->chunkMask); 3523 + } 3524 + else if(dev->crumbsPerChunk) 3525 + { 3526 + /* Case where we're using "crumbs" */ 3527 + *offset = (__u32)(addr & dev->crumbMask); 3528 + addr >>= dev->crumbShift; 3529 + *chunk = ((__u32)addr)/dev->crumbsPerChunk; 3530 + *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift); 3531 + } 2542 +static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in); 2543 +static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId); 2544 + 2545 +static int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *buffer, yaffs_ExtendedTags *tags) 2546 +{ 2547 + chunkInNAND -= dev->chunkOffset; 2548 + 2549 + if(dev->readChunkWithTagsFromNAND) 2550 + return dev->readChunkWithTagsFromNAND(dev,chunkInNAND,buffer,tags); 3532 2551 + else 3533 + YBUG(); 3534 +} 3535 + 3536 +/* Function to return the number of shifts for a power of 2 greater than or equal 3537 + * to the given number 3538 + * Note we don't try to cater for all possible numbers and this does not have to 3539 + * be hellishly efficient. 3540 + */ 3541 + 3542 +static __u32 ShiftsGE(__u32 x) 3543 +{ 3544 + int extraBits; 3545 + int nShifts; 3546 + 3547 + nShifts = extraBits = 0; 3548 + 3549 + while(x>1){ 3550 + if(x & 1) extraBits++; 3551 + x>>=1; 3552 + nShifts++; 3553 + } 3554 + 3555 + if(extraBits) 3556 + nShifts++; 3557 + 3558 + return nShifts; 3559 +} 3560 + 3561 +/* Function to return the number of shifts to get a 1 in bit 0 3562 + */ 3563 + 3564 +static __u32 ShiftDiv(__u32 x) 3565 +{ 3566 + int nShifts; 3567 + 3568 + nShifts = 0; 3569 + 3570 + if(!x) return 0; 3571 + 3572 + while( !(x&1)){ 3573 + x>>=1; 3574 + nShifts++; 3575 + } 3576 + 3577 + return nShifts; 3578 +} 3579 + 3580 + 3581 + 3582 +/* 3583 + * Temporary buffer manipulations. 3584 + */ 3585 + 3586 +static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) 3587 +{ 3588 + int i, j; 3589 + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { 3590 + if (dev->tempBuffer[i].line == 0) { 2552 + return yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,chunkInNAND,buffer,tags); 2553 +} 2554 + 2555 +static Y_INLINE int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *buffer, yaffs_ExtendedTags *tags) 2556 +{ 2557 + chunkInNAND -= dev->chunkOffset; 2558 + 2559 + if(tags) 2560 + { 2561 + tags->sequenceNumber = dev->sequenceNumber; 2562 + tags->chunkUsed = 1; 2563 + if(!yaffs_ValidateTags(tags)) 2564 + { 2565 + T(YAFFS_TRACE_ERROR,(TSTR("Writing uninitialised tags" TENDSTR))); 2566 + YBUG(); 2567 + } 2568 + T(YAFFS_TRACE_WRITE,(TSTR("Writing chunk %d tags %d %d"TENDSTR),chunkInNAND,tags->objectId,tags->chunkId)); 2569 + } 2570 + else 2571 + { 2572 + T(YAFFS_TRACE_ERROR,(TSTR("Writing with no tags" TENDSTR))); 2573 + YBUG(); 2574 + } 2575 + 2576 + if(dev->writeChunkWithTagsToNAND) 2577 + return dev->writeChunkWithTagsToNAND(dev,chunkInNAND,buffer,tags); 2578 + else 2579 + return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,chunkInNAND,buffer,tags); 2580 +} 2581 + 2582 +static Y_INLINE int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo) 2583 +{ 2584 + blockNo -= dev->blockOffset; 2585 + 2586 + if(dev->markNANDBlockBad) 2587 + return dev->markNANDBlockBad(dev,blockNo); 2588 + else 2589 + return yaffs_TagsCompatabilityMarkNANDBlockBad(dev,blockNo); 2590 +} 2591 +static Y_INLINE int yaffs_QueryInitialBlockState(yaffs_Device *dev,int blockNo, yaffs_BlockState *state, unsigned *sequenceNumber) 2592 +{ 2593 + blockNo -= dev->blockOffset; 2594 + 2595 + if(dev->queryNANDBlock) 2596 + return dev->queryNANDBlock(dev,blockNo,state,sequenceNumber); 2597 + else 2598 + return yaffs_TagsCompatabilityQueryNANDBlock(dev,blockNo,state,sequenceNumber); 2599 +} 2600 + 2601 +static int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND) 2602 +{ 2603 + int result; 2604 + 2605 + blockInNAND -= dev->blockOffset; 2606 + 2607 + dev->nBlockErasures++; 2608 + result = dev->eraseBlockInNAND(dev,blockInNAND); 2609 + 2610 + if(!result)result = dev->eraseBlockInNAND(dev,blockInNAND); // If at first we don't succeed, try again *once*. 2611 + return result; 2612 +} 2613 + 2614 +static int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev) 2615 +{ 2616 + return dev->initialiseNAND(dev); 2617 +} 2618 + 2619 + 2620 + 2621 + 2622 +// Temporary buffer manipulations 2623 + 2624 +static __u8 *yaffs_GetTempBuffer(yaffs_Device *dev,int lineNo) 2625 +{ 2626 + int i,j; 2627 + for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) 2628 + { 2629 + if(dev->tempBuffer[i].line == 0) 2630 + { 3591 2631 + dev->tempBuffer[i].line = lineNo; 3592 + if ((i + 1) > dev->maxTemp) { 2632 + if((i+1) > dev->maxTemp) 2633 + { 3593 2634 + dev->maxTemp = i + 1; 3594 + for (j = 0; j <= i; j++) 3595 + dev->tempBuffer[j].maxLine = 3596 + dev->tempBuffer[j].line; 3597 + } 3598 + 2635 + for(j = 0; j <= i; j++) 2636 + dev->tempBuffer[j].maxLine = dev->tempBuffer[j].line; 2637 + } 2638 + 3599 2639 + return dev->tempBuffer[i].buffer; 3600 2640 + } 3601 2641 + } 3602 2642 + 3603 + T(YAFFS_TRACE_BUFFERS, 3604 + (TSTR("Out of temp buffers at line %d, other held by lines:"), 3605 + lineNo)); 3606 + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { 3607 + T(YAFFS_TRACE_BUFFERS, (TSTR(" %d "), dev->tempBuffer[i].line)); 3608 + } 3609 + T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR))); 3610 + 3611 + /* 3612 + * If we got here then we have to allocate an unmanaged one 3613 + * This is not good. 3614 + */ 3615 + 2643 + T(YAFFS_TRACE_BUFFERS,(TSTR("Out of temp buffers at line %d, other held by lines:"),lineNo)); 2644 + for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) 2645 + { 2646 + T(YAFFS_TRACE_BUFFERS,(TSTR(" %d "),dev->tempBuffer[i].line)); 2647 + } 2648 + T(YAFFS_TRACE_BUFFERS,(TSTR(" "TENDSTR))); 2649 + 3616 2650 + dev->unmanagedTempAllocations++; 3617 + return YMALLOC(dev->nDataBytesPerChunk); 3618 + 3619 +} 3620 + 3621 +static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, 3622 + int lineNo) 2651 + // Get an unmanaged one 2652 + return YMALLOC(dev->nBytesPerChunk); 2653 + 2654 + 2655 +} 2656 + 2657 +static void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo) 3623 2658 +{ 3624 2659 + int i; 3625 + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { 3626 + if (dev->tempBuffer[i].buffer == buffer) { 2660 + for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) 2661 + { 2662 + if(dev->tempBuffer[i].buffer == buffer) 2663 + { 3627 2664 + dev->tempBuffer[i].line = 0; 3628 2665 + return; 3629 2666 + } 3630 2667 + } 3631 + 3632 + if (buffer) { 3633 + /* assume it is an unmanaged one. */ 3634 + T(YAFFS_TRACE_BUFFERS, 3635 + (TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR), 3636 + lineNo)); 2668 + 2669 + if(buffer) 2670 + { 2671 + // assume it is an unmanaged one. 2672 + T(YAFFS_TRACE_BUFFERS,(TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR),lineNo)); 3637 2673 + YFREE(buffer); 3638 2674 + dev->unmanagedTempDeallocations++; … … 3641 2677 +} 3642 2678 + 3643 +/* 3644 + * Determine if we have a managed buffer. 3645 + */ 3646 +int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer) 3647 +{ 2679 + 2680 +// Chunk bitmap manipulations 2681 + 2682 +static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk) 2683 +{ 2684 + if(blk < dev->internalStartBlock || blk > dev->internalEndBlock) 2685 + { 2686 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),blk)); 2687 + YBUG(); 2688 + } 2689 + return dev->chunkBits + (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); 2690 +} 2691 + 2692 +static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device *dev,int blk) 2693 +{ 2694 + __u8 *blkBits = yaffs_BlockBits(dev,blk); 2695 + 2696 + memset(blkBits,0,dev->chunkBitmapStride); 2697 +} 2698 + 2699 +static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device *dev,int blk,int chunk) 2700 +{ 2701 + __u8 *blkBits = yaffs_BlockBits(dev,blk); 2702 + 2703 + blkBits[chunk/8] &= ~ (1<<(chunk & 7)); 2704 +} 2705 + 2706 +static Y_INLINE void yaffs_SetChunkBit(yaffs_Device *dev,int blk,int chunk) 2707 +{ 2708 + __u8 *blkBits = yaffs_BlockBits(dev,blk); 2709 + 2710 + blkBits[chunk/8] |= (1<<(chunk & 7)); 2711 +} 2712 + 2713 +static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device *dev,int blk,int chunk) 2714 +{ 2715 + __u8 *blkBits = yaffs_BlockBits(dev,blk); 2716 + return (blkBits[chunk/8] & (1<<(chunk & 7))) ? 1 :0; 2717 +} 2718 + 2719 +static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device *dev,int blk) 2720 +{ 2721 + __u8 *blkBits = yaffs_BlockBits(dev,blk); 3648 2722 + int i; 3649 + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { 3650 + if (dev->tempBuffer[i].buffer == buffer) 3651 + return 1; 3652 + 3653 + } 3654 + 3655 + for (i = 0; i < dev->nShortOpCaches; i++) { 3656 + if( dev->srCache[i].data == buffer ) 3657 + return 1; 3658 + 3659 + } 3660 + 3661 + if (buffer == dev->checkpointBuffer) 3662 + return 1; 3663 + 3664 + T(YAFFS_TRACE_ALWAYS, 3665 + (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR))); 3666 + return 0; 3667 +} 3668 + 3669 +/* 3670 + * Chunk bitmap manipulations 3671 + */ 3672 + 3673 +static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device * dev, int blk) 3674 +{ 3675 + if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { 3676 + T(YAFFS_TRACE_ERROR, 3677 + (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR), 3678 + blk)); 3679 + YBUG(); 3680 + } 3681 + return dev->chunkBits + 3682 + (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); 3683 +} 3684 + 3685 +static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk) 3686 +{ 3687 + __u8 *blkBits = yaffs_BlockBits(dev, blk); 3688 + 3689 + memset(blkBits, 0, dev->chunkBitmapStride); 3690 +} 3691 + 3692 +static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device * dev, int blk, int chunk) 3693 +{ 3694 + __u8 *blkBits = yaffs_BlockBits(dev, blk); 3695 + 3696 + blkBits[chunk / 8] &= ~(1 << (chunk & 7)); 3697 +} 3698 + 3699 +static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk) 3700 +{ 3701 + __u8 *blkBits = yaffs_BlockBits(dev, blk); 3702 + 3703 + blkBits[chunk / 8] |= (1 << (chunk & 7)); 3704 +} 3705 + 3706 +static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk) 3707 +{ 3708 + __u8 *blkBits = yaffs_BlockBits(dev, blk); 3709 + return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0; 3710 +} 3711 + 3712 +static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk) 3713 +{ 3714 + __u8 *blkBits = yaffs_BlockBits(dev, blk); 3715 + int i; 3716 + for (i = 0; i < dev->chunkBitmapStride; i++) { 3717 + if (*blkBits) 3718 + return 1; 2723 + for(i = 0; i < dev->chunkBitmapStride; i++) 2724 + { 2725 + if(*blkBits) return 1; 3719 2726 + blkBits++; 3720 2727 + } … … 3722 2729 +} 3723 2730 + 3724 +/* 3725 + * Simple hash function. Needs to have a reasonable spread 3726 + */ 3727 + 3728 +static Y_INLINE int yaffs_HashFunction(int n) 3729 +{ 3730 + n = abs(n); 2731 + 2732 +static Y_INLINE int yaffs_HashFunction(int n) 2733 +{ 3731 2734 + return (n % YAFFS_NOBJECT_BUCKETS); 3732 2735 +} 3733 2736 + 3734 +/* 3735 + * Access functions to useful fake objects 3736 + */ 3737 + 3738 +yaffs_Object *yaffs_Root(yaffs_Device * dev) 2737 + 2738 +yaffs_Object *yaffs_Root(yaffs_Device *dev) 3739 2739 +{ 3740 2740 + return dev->rootDir; 3741 2741 +} 3742 2742 + 3743 +yaffs_Object *yaffs_LostNFound(yaffs_Device * dev)2743 +yaffs_Object *yaffs_LostNFound(yaffs_Device *dev) 3744 2744 +{ 3745 2745 + return dev->lostNFoundDir; … … 3747 2747 + 3748 2748 + 3749 +/* 3750 + * Erased NAND checking functions 3751 + */ 3752 + 3753 +int yaffs_CheckFF(__u8 * buffer, int nBytes) 3754 +{ 3755 + /* Horrible, slow implementation */ 3756 + while (nBytes--) { 3757 + if (*buffer != 0xFF) 2749 + 2750 + 2751 +int yaffs_CheckFF(__u8 *buffer,int nBytes) 2752 +{ 2753 + //Horrible, slow implementation 2754 + while(nBytes--) 2755 + { 2756 + if(*buffer != 0xFF) return 0; 2757 + buffer++; 2758 + } 2759 + return 1; 2760 +} 2761 + 2762 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND) 2763 +{ 2764 + 2765 + int retval = YAFFS_OK; 2766 + __u8 *data = yaffs_GetTempBuffer(dev,__LINE__); 2767 + yaffs_ExtendedTags tags; 2768 + 2769 +// NCB dev->readChunkWithTagsFromNAND(dev,chunkInNAND,data,&tags); 2770 + yaffs_ReadChunkWithTagsFromNAND(dev,chunkInNAND,data,&tags); 2771 + 2772 + if(!yaffs_CheckFF(data,dev->nBytesPerChunk) || tags.chunkUsed) 2773 + { 2774 + T(YAFFS_TRACE_NANDACCESS,(TSTR("Chunk %d not erased" TENDSTR),chunkInNAND)); 2775 + retval = YAFFS_FAIL; 2776 + } 2777 + 2778 + yaffs_ReleaseTempBuffer(dev,data,__LINE__); 2779 + 2780 + return retval; 2781 + 2782 +} 2783 + 2784 + 2785 + 2786 +#if 1 2787 +static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, const __u8 *data, yaffs_ExtendedTags *tags,int useReserve) 2788 +{ 2789 + int chunk; 2790 + 2791 + int writeOk = 1; 2792 + int attempts = 0; 2793 + 2794 + 2795 + 2796 + do{ 2797 + chunk = yaffs_AllocateChunk(dev,useReserve); 2798 + 2799 + if(chunk >= 0) 2800 + { 2801 + 2802 + // First check this chunk is erased... 2803 +#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK 2804 + writeOk = yaffs_CheckChunkErased(dev,chunk); 2805 +#endif 2806 + if(!writeOk) 2807 + { 2808 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d was not erased" TENDSTR),chunk)); 2809 + } 2810 + else 2811 + { 2812 + writeOk = yaffs_WriteChunkWithTagsToNAND(dev,chunk,data,tags); 2813 + } 2814 + attempts++; 2815 + 2816 + if(writeOk) 2817 + { 2818 + // Copy the data into the robustification buffer. 2819 + // NB We do this at the end to prevent duplicates in the case of a write error. 2820 + //Todo 2821 + yaffs_HandleWriteChunkOk(dev,chunk,data,tags); 2822 + } 2823 + else 2824 + { 2825 + yaffs_HandleWriteChunkError(dev,chunk); 2826 + } 2827 + } 2828 + 2829 + } while(chunk >= 0 && ! writeOk); 2830 + 2831 + if(attempts > 1) 2832 + { 2833 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write required %d attempts" TENDSTR),attempts)); 2834 + dev->nRetriedWrites+= (attempts - 1); 2835 + } 2836 + 2837 + 2838 + 2839 + return chunk; 2840 +} 2841 +#endif 2842 + 2843 + 2844 +/// 2845 +// Functions for robustisizing 2846 +// 2847 +// 2848 + 2849 +static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND) 2850 +{ 2851 + 2852 + yaffs_MarkBlockBad(dev,blockInNAND); 2853 + 2854 + yaffs_GetBlockInfo(dev,blockInNAND)->blockState = YAFFS_BLOCK_STATE_DEAD; 2855 + 2856 + dev->nRetiredBlocks++; 2857 +} 2858 + 2859 + 2860 +#if 0 2861 +static int yaffs_RewriteBufferedBlock(yaffs_Device *dev) 2862 +{ 2863 + dev->doingBufferedBlockRewrite = 1; 2864 + // 2865 + // Remove erased chunks 2866 + // Rewrite existing chunks to a new block 2867 + // Set current write block to the new block 2868 + 2869 + dev->doingBufferedBlockRewrite = 0; 2870 + 2871 + return 1; 2872 +} 2873 + 2874 + 2875 +static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND) 2876 +{ 2877 + int blockInNAND = chunkInNAND/dev->nChunksPerBlock; 2878 + 2879 + // Mark the block for retirement 2880 + yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1; 2881 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>>Block %d marked for retirement" TENDSTR),blockInNAND)); 2882 + 2883 + 2884 + //TODO 2885 + // Just do a garbage collection on the affected block then retire the block 2886 + // NB recursion 2887 +} 2888 + 2889 + 2890 +static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND) 2891 +{ 2892 +} 2893 + 2894 +#endif 2895 + 2896 +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags) 2897 +{ 2898 +} 2899 + 2900 +static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_ExtendedTags *tags) 2901 +{ 2902 +} 2903 + 2904 +static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND) 2905 +{ 2906 + int blockInNAND = chunkInNAND/dev->nChunksPerBlock; 2907 + 2908 + // Mark the block for retirement 2909 + yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1; 2910 + // Delete the chunk 2911 + yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__); 2912 +} 2913 + 2914 + 2915 + 2916 +#if 0 2917 +static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1,int dataSize) 2918 +{ 2919 + 2920 + 2921 + if( memcmp(d0,d1,dataSize) != 0 || 2922 + s0->tagByte0 != s1->tagByte0 || 2923 + s0->tagByte1 != s1->tagByte1 || 2924 + s0->tagByte2 != s1->tagByte2 || 2925 + s0->tagByte3 != s1->tagByte3 || 2926 + s0->tagByte4 != s1->tagByte4 || 2927 + s0->tagByte5 != s1->tagByte5 || 2928 + s0->tagByte6 != s1->tagByte6 || 2929 + s0->tagByte7 != s1->tagByte7 || 2930 + s0->ecc1[0] != s1->ecc1[0] || 2931 + s0->ecc1[1] != s1->ecc1[1] || 2932 + s0->ecc1[2] != s1->ecc1[2] || 2933 + s0->ecc2[0] != s1->ecc2[0] || 2934 + s0->ecc2[1] != s1->ecc2[1] || 2935 + s0->ecc2[2] != s1->ecc2[2] ) 2936 + { 3758 2937 + return 0; 3759 + buffer++;3760 + }2938 + } 2939 + 3761 2940 + return 1; 3762 2941 +} 3763 + 3764 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, 3765 + int chunkInNAND) 3766 +{ 3767 + 3768 + int retval = YAFFS_OK; 3769 + __u8 *data = yaffs_GetTempBuffer(dev, __LINE__); 3770 + yaffs_ExtendedTags tags; 3771 + int result; 3772 + 3773 + result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags); 3774 + 3775 + if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR) 3776 + retval = YAFFS_FAIL; 3777 + 3778 + 3779 + if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) { 3780 + T(YAFFS_TRACE_NANDACCESS, 3781 + (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND)); 3782 + retval = YAFFS_FAIL; 3783 + } 3784 + 3785 + yaffs_ReleaseTempBuffer(dev, data, __LINE__); 3786 + 3787 + return retval; 3788 + 3789 +} 3790 + 3791 +static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, 3792 + const __u8 * data, 3793 + yaffs_ExtendedTags * tags, 3794 + int useReserve) 3795 +{ 3796 + int chunk; 3797 + 3798 + int writeOk = 0; 3799 + int erasedOk = 1; 3800 + int attempts = 0; 3801 + yaffs_BlockInfo *bi; 3802 + 3803 + yaffs_InvalidateCheckpoint(dev); 3804 + 3805 + do { 3806 + chunk = yaffs_AllocateChunk(dev, useReserve,&bi); 3807 + 3808 + if (chunk >= 0) { 3809 + /* First check this chunk is erased, if it needs checking. 3810 + * The checking policy (unless forced always on) is as follows: 3811 + * Check the first page we try to write in a block. 3812 + * - If the check passes then we don't need to check any more. 3813 + * - If the check fails, we check again... 3814 + * If the block has been erased, we don't need to check. 3815 + * 3816 + * However, if the block has been prioritised for gc, then 3817 + * we think there might be something odd about this block 3818 + * and stop using it. 3819 + * 3820 + * Rationale: 3821 + * We should only ever see chunks that have not been erased 3822 + * if there was a partially written chunk due to power loss 3823 + * This checking policy should catch that case with very 3824 + * few checks and thus save a lot of checks that are most likely not 3825 + * needed. 3826 + */ 3827 + 3828 + if(bi->gcPrioritise){ 3829 + yaffs_DeleteChunk(dev, chunk, 1, __LINE__); 3830 + } else { 3831 +#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED 3832 + 3833 + bi->skipErasedCheck = 0; 3834 + 3835 +#endif 3836 + if(!bi->skipErasedCheck){ 3837 + erasedOk = yaffs_CheckChunkErased(dev, chunk); 3838 + if(erasedOk && !bi->gcPrioritise) 3839 + bi->skipErasedCheck = 1; 3840 + } 3841 + 3842 + if (!erasedOk) { 3843 + T(YAFFS_TRACE_ERROR, 3844 + (TSTR 3845 + ("**>> yaffs chunk %d was not erased" 3846 + TENDSTR), chunk)); 3847 + } else { 3848 + writeOk = 3849 + yaffs_WriteChunkWithTagsToNAND(dev, chunk, 3850 + data, tags); 3851 + } 3852 + 3853 + attempts++; 3854 + 3855 + if (writeOk) { 3856 + /* 3857 + * Copy the data into the robustification buffer. 3858 + * NB We do this at the end to prevent duplicates in the case of a write error. 3859 + * Todo 3860 + */ 3861 + yaffs_HandleWriteChunkOk(dev, chunk, data, tags); 3862 + 3863 + } else { 3864 + /* The erased check or write failed */ 3865 + yaffs_HandleWriteChunkError(dev, chunk, erasedOk); 3866 + } 3867 + } 3868 + } 3869 + 3870 + } while (chunk >= 0 && !writeOk); 3871 + 3872 + if (attempts > 1) { 3873 + T(YAFFS_TRACE_ERROR, 3874 + (TSTR("**>> yaffs write required %d attempts" TENDSTR), 3875 + attempts)); 3876 + dev->nRetriedWrites += (attempts - 1); 3877 + } 3878 + 3879 + return chunk; 3880 +} 3881 + 3882 +/* 3883 + * Block retiring for handling a broken block. 3884 + */ 3885 + 3886 +static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND) 3887 +{ 3888 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); 3889 + 3890 + yaffs_InvalidateCheckpoint(dev); 3891 + 3892 + yaffs_MarkBlockBad(dev, blockInNAND); 3893 + 3894 + bi->blockState = YAFFS_BLOCK_STATE_DEAD; 3895 + bi->gcPrioritise = 0; 3896 + bi->needsRetiring = 0; 3897 + 3898 + dev->nRetiredBlocks++; 3899 +} 3900 + 3901 +/* 3902 + * Functions for robustisizing TODO 3903 + * 3904 + */ 3905 + 3906 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, 3907 + const __u8 * data, 3908 + const yaffs_ExtendedTags * tags) 3909 +{ 3910 +} 3911 + 3912 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, 3913 + const yaffs_ExtendedTags * tags) 3914 +{ 3915 +} 3916 + 3917 +void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi) 3918 +{ 3919 + if(!bi->gcPrioritise){ 3920 + bi->gcPrioritise = 1; 3921 + dev->hasPendingPrioritisedGCs = 1; 3922 + bi->chunkErrorStrikes ++; 3923 + 3924 + if(bi->chunkErrorStrikes > 3){ 3925 + bi->needsRetiring = 1; /* Too many stikes, so retire this */ 3926 + T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR))); 3927 + 3928 + } 3929 + 3930 + } 3931 +} 3932 + 3933 +static void yaffs_ReportOddballBlocks(yaffs_Device *dev) 3934 +{ 3935 + int i; 3936 + 3937 + for(i = dev->internalStartBlock; i <= dev->internalEndBlock && (yaffs_traceMask & YAFFS_TRACE_BAD_BLOCKS); i++){ 3938 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); 3939 + if(bi->needsRetiring || bi->gcPrioritise) 3940 + T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("yaffs block %d%s%s" TENDSTR), 3941 + i, 3942 + bi->needsRetiring ? " needs retiring" : "", 3943 + bi->gcPrioritise ? " gc prioritised" : "")); 3944 + 3945 + } 3946 +} 3947 + 3948 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk) 3949 +{ 3950 + 3951 + int blockInNAND = chunkInNAND / dev->nChunksPerBlock; 3952 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); 3953 + 3954 + yaffs_HandleChunkError(dev,bi); 3955 + 3956 + 3957 + if(erasedOk ) { 3958 + /* Was an actual write failure, so mark the block for retirement */ 3959 + bi->needsRetiring = 1; 3960 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, 3961 + (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND)); 3962 + 3963 + 3964 + } 3965 + 3966 + /* Delete the chunk */ 3967 + yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__); 3968 +} 3969 + 3970 + 3971 +/*---------------- Name handling functions ------------*/ 3972 + 3973 +static __u16 yaffs_CalcNameSum(const YCHAR * name) 2942 +#endif 2943 + 2944 + 2945 +///////////////////////// Object management ////////////////// 2946 +// List of spare objects 2947 +// The list is hooked together using the first pointer 2948 +// in the object 2949 + 2950 +// static yaffs_Object *yaffs_freeObjects = NULL; 2951 + 2952 +// static int yaffs_nFreeObjects; 2953 + 2954 +// static yaffs_ObjectList *yaffs_allocatedObjectList = NULL; 2955 + 2956 +// static yaffs_ObjectBucket yaffs_objectBucket[YAFFS_NOBJECT_BUCKETS]; 2957 + 2958 + 2959 +static __u16 yaffs_CalcNameSum(const YCHAR *name) 3974 2960 +{ 3975 2961 + __u16 sum = 0; 3976 2962 + __u16 i = 1; 3977 + 3978 + YUCHAR *bname = (YUCHAR *) name; 3979 + if (bname) { 3980 + while ((*bname) && (i <= YAFFS_MAX_NAME_LENGTH)) { 2963 + 2964 + YUCHAR *bname = (YUCHAR *)name; 2965 + if(bname) 2966 + { 2967 + while ((*bname) && (i <=YAFFS_MAX_NAME_LENGTH)) 2968 + { 3981 2969 + 3982 2970 +#ifdef CONFIG_YAFFS_CASE_INSENSITIVE … … 3992 2980 +} 3993 2981 + 3994 +static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR *name)2982 +static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name) 3995 2983 +{ 3996 2984 +#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM 3997 + if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) { 3998 + yaffs_strcpy(obj->shortName, name); 3999 + } else { 4000 + obj->shortName[0] = _Y('\0'); 4001 + } 4002 +#endif 4003 + obj->sum = yaffs_CalcNameSum(name); 4004 +} 4005 + 4006 +/*-------------------- TNODES ------------------- 4007 + 4008 + * List of spare tnodes 4009 + * The list is hooked together using the first pointer 4010 + * in the tnode. 4011 + */ 4012 + 4013 +/* yaffs_CreateTnodes creates a bunch more tnodes and 4014 + * adds them to the tnode free list. 4015 + * Don't use this function directly 4016 + */ 4017 + 4018 +static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes) 4019 +{ 4020 + int i; 4021 + int tnodeSize; 4022 + yaffs_Tnode *newTnodes; 4023 + __u8 *mem; 4024 + yaffs_Tnode *curr; 4025 + yaffs_Tnode *next; 4026 + yaffs_TnodeList *tnl; 4027 + 4028 + if (nTnodes < 1) 4029 + return YAFFS_OK; 4030 + 4031 + /* Calculate the tnode size in bytes for variable width tnode support. 4032 + * Must be a multiple of 32-bits */ 4033 + tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; 4034 + 4035 + /* make these things */ 4036 + 4037 + newTnodes = YMALLOC(nTnodes * tnodeSize); 4038 + mem = (__u8 *)newTnodes; 4039 + 4040 + if (!newTnodes) { 4041 + T(YAFFS_TRACE_ERROR, 4042 + (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); 2985 + if(name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) 2986 + { 2987 + yaffs_strcpy(obj->shortName,name); 2988 + } 2989 + else 2990 + { 2991 + obj->shortName[0]=_Y('\0'); 2992 + } 2993 +#endif 2994 + obj->sum = yaffs_CalcNameSum(name); 2995 +} 2996 + 2997 +#if 0 2998 +void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) 2999 +{ 3000 + yaffs_ECCCalculate(data , spare->ecc1); 3001 + yaffs_ECCCalculate(&data[256] , spare->ecc2); 3002 +} 3003 +#endif 3004 + 3005 + 3006 +///////////////////////// TNODES /////////////////////// 3007 + 3008 +// List of spare tnodes 3009 +// The list is hooked together using the first pointer 3010 +// in the tnode. 3011 + 3012 +//static yaffs_Tnode *yaffs_freeTnodes = NULL; 3013 + 3014 +// static int yaffs_nFreeTnodes; 3015 + 3016 +//static yaffs_TnodeList *yaffs_allocatedTnodeList = NULL; 3017 + 3018 + 3019 + 3020 +// yaffs_CreateTnodes creates a bunch more tnodes and 3021 +// adds them to the tnode free list. 3022 +// Don't use this function directly 3023 + 3024 +static int yaffs_CreateTnodes(yaffs_Device *dev,int nTnodes) 3025 +{ 3026 + int i; 3027 + yaffs_Tnode *newTnodes; 3028 + yaffs_TnodeList *tnl; 3029 + 3030 + if(nTnodes < 1) return YAFFS_OK; 3031 + 3032 + // make these things 3033 + 3034 + newTnodes = YMALLOC(nTnodes * sizeof(yaffs_Tnode)); 3035 + 3036 + if (!newTnodes) 3037 + { 3038 + T(YAFFS_TRACE_ERROR,(TSTR("yaffs: Could not allocate Tnodes"TENDSTR))); 4043 3039 + return YAFFS_FAIL; 4044 + }4045 + 4046 + /* Hook them into the free list */4047 + #if 04048 + for (i = 0; i < nTnodes - 1; i++){4049 + newTnodes[i].internal[0] = &newTnodes[i +1];3040 + } 3041 + 3042 + // Hook them into the free list 3043 + for(i = 0; i < nTnodes - 1; i++) 3044 + { 3045 + newTnodes[i].internal[0] = &newTnodes[i+1]; 4050 3046 +#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG 4051 + newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;4052 +#endif 4053 + }4054 + 3047 + newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1; 3048 +#endif 3049 + } 3050 + 4055 3051 + newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes; 4056 3052 +#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG 4057 + newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;3053 + newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1; 4058 3054 +#endif 4059 3055 + dev->freeTnodes = newTnodes; 4060 +#else 4061 + /* New hookup for wide tnodes */ 4062 + for(i = 0; i < nTnodes -1; i++) { 4063 + curr = (yaffs_Tnode *) &mem[i * tnodeSize]; 4064 + next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize]; 4065 + curr->internal[0] = next; 4066 + } 4067 + 4068 + curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize]; 4069 + curr->internal[0] = dev->freeTnodes; 4070 + dev->freeTnodes = (yaffs_Tnode *)mem; 4071 + 4072 +#endif 4073 + 4074 + 4075 + dev->nFreeTnodes += nTnodes; 3056 + dev->nFreeTnodes+= nTnodes; 4076 3057 + dev->nTnodesCreated += nTnodes; 4077 3058 + 4078 + /* Now add this bunch of tnodes to a list for freeing up. 4079 + * NB If we can't add this to the management list it isn't fatal 4080 + * but it just means we can't free this bunch of tnodes later. 4081 + */ 4082 + 3059 + // Now add this bunch of tnodes to a list for freeing up. 3060 + // NB If we can't add this to the management list it isn't fatal 3061 + // but it just means we can't free this bunch of tnodes later. 4083 3062 + tnl = YMALLOC(sizeof(yaffs_TnodeList)); 4084 + if (!tnl) { 4085 + T(YAFFS_TRACE_ERROR, 4086 + (TSTR 4087 + ("yaffs: Could not add tnodes to management list" TENDSTR))); 4088 + 4089 + } else { 3063 + if(!tnl) 3064 + { 3065 + T(YAFFS_TRACE_ERROR,(TSTR("yaffs: Could not add tnodes to management list" TENDSTR))); 3066 + 3067 + } 3068 + else 3069 + { 4090 3070 + tnl->tnodes = newTnodes; 4091 3071 + tnl->next = dev->allocatedTnodeList; … … 4093 3073 + } 4094 3074 + 4095 + T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR))); 3075 + 3076 + T(YAFFS_TRACE_ALLOCATE,(TSTR("yaffs: Tnodes added" TENDSTR))); 3077 + 4096 3078 + 4097 3079 + return YAFFS_OK; 4098 3080 +} 4099 3081 + 4100 + /* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */4101 + 4102 +static yaffs_Tnode *yaffs_GetTnode Raw(yaffs_Device *dev)3082 + 3083 +// GetTnode gets us a clean tnode. Tries to make allocate more if we run out 3084 +static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev) 4103 3085 +{ 4104 3086 + yaffs_Tnode *tn = NULL; 4105 + 4106 + /* If there are none left make more */ 4107 + if (!dev->freeTnodes) { 4108 + yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES); 4109 + } 4110 + 4111 + if (dev->freeTnodes) { 3087 + 3088 + // If there are none left make more 3089 + if(!dev->freeTnodes) 3090 + { 3091 + yaffs_CreateTnodes(dev,YAFFS_ALLOCATION_NTNODES); 3092 + } 3093 + 3094 + if(dev->freeTnodes) 3095 + { 4112 3096 + tn = dev->freeTnodes; 4113 3097 +#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG 4114 + if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) {4115 + /* Hoosterman, this thing looks like it isn't in the list */4116 + T(YAFFS_TRACE_ALWAYS,4117 + (TSTR("yaffs: Tnode list bug 1" TENDSTR)));3098 + if(tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) 3099 + { 3100 + // Hoosterman, this thing looks like it isn't in the list 3101 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 1" TENDSTR))); 4118 3102 + } 4119 3103 +#endif 4120 3104 + dev->freeTnodes = dev->freeTnodes->internal[0]; 4121 3105 + dev->nFreeTnodes--; 4122 + } 3106 + // zero out 3107 + memset(tn,0,sizeof(yaffs_Tnode)); 3108 + } 3109 + 4123 3110 + 4124 3111 + return tn; 4125 3112 +} 4126 3113 + 4127 + static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)4128 + {4129 + yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);4130 + 3114 + 3115 +// FreeTnode frees up a tnode and puts it back on the free list 3116 +static void yaffs_FreeTnode(yaffs_Device*dev, yaffs_Tnode *tn) 3117 +{ 4131 3118 + if(tn) 4132 + memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); 4133 + 4134 + return tn; 4135 +} 4136 + 4137 +/* FreeTnode frees up a tnode and puts it back on the free list */ 4138 +static void yaffs_FreeTnode(yaffs_Device * dev, yaffs_Tnode * tn) 4139 +{ 4140 + if (tn) { 3119 + { 4141 3120 +#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG 4142 + if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) {4143 + /* Hoosterman, this thing looks like it is already in the list */4144 + T(YAFFS_TRACE_ALWAYS,4145 + (TSTR("yaffs: Tnode list bug 2" TENDSTR)));3121 + if(tn->internal[YAFFS_NTNODES_INTERNAL] != 0) 3122 + { 3123 + // Hoosterman, this thing looks like it is already in the list 3124 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 2" TENDSTR))); 4146 3125 + } 4147 3126 + tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1; … … 4153 3132 +} 4154 3133 + 4155 +static void yaffs_DeinitialiseTnodes(yaffs_Device * dev) 4156 +{ 4157 + /* Free the list of allocated tnodes */ 3134 + 3135 +static void yaffs_DeinitialiseTnodes(yaffs_Device*dev) 3136 +{ 3137 + // Free the list of allocated tnodes 4158 3138 + yaffs_TnodeList *tmp; 4159 + 4160 + while (dev->allocatedTnodeList) { 4161 + tmp = dev->allocatedTnodeList->next; 3139 + 3140 + while(dev->allocatedTnodeList) 3141 + { 3142 + tmp = dev->allocatedTnodeList->next; 4162 3143 + 4163 3144 + YFREE(dev->allocatedTnodeList->tnodes); 4164 3145 + YFREE(dev->allocatedTnodeList); 4165 + dev->allocatedTnodeList = tmp;4166 + 4167 + } 4168 + 3146 + dev->allocatedTnodeList = tmp; 3147 + 3148 + } 3149 + 4169 3150 + dev->freeTnodes = NULL; 4170 3151 + dev->nFreeTnodes = 0; 4171 3152 +} 4172 3153 + 4173 +static void yaffs_InitialiseTnodes(yaffs_Device *dev)3154 +static void yaffs_InitialiseTnodes(yaffs_Device*dev) 4174 3155 +{ 4175 3156 + dev->allocatedTnodeList = NULL; … … 4180 3161 +} 4181 3162 + 4182 + 4183 +void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val) 4184 +{ 4185 + __u32 *map = (__u32 *)tn; 4186 + __u32 bitInMap; 4187 + __u32 bitInWord; 4188 + __u32 wordInMap; 4189 + __u32 mask; 4190 + 4191 + pos &= YAFFS_TNODES_LEVEL0_MASK; 4192 + val >>= dev->chunkGroupBits; 4193 + 4194 + bitInMap = pos * dev->tnodeWidth; 4195 + wordInMap = bitInMap /32; 4196 + bitInWord = bitInMap & (32 -1); 4197 + 4198 + mask = dev->tnodeMask << bitInWord; 4199 + 4200 + map[wordInMap] &= ~mask; 4201 + map[wordInMap] |= (mask & (val << bitInWord)); 4202 + 4203 + if(dev->tnodeWidth > (32-bitInWord)) { 4204 + bitInWord = (32 - bitInWord); 4205 + wordInMap++;; 4206 + mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord); 4207 + map[wordInMap] &= ~mask; 4208 + map[wordInMap] |= (mask & (val >> bitInWord)); 4209 + } 4210 +} 4211 + 4212 +__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) 4213 +{ 4214 + __u32 *map = (__u32 *)tn; 4215 + __u32 bitInMap; 4216 + __u32 bitInWord; 4217 + __u32 wordInMap; 4218 + __u32 val; 4219 + 4220 + pos &= YAFFS_TNODES_LEVEL0_MASK; 4221 + 4222 + bitInMap = pos * dev->tnodeWidth; 4223 + wordInMap = bitInMap /32; 4224 + bitInWord = bitInMap & (32 -1); 4225 + 4226 + val = map[wordInMap] >> bitInWord; 4227 + 4228 + if(dev->tnodeWidth > (32-bitInWord)) { 4229 + bitInWord = (32 - bitInWord); 4230 + wordInMap++;; 4231 + val |= (map[wordInMap] << bitInWord); 4232 + } 4233 + 4234 + val &= dev->tnodeMask; 4235 + val <<= dev->chunkGroupBits; 4236 + 4237 + return val; 4238 +} 4239 + 4240 +/* ------------------- End of individual tnode manipulation -----------------*/ 4241 + 4242 +/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------ 4243 + * The look up tree is represented by the top tnode and the number of topLevel 4244 + * in the tree. 0 means only the level 0 tnode is in the tree. 4245 + */ 4246 + 4247 +/* FindLevel0Tnode finds the level 0 tnode, if one exists. */ 4248 +static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev, 4249 + yaffs_FileStructure * fStruct, 4250 + __u32 chunkId) 4251 +{ 4252 + 3163 +#if 0 3164 +void yaffs_TnodeTest(yaffs_Device *dev) 3165 +{ 3166 + 3167 + int i; 3168 + int j; 3169 + yaffs_Tnode *tn[1000]; 3170 + 3171 + YINFO("Testing TNodes"); 3172 + 3173 + for(j = 0; j < 50; j++) 3174 + { 3175 + for(i = 0; i < 1000; i++) 3176 + { 3177 + tn[i] = yaffs_GetTnode(dev); 3178 + if(!tn[i]) 3179 + { 3180 + YALERT("Getting tnode failed"); 3181 + } 3182 + } 3183 + for(i = 0; i < 1000; i+=3) 3184 + { 3185 + yaffs_FreeTnode(dev,tn[i]); 3186 + tn[i] = NULL; 3187 + } 3188 + 3189 + } 3190 +} 3191 +#endif 3192 + 3193 + 3194 +////////////////// END OF TNODE MANIPULATION /////////////////////////// 3195 + 3196 +/////////////// Functions to manipulate the look-up tree (made up of tnodes) 3197 +// The look up tree is represented by the top tnode and the number of topLevel 3198 +// in the tree. 0 means only the level 0 tnode is in the tree. 3199 + 3200 + 3201 +// FindLevel0Tnode finds the level 0 tnode, if one exists. 3202 +// Used when reading..... 3203 +static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev,yaffs_FileStructure *fStruct, __u32 chunkId) 3204 +{ 3205 + 4253 3206 + yaffs_Tnode *tn = fStruct->top; 4254 3207 + __u32 i; 4255 + int requiredTallness; 3208 + int requiredTallness; 4256 3209 + int level = fStruct->topLevel; 4257 + 4258 + /* Check sane level and chunk Id */ 4259 + if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) { 3210 + 3211 + // Check sane level and chunk Id 3212 + if(level < 0 || level > YAFFS_TNODES_MAX_LEVEL) 3213 + { 3214 +// char str[50]; 3215 +// sprintf(str,"Bad level %d",level); 3216 +// YALERT(str); 4260 3217 + return NULL; 4261 3218 + } 4262 + 4263 + if (chunkId > YAFFS_MAX_CHUNK_ID) { 3219 + 3220 + if(chunkId > YAFFS_MAX_CHUNK_ID) 3221 + { 3222 +// char str[50]; 3223 +// sprintf(str,"Bad chunkId %d",chunkId); 3224 +// YALERT(str); 4264 3225 + return NULL; 4265 3226 + } 4266 3227 + 4267 + / * First check we're tall enough (ie enough topLevel) */4268 + 4269 + i = chunkId >> YAFFS_TNODES_LEVEL0_BITS;3228 + // First check we're tall enough (ie enough topLevel) 3229 + 3230 + i = chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS); 4270 3231 + requiredTallness = 0; 4271 + while (i) { 3232 + while(i) 3233 + { 4272 3234 + i >>= YAFFS_TNODES_INTERNAL_BITS; 4273 3235 + requiredTallness++; 4274 3236 + } 4275 + 4276 + if (requiredTallness > fStruct->topLevel) { 4277 + /* Not tall enough, so we can't find it, return NULL. */ 3237 + 3238 + 3239 + if(requiredTallness > fStruct->topLevel) 3240 + { 3241 + // Not tall enough, so we can't find it, return NULL. 4278 3242 + return NULL; 4279 3243 + } 4280 + 4281 + /* Traverse down to level 0 */ 4282 + while (level > 0 && tn) { 4283 + tn = tn-> 4284 + internal[(chunkId >> 4285 + ( YAFFS_TNODES_LEVEL0_BITS + 4286 + (level - 1) * 4287 + YAFFS_TNODES_INTERNAL_BITS) 4288 + ) & 4289 + YAFFS_TNODES_INTERNAL_MASK]; 3244 + 3245 + 3246 + // Traverse down to level 0 3247 + while (level > 0 && tn) 3248 + { 3249 + tn = tn->internal[(chunkId >>(/* dev->chunkGroupBits + */ YAFFS_TNODES_LEVEL0_BITS + (level-1) * YAFFS_TNODES_INTERNAL_BITS)) & 3250 + YAFFS_TNODES_INTERNAL_MASK]; 4290 3251 + level--; 4291 + 4292 + } 4293 + 4294 + return tn; 4295 +} 4296 + 4297 +/* AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree. 4298 + * This happens in two steps: 4299 + * 1. If the tree isn't tall enough, then make it taller. 4300 + * 2. Scan down the tree towards the level 0 tnode adding tnodes if required. 4301 + * 4302 + * Used when modifying the tree. 4303 + * 4304 + * If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will 4305 + * be plugged into the ttree. 4306 + */ 4307 + 4308 +static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev, 4309 + yaffs_FileStructure * fStruct, 4310 + __u32 chunkId, 4311 + yaffs_Tnode *passedTn) 4312 +{ 4313 + 3252 + 3253 + } 3254 + 3255 + return tn; 3256 +} 3257 + 3258 +// AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree. 3259 +// This happens in two steps: 3260 +// 1. If the tree isn't tall enough, then make it taller. 3261 +// 2. Scan down the tree towards the level 0 tnode adding tnodes if required. 3262 +// 3263 +// Used when modifying the tree. 3264 +// 3265 +static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId) 3266 +{ 3267 + 3268 + yaffs_Tnode *tn; 3269 + 4314 3270 + int requiredTallness; 4315 3271 + int i; 4316 3272 + int l; 4317 + yaffs_Tnode *tn; 4318 + 3273 + 4319 3274 + __u32 x; 4320 + 4321 + 4322 + /* Check sane level and page Id */ 4323 + if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) { 3275 + 3276 + 3277 + //T((TSTR("AddOrFind topLevel=%d, chunk=%d"),fStruct->topLevel,chunkId)); 3278 + 3279 + // Check sane level and page Id 3280 + if(fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) 3281 + { 3282 +// char str[50]; 3283 +// sprintf(str,"Bad level %d",fStruct->topLevel); 3284 +// YALERT(str); 4324 3285 + return NULL; 4325 3286 + } 4326 + 4327 + if (chunkId > YAFFS_MAX_CHUNK_ID) { 3287 + 3288 + if(chunkId > YAFFS_MAX_CHUNK_ID) 3289 + { 3290 +// char str[50]; 3291 +// sprintf(str,"Bad chunkId %d",chunkId); 3292 +// YALERT(str); 4328 3293 + return NULL; 4329 3294 + } 4330 + 4331 + / * First check we're tall enough (ie enough topLevel) */4332 + 4333 + x = chunkId >> YAFFS_TNODES_LEVEL0_BITS;3295 + 3296 + // First check we're tall enough (ie enough topLevel) 3297 + 3298 + x = chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS); 4334 3299 + requiredTallness = 0; 4335 + while (x) { 3300 + while(x) 3301 + { 4336 3302 + x >>= YAFFS_TNODES_INTERNAL_BITS; 4337 3303 + requiredTallness++; 4338 3304 + } 4339 + 4340 + 4341 + if (requiredTallness > fStruct->topLevel) { 4342 + /* Not tall enough,gotta make the tree taller */ 4343 + for (i = fStruct->topLevel; i < requiredTallness; i++) { 4344 + 3305 + 3306 + //T((TSTR(" required=%d"),requiredTallness)); 3307 + 3308 + 3309 + if(requiredTallness > fStruct->topLevel) 3310 + { 3311 + // Not tall enough,gotta make the tree taller 3312 + for(i = fStruct->topLevel; i < requiredTallness; i++) 3313 + { 3314 + //T((TSTR(" add new top"))); 3315 + 4345 3316 + tn = yaffs_GetTnode(dev); 4346 + 4347 + if (tn) { 3317 + 3318 + if(tn) 3319 + { 4348 3320 + tn->internal[0] = fStruct->top; 4349 3321 + fStruct->top = tn; 4350 + } else {4351 + T(YAFFS_TRACE_ERROR,4352 + (TSTR("yaffs: no more tnodes" TENDSTR)));4353 3322 + } 4354 + } 4355 + 3323 + else 3324 + { 3325 + T(YAFFS_TRACE_ERROR,(TSTR("yaffs: no more tnodes" TENDSTR))); 3326 + } 3327 + } 3328 + 4356 3329 + fStruct->topLevel = requiredTallness; 4357 3330 + } 4358 + 4359 + /* Traverse down to level 0, adding anything we need */ 4360 + 3331 + 3332 + 3333 + // Traverse down to level 0, adding anything we need 3334 + 4361 3335 + l = fStruct->topLevel; 4362 3336 + tn = fStruct->top; 4363 + 4364 + if(l > 0) { 4365 + while (l > 0 && tn) { 4366 + x = (chunkId >> 4367 + ( YAFFS_TNODES_LEVEL0_BITS + 4368 + (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) & 4369 + YAFFS_TNODES_INTERNAL_MASK; 4370 + 4371 + 4372 + if((l>1) && !tn->internal[x]){ 4373 + /* Add missing non-level-zero tnode */ 4374 + tn->internal[x] = yaffs_GetTnode(dev); 4375 + 4376 + } else if(l == 1) { 4377 + /* Looking from level 1 at level 0 */ 4378 + if (passedTn) { 4379 + /* If we already have one, then release it.*/ 4380 + if(tn->internal[x]) 4381 + yaffs_FreeTnode(dev,tn->internal[x]); 4382 + tn->internal[x] = passedTn; 4383 + 4384 + } else if(!tn->internal[x]) { 4385 + /* Don't have one, none passed in */ 4386 + tn->internal[x] = yaffs_GetTnode(dev); 4387 + } 3337 + while (l > 0 && tn) 3338 + { 3339 + x = (chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS + (l-1) * YAFFS_TNODES_INTERNAL_BITS)) & 3340 + YAFFS_TNODES_INTERNAL_MASK; 3341 + 3342 + //T((TSTR(" [%d:%d]"),l,i)); 3343 + 3344 + if(!tn->internal[x]) 3345 + { 3346 + //T((TSTR(" added"))); 3347 + 3348 + tn->internal[x] = yaffs_GetTnode(dev); 3349 + } 3350 + 3351 + tn = tn->internal[x]; 3352 + l--; 3353 + 3354 + } 3355 + 3356 + //TSTR(TENDSTR))); 3357 + 3358 + return tn; 3359 +} 3360 + 3361 + 3362 +static int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk, yaffs_ExtendedTags *tags, int objectId, int chunkInInode) 3363 +{ 3364 + int j; 3365 + 3366 + 3367 + for(j = 0; theChunk && j < dev->chunkGroupSize; j++) 3368 + { 3369 + if(yaffs_CheckChunkBit(dev,theChunk / dev->nChunksPerBlock,theChunk % dev->nChunksPerBlock)) 3370 + { 3371 + yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL,tags); 3372 + if(yaffs_TagsMatch(tags,objectId,chunkInInode)) 3373 + { 3374 + // found it; 3375 + return theChunk; 3376 + 4388 3377 + } 4389 +4390 + tn = tn->internal[x];4391 + l--;4392 + }4393 + } else {4394 + /* top is level 0 */4395 + if(passedTn) {4396 + memcpy(tn,passedTn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);4397 + yaffs_FreeTnode(dev,passedTn);4398 + }4399 + }4400 +4401 + return tn;4402 +}4403 +4404 +static int yaffs_FindChunkInGroup(yaffs_Device * dev, int theChunk,4405 + yaffs_ExtendedTags * tags, int objectId,4406 + int chunkInInode)4407 +{4408 + int j;4409 +4410 + for (j = 0; theChunk && j < dev->chunkGroupSize; j++) {4411 + if (yaffs_CheckChunkBit4412 + (dev, theChunk / dev->nChunksPerBlock,4413 + theChunk % dev->nChunksPerBlock)) {4414 + yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL,4415 + tags);4416 + if (yaffs_TagsMatch(tags, objectId, chunkInInode)) {4417 + /* found it; */4418 + return theChunk;4419 +4420 + }4421 3378 + } 4422 3379 + theChunk++; … … 4425 3382 +} 4426 3383 + 4427 + 4428 +/* DeleteWorker scans backwards through the tnode tree and deletes all the 4429 + * chunks and tnodes in the file 4430 + * Returns 1 if the tree was deleted. 4431 + * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete. 4432 + */ 4433 + 4434 +static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, 4435 + int chunkOffset, int *limit) 3384 +// DeleteWorker scans backwards through the tnode tree and deletes all the 3385 +// chunks and tnodes in the file 3386 +// Returns 1 if the tree was deleted. Returns 0 if it stopped early due to hitting the limit and the delete is incomplete. 3387 + 3388 +static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit) 4436 3389 +{ 4437 3390 + int i; … … 4443 3396 + 4444 3397 + int allDone = 1; 4445 + 4446 + if (tn) { 4447 + if (level > 0) { 4448 + 4449 + for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0; 4450 + i--) { 4451 + if (tn->internal[i]) { 4452 + if (limit && (*limit) < 0) { 3398 + 3399 + 3400 + if(tn) 3401 + { 3402 + if(level > 0) 3403 + { 3404 + 3405 + for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--) 3406 + { 3407 + if(tn->internal[i]) 3408 + { 3409 + if(limit && (*limit) < 0) 3410 + { 4453 3411 + allDone = 0; 4454 + } else {4455 + allDone =4456 + yaffs_DeleteWorker(in,4457 + tn->4458 + internal4459 + [i],4460 + level -4461 + 1,4462 + (chunkOffset4463 + <<4464 + YAFFS_TNODES_INTERNAL_BITS)4465 + + i,4466 + limit);4467 3412 + } 4468 + if (allDone) { 4469 + yaffs_FreeTnode(dev, 4470 + tn-> 4471 + internal[i]); 4472 + tn->internal[i] = NULL; 3413 + else 3414 + { 3415 + allDone = yaffs_DeleteWorker(in,tn->internal[i],level - 1, 3416 + (chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i ,limit); 4473 3417 + } 4474 + } 4475 + 3418 + if(allDone) 3419 + { 3420 + yaffs_FreeTnode(dev,tn->internal[i]); 3421 + tn->internal[i] = NULL; 3422 + } 3423 + } 3424 + 4476 3425 + } 4477 3426 + return (allDone) ? 1 : 0; 4478 + } else if (level == 0) { 3427 + } 3428 + else if(level == 0) 3429 + { 4479 3430 + int hitLimit = 0; 4480 + 4481 + for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit; 4482 + i--) { 4483 + theChunk = yaffs_GetChunkGroupBase(dev,tn,i); 4484 + if (theChunk) { 4485 + 4486 + chunkInInode = 4487 + (chunkOffset << 4488 + YAFFS_TNODES_LEVEL0_BITS) + i; 4489 + 4490 + foundChunk = 4491 + yaffs_FindChunkInGroup(dev, 4492 + theChunk, 4493 + &tags, 4494 + in->objectId, 4495 + chunkInInode); 4496 + 4497 + if (foundChunk > 0) { 4498 + yaffs_DeleteChunk(dev, 4499 + foundChunk, 1, 4500 + __LINE__); 3431 + 3432 + for(i = YAFFS_NTNODES_LEVEL0 -1; i >= 0 && !hitLimit; i--) 3433 + { 3434 + if(tn->level0[i]) 3435 + { 3436 + 3437 + chunkInInode = (chunkOffset << YAFFS_TNODES_LEVEL0_BITS ) + i; 3438 + 3439 + theChunk = tn->level0[i] << dev->chunkGroupBits; 3440 + 3441 + foundChunk = yaffs_FindChunkInGroup(dev,theChunk,&tags,in->objectId,chunkInInode); 3442 + 3443 + if(foundChunk > 0) 3444 + { 3445 + yaffs_DeleteChunk(dev,foundChunk,1,__LINE__); 4501 3446 + in->nDataChunks--; 4502 + if (limit) { 4503 + *limit = *limit - 1; 4504 + if (*limit <= 0) { 3447 + if(limit) 3448 + { 3449 + *limit = *limit-1; 3450 + if(*limit <= 0) 3451 + { 4505 3452 + hitLimit = 1; 4506 3453 + } 4507 3454 + } 4508 + 3455 + 4509 3456 + } 4510 + 4511 + yaffs_PutLevel0Tnode(dev,tn,i,0);4512 + }4513 + 3457 + 3458 + tn->level0[i] = 0; 3459 + } 3460 + 4514 3461 + } 4515 3462 + return (i < 0) ? 1 : 0; 4516 3463 + 4517 + } 4518 + 4519 + } 4520 + 3464 + 3465 + } 3466 + 3467 + } 3468 + 4521 3469 + return 1; 4522 + 4523 +} 4524 + 4525 +static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk) 4526 +{ 4527 + 4528 + yaffs_BlockInfo *theBlock; 4529 + 4530 + T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk)); 4531 + 4532 + theBlock = yaffs_GetBlockInfo(dev, chunk / dev->nChunksPerBlock); 4533 + if (theBlock) { 3470 + 3471 +} 3472 + 3473 + 3474 +static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk) 3475 +{ 3476 + 3477 + yaffs_BlockInfo *theBlock; 3478 + 3479 + T(YAFFS_TRACE_DELETION,(TSTR("soft delete chunk %d" TENDSTR),chunk)); 3480 + 3481 + theBlock = yaffs_GetBlockInfo(dev, chunk/dev->nChunksPerBlock); 3482 + if(theBlock) 3483 + { 4534 3484 + theBlock->softDeletions++; 4535 3485 + dev->nFreeChunks++; … … 4537 3487 +} 4538 3488 + 4539 +/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file. 4540 + * All soft deleting does is increment the block's softdelete count and pulls the chunk out 4541 + * of the tnode. 4542 + * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted. 4543 + */ 4544 + 4545 +static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, 4546 + __u32 level, int chunkOffset) 3489 +// SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file. 3490 +// All soft deleting does is increment the block's softdelete count and pulls the chunk out 3491 +// of the tnode. 3492 +// THus, essentially this is the same as DeleteWorker except that the chunks are soft deleted. 3493 +// 3494 +static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset) 4547 3495 +{ 4548 3496 + int i; … … 4550 3498 + int allDone = 1; 4551 3499 + yaffs_Device *dev = in->myDev; 4552 + 4553 + if (tn) { 4554 + if (level > 0) { 4555 + 4556 + for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0; 4557 + i--) { 4558 + if (tn->internal[i]) { 4559 + allDone = 4560 + yaffs_SoftDeleteWorker(in, 4561 + tn-> 4562 + internal[i], 4563 + level - 1, 4564 + (chunkOffset 4565 + << 4566 + YAFFS_TNODES_INTERNAL_BITS) 4567 + + i); 4568 + if (allDone) { 4569 + yaffs_FreeTnode(dev, 4570 + tn-> 4571 + internal[i]); 4572 + tn->internal[i] = NULL; 4573 + } else { 4574 + /* Hoosterman... how could this happen? */ 3500 + 3501 + 3502 + if(tn) 3503 + { 3504 + if(level > 0) 3505 + { 3506 + 3507 + for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--) 3508 + { 3509 + if(tn->internal[i]) 3510 + { 3511 + allDone = yaffs_SoftDeleteWorker(in,tn->internal[i],level - 1, 3512 + (chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i); 3513 + if(allDone) 3514 + { 3515 + yaffs_FreeTnode(dev,tn->internal[i]); 3516 + tn->internal[i] = NULL; 4575 3517 + } 4576 + } 3518 + else 3519 + { 3520 + //Hoosterman... how could this happen. 3521 + } 3522 + } 4577 3523 + } 4578 3524 + return (allDone) ? 1 : 0; 4579 + } else if (level == 0) { 4580 + 4581 + for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) { 4582 + theChunk = yaffs_GetChunkGroupBase(dev,tn,i); 4583 + if (theChunk) { 4584 + /* Note this does not find the real chunk, only the chunk group. 4585 + * We make an assumption that a chunk group is not larger than 4586 + * a block. 4587 + */ 4588 + yaffs_SoftDeleteChunk(dev, theChunk); 4589 + yaffs_PutLevel0Tnode(dev,tn,i,0); 4590 + } 4591 + 3525 + } 3526 + else if(level == 0) 3527 + { 3528 + 3529 + for(i = YAFFS_NTNODES_LEVEL0 -1; i >=0; i--) 3530 + { 3531 + if(tn->level0[i]) 3532 + { 3533 + // Note this does not find the real chunk, only the chunk group. 3534 + // We make an assumption that a chunk group is niot larger than a block. 3535 + theChunk = (tn->level0[i] << dev->chunkGroupBits); 3536 + 3537 + yaffs_SoftDeleteChunk(dev,theChunk); 3538 + tn->level0[i] = 0; 3539 + } 3540 + 4592 3541 + } 4593 3542 + return 1; 4594 + 4595 + } 4596 + 4597 + } 4598 + 3543 + 3544 + } 3545 + 3546 + } 3547 + 4599 3548 + return 1; 4600 + 4601 +} 4602 + 4603 +static void yaffs_SoftDeleteFile(yaffs_Object * obj) 4604 +{ 4605 + if (obj->deleted && 4606 + obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) { 4607 + if (obj->nDataChunks <= 0) { 4608 + /* Empty file with no duplicate object headers, just delete it immediately */ 4609 + yaffs_FreeTnode(obj->myDev, 4610 + obj->variant.fileVariant.top); 4611 + obj->variant.fileVariant.top = NULL; 4612 + T(YAFFS_TRACE_TRACING, 4613 + (TSTR("yaffs: Deleting empty file %d" TENDSTR), 4614 + obj->objectId)); 4615 + yaffs_DoGenericObjectDeletion(obj); 4616 + } else { 4617 + yaffs_SoftDeleteWorker(obj, 4618 + obj->variant.fileVariant.top, 4619 + obj->variant.fileVariant. 4620 + topLevel, 0); 3549 + 3550 +} 3551 + 3552 + 3553 + 3554 +static void yaffs_SoftDeleteFile(yaffs_Object *obj) 3555 +{ 3556 + if(obj->deleted && 3557 + obj->variantType == YAFFS_OBJECT_TYPE_FILE && 3558 + !obj->softDeleted) 3559 + { 3560 + if(obj->nDataChunks <= 0) 3561 + { 3562 + // Empty file with no duplicate object headers, just delete it immediately 3563 + yaffs_FreeTnode(obj->myDev,obj->variant.fileVariant.top); 3564 + obj->variant.fileVariant.top = NULL; 3565 + T(YAFFS_TRACE_TRACING,(TSTR("yaffs: Deleting empty file %d" TENDSTR),obj->objectId)); 3566 + yaffs_DoGenericObjectDeletion(obj); 3567 + } 3568 + else 3569 + { 3570 + yaffs_SoftDeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0); 4621 3571 + obj->softDeleted = 1; 4622 3572 + } … … 4624 3574 +} 4625 3575 + 4626 +/* Pruning removes any part of the file structure tree that is beyond the 4627 + * bounds of the file (ie that does not point to chunks). 4628 + * 4629 + * A file should only get pruned when its size is reduced. 4630 + * 4631 + * Before pruning, the chunks must be pulled from the tree and the 4632 + * level 0 tnode entries must be zeroed out. 4633 + * Could also use this for file deletion, but that's probably better handled 4634 + * by a special case. 4635 + */ 4636 + 4637 +static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn, 4638 + __u32 level, int del0) 3576 + 3577 + 3578 + 3579 + 3580 +// Pruning removes any part of the file structure tree that is beyond the 3581 +// bounds of the file (ie that does not point to chunks). 3582 +// 3583 +// A file should only get pruned when its size is reduced. 3584 +// 3585 +// Before pruning, the chunks must be pulled from the tree and the 3586 +// level 0 tnode entries must be zeroed out. 3587 +// Could also use this for file deletion, but that's probably better handled 3588 +// by a special case. 3589 + 3590 +// yaffs_PruneWorker should only be called by yaffs_PruneFileStructure() 3591 + 3592 +static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, __u32 level, int del0) 4639 3593 +{ 4640 3594 + int i; 4641 3595 + int hasData; 4642 + 4643 + if (tn) { 3596 + 3597 + if(tn) 3598 + { 4644 3599 + hasData = 0; 4645 + 4646 + for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) { 4647 + if (tn->internal[i] && level > 0) { 4648 + tn->internal[i] = 4649 + yaffs_PruneWorker(dev, tn->internal[i], 4650 + level - 1, 4651 + (i == 0) ? del0 : 1); 3600 + 3601 + for(i = 0; i < YAFFS_NTNODES_INTERNAL; i++) 3602 + { 3603 + if(tn->internal[i] && level > 0) 3604 + { 3605 + tn->internal[i] = yaffs_PruneWorker(dev,tn->internal[i],level - 1, ( i == 0) ? del0 : 1); 3606 + } 3607 + 3608 + if(tn->internal[i]) 3609 + { 3610 + hasData++; 4652 3611 + } 4653 + 4654 + if (tn->internal[i]) { 4655 + hasData++; 4656 + } 4657 + } 4658 + 4659 + if (hasData == 0 && del0) { 4660 + /* Free and return NULL */ 4661 + 4662 + yaffs_FreeTnode(dev, tn); 3612 + } 3613 + 3614 + if(hasData == 0 && del0) 3615 + { 3616 + // Free and return NULL 3617 + 3618 + yaffs_FreeTnode(dev,tn); 4663 3619 + tn = NULL; 4664 3620 + } 4665 + 3621 + 4666 3622 + } 4667 3623 + 4668 3624 + return tn; 4669 + 4670 +} 4671 + 4672 +static int yaffs_PruneFileStructure(yaffs_Device * dev, 4673 + yaffs_FileStructure * fStruct) 3625 + 3626 +} 3627 + 3628 +static int yaffs_PruneFileStructure(yaffs_Device *dev, yaffs_FileStructure *fStruct) 4674 3629 +{ 4675 3630 + int i; … … 4677 3632 + int done = 0; 4678 3633 + yaffs_Tnode *tn; 4679 + 4680 + if (fStruct->topLevel > 0) {4681 + fStruct->top =4682 + yaffs_PruneWorker(dev, fStruct->top, fStruct->topLevel,0);4683 + 4684 + / *Now we have a tree with all the non-zero branches NULL but the height4685 + *is the same as it was.4686 + *Let's see if we can trim internal tnodes to shorten the tree.4687 + *We can do this if only the 0th element in the tnode is in use4688 + *(ie all the non-zero are NULL)4689 + */4690 + 4691 + while (fStruct->topLevel && !done){3634 + 3635 + if(fStruct->topLevel > 0) 3636 + { 3637 + fStruct->top = yaffs_PruneWorker(dev,fStruct->top, fStruct->topLevel,0); 3638 + 3639 + // Now we have a tree with all the non-zero branches NULL but the height 3640 + // is the same as it was. 3641 + // Let's see if we can trim internal tnodes to shorten the tree. 3642 + // We can do this if only the 0th element in the tnode is in use 3643 + // (ie all the non-zero are NULL) 3644 + 3645 + while(fStruct->topLevel && !done) 3646 + { 4692 3647 + tn = fStruct->top; 4693 + 3648 + 4694 3649 + hasData = 0; 4695 + for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) { 4696 + if (tn->internal[i]) { 4697 + hasData++; 3650 + for(i = 1; i <YAFFS_NTNODES_INTERNAL; i++) 3651 + { 3652 + if(tn->internal[i]) 3653 + { 3654 + hasData++; 4698 3655 + } 4699 3656 + } 4700 + 4701 + if (!hasData) { 3657 + 3658 + if(!hasData) 3659 + { 4702 3660 + fStruct->top = tn->internal[0]; 4703 3661 + fStruct->topLevel--; 4704 + yaffs_FreeTnode(dev, tn); 4705 + } else { 3662 + yaffs_FreeTnode(dev,tn); 3663 + } 3664 + else 3665 + { 4706 3666 + done = 1; 4707 3667 + } 4708 3668 + } 4709 3669 + } 4710 + 3670 + 4711 3671 + return YAFFS_OK; 4712 3672 +} 4713 3673 + 4714 +/*-------------------- End of File Structure functions.-------------------*/ 4715 + 4716 +/* yaffs_CreateFreeObjects creates a bunch more objects and 4717 + * adds them to the object free list. 4718 + */ 4719 +static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects) 4720 +{ 4721 + int i; 4722 + yaffs_Object *newObjects; 4723 + yaffs_ObjectList *list; 4724 + 4725 + if (nObjects < 1) 4726 + return YAFFS_OK; 4727 + 4728 + /* make these things */ 4729 + newObjects = YMALLOC(nObjects * sizeof(yaffs_Object)); 4730 + 4731 + if (!newObjects) { 4732 + T(YAFFS_TRACE_ALLOCATE, 4733 + (TSTR("yaffs: Could not allocate more objects" TENDSTR))); 3674 + 3675 + 3676 + 3677 + 3678 +/////////////////////// End of File Structure functions. ///////////////// 3679 + 3680 +// yaffs_CreateFreeObjects creates a bunch more objects and 3681 +// adds them to the object free list. 3682 +static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects) 3683 +{ 3684 + int i; 3685 + yaffs_Object *newObjects; 3686 + yaffs_ObjectList *list; 3687 + 3688 + if(nObjects < 1) return YAFFS_OK; 3689 + 3690 + // make these things 3691 + 3692 + newObjects = YMALLOC(nObjects * sizeof(yaffs_Object)); 3693 + 3694 + if (!newObjects) 3695 + { 3696 + T(YAFFS_TRACE_ALLOCATE,(TSTR("yaffs: Could not allocate more objects" TENDSTR))); 4734 3697 + return YAFFS_FAIL; 4735 + }4736 + 4737 + /* Hook them into the free list */4738 + for (i = 0; i < nObjects - 1; i++) {4739 + newObjects[i].siblings.next =4740 + (struct list_head *)(&newObjects[i +1]);4741 + }4742 + 3698 + } 3699 + 3700 + // Hook them into the free list 3701 + for(i = 0; i < nObjects - 1; i++) 3702 + { 3703 + newObjects[i].siblings.next = (struct list_head *)(&newObjects[i+1]); 3704 + } 3705 + 4743 3706 + newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects; 4744 3707 + dev->freeObjects = newObjects; 4745 + dev->nFreeObjects += nObjects;4746 + dev->nObjectsCreated += nObjects;4747 + 4748 + / * Now add this bunch of Objects to a list for freeing up. */4749 + 3708 + dev->nFreeObjects+= nObjects; 3709 + dev->nObjectsCreated+= nObjects; 3710 + 3711 + // Now add this bunch of Objects to a list for freeing up. 3712 + 4750 3713 + list = YMALLOC(sizeof(yaffs_ObjectList)); 4751 + if (!list) { 4752 + T(YAFFS_TRACE_ALLOCATE, 4753 + (TSTR("Could not add objects to management list" TENDSTR))); 4754 + } else { 3714 + if(!list) 3715 + { 3716 + T(YAFFS_TRACE_ALLOCATE,(TSTR("Could not add objects to management list" TENDSTR))); 3717 + } 3718 + else 3719 + { 4755 3720 + list->objects = newObjects; 4756 3721 + list->next = dev->allocatedObjectList; 4757 3722 + dev->allocatedObjectList = list; 4758 3723 + } 4759 + 3724 + 3725 + 3726 + 4760 3727 + return YAFFS_OK; 4761 3728 +} 4762 3729 + 4763 3730 + 4764 +/ * AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */4765 +static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)3731 +// AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out 3732 +static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev) 4766 3733 +{ 4767 3734 + yaffs_Object *tn = NULL; 4768 + 4769 + /* If there are none left make more */ 4770 + if (!dev->freeObjects) { 4771 + yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS); 4772 + } 4773 + 4774 + if (dev->freeObjects) { 3735 + 3736 + // If there are none left make more 3737 + if(!dev->freeObjects) 3738 + { 3739 + yaffs_CreateFreeObjects(dev,YAFFS_ALLOCATION_NOBJECTS); 3740 + } 3741 + 3742 + if(dev->freeObjects) 3743 + { 4775 3744 + tn = dev->freeObjects; 4776 + dev->freeObjects = 4777 + (yaffs_Object *) (dev->freeObjects->siblings.next); 3745 + dev->freeObjects = (yaffs_Object *)(dev->freeObjects->siblings.next); 4778 3746 + dev->nFreeObjects--; 4779 + 4780 + / * Now sweeten it up... */4781 + 4782 + memset(tn, 0,sizeof(yaffs_Object));3747 + 3748 + // Now sweeten it up... 3749 + 3750 + memset(tn,0,sizeof(yaffs_Object)); 4783 3751 + tn->myDev = dev; 4784 3752 + tn->chunkId = -1; … … 4787 3755 + INIT_LIST_HEAD(&(tn->hashLink)); 4788 3756 + INIT_LIST_HEAD(&tn->siblings); 4789 + 4790 + /* Add it to the lost and found directory. 4791 + * NB Can't put root or lostNFound in lostNFound so 4792 + * check if lostNFound exists first 4793 + */ 4794 + if (dev->lostNFoundDir) { 4795 + yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn); 4796 + } 4797 + } 3757 + 3758 + // Add it to the lost and found directory. 3759 + // NB Can't put root or lostNFound in lostNFound so 3760 + // check if lostNFound exists first 3761 + if(dev->lostNFoundDir) 3762 + { 3763 + yaffs_AddObjectToDirectory(dev->lostNFoundDir,tn); 3764 + } 3765 + } 3766 + 4798 3767 + 4799 3768 + return tn; 4800 3769 +} 4801 3770 + 4802 +static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number, 4803 + __u32 mode) 4804 +{ 4805 + 4806 + yaffs_Object *obj = 4807 + yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY); 4808 + if (obj) { 4809 + obj->fake = 1; /* it is fake so it has no NAND presence... */ 4810 + obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */ 4811 + obj->unlinkAllowed = 0; /* ... or unlink it */ 3771 +static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev,int number,__u32 mode) 3772 +{ 3773 + 3774 + yaffs_Object *obj = yaffs_CreateNewObject(dev,number,YAFFS_OBJECT_TYPE_DIRECTORY); 3775 + if(obj) 3776 + { 3777 + obj->fake = 1; // it is fake so it has no NAND presence... 3778 + obj->renameAllowed= 0; // ... and we're not allowed to rename it... 3779 + obj->unlinkAllowed= 0; // ... or unlink it 4812 3780 + obj->deleted = 0; 4813 3781 + obj->unlinked = 0; 4814 3782 + obj->yst_mode = mode; 4815 3783 + obj->myDev = dev; 4816 + obj->chunkId = 0; /* Not a valid chunk. */4817 + } 4818 + 3784 + obj->chunkId = 0; // Not a valid chunk. 3785 + } 3786 + 4819 3787 + return obj; 4820 + 4821 +} 4822 + 4823 +static void yaffs_UnhashObject(yaffs_Object * tn) 3788 + 3789 +} 3790 + 3791 + 3792 +static void yaffs_UnhashObject(yaffs_Object *tn) 4824 3793 +{ 4825 3794 + int bucket; 4826 3795 + yaffs_Device *dev = tn->myDev; 4827 + 4828 + /* If it is still linked into the bucket list, free from the list */ 4829 + if (!list_empty(&tn->hashLink)) { 3796 + 3797 + 3798 + // If it is still linked into the bucket list, free from the list 3799 + if(!list_empty(&tn->hashLink)) 3800 + { 4830 3801 + list_del_init(&tn->hashLink); 4831 + bucket = yaffs_HashFunction(tn->objectId);3802 + bucket = yaffs_HashFunction(tn->objectId); 4832 3803 + dev->objectBucket[bucket].count--; 4833 3804 + } 4834 + 4835 +} 4836 + 4837 +/* FreeObject frees up a Object and puts it back on the free list */ 4838 +static void yaffs_FreeObject(yaffs_Object * tn) 3805 + 3806 +} 3807 + 3808 + 3809 +// FreeObject frees up a Object and puts it back on the free list 3810 +static void yaffs_FreeObject(yaffs_Object *tn) 4839 3811 +{ 4840 3812 + 4841 3813 + yaffs_Device *dev = tn->myDev; 4842 + 3814 + 4843 3815 +#ifdef __KERNEL__ 4844 + if (tn->myInode) {4845 + /* We're still hooked up to a cached inode.4846 + * Don't delete now, but mark for later deletion4847 + */3816 + if(tn->myInode) 3817 + { 3818 + // We're still hooked up to a cached inode. 3819 + // Don't delete now, but mark for later deletion 4848 3820 + tn->deferedFree = 1; 4849 3821 + return; 4850 3822 + } 4851 3823 +#endif 4852 + 3824 + 4853 3825 + yaffs_UnhashObject(tn); 4854 + 4855 + / * Link into the free list. */3826 + 3827 + // Link into the free list. 4856 3828 + tn->siblings.next = (struct list_head *)(dev->freeObjects); 4857 3829 + dev->freeObjects = tn; … … 4859 3831 +} 4860 3832 + 3833 + 3834 + 4861 3835 +#ifdef __KERNEL__ 4862 3836 + 4863 +void yaffs_HandleDeferedFree(yaffs_Object * obj) 4864 +{ 4865 + if (obj->deferedFree) { 4866 + yaffs_FreeObject(obj); 4867 + } 4868 +} 4869 + 4870 +#endif 4871 + 4872 +static void yaffs_DeinitialiseObjects(yaffs_Device * dev) 4873 +{ 4874 + /* Free the list of allocated Objects */ 4875 + 3837 +void yaffs_HandleDeferedFree(yaffs_Object *obj) 3838 +{ 3839 + if(obj->deferedFree) 3840 + { 3841 + yaffs_FreeObject(obj); 3842 + } 3843 +} 3844 + 3845 +#endif 3846 + 3847 + 3848 + 3849 +static void yaffs_DeinitialiseObjects(yaffs_Device *dev) 3850 +{ 3851 + // Free the list of allocated Objects 3852 + 4876 3853 + yaffs_ObjectList *tmp; 4877 + 4878 + while (dev->allocatedObjectList) { 4879 + tmp = dev->allocatedObjectList->next; 3854 + 3855 + while( dev->allocatedObjectList) 3856 + { 3857 + tmp = dev->allocatedObjectList->next; 4880 3858 + YFREE(dev->allocatedObjectList->objects); 4881 3859 + YFREE(dev->allocatedObjectList); 4882 + 4883 + dev->allocatedObjectList = tmp;4884 + } 4885 + 3860 + 3861 + dev->allocatedObjectList = tmp; 3862 + } 3863 + 4886 3864 + dev->freeObjects = NULL; 4887 3865 + dev->nFreeObjects = 0; 4888 3866 +} 4889 3867 + 4890 +static void yaffs_InitialiseObjects(yaffs_Device * dev)3868 +static void yaffs_InitialiseObjects(yaffs_Device *dev) 4891 3869 +{ 4892 3870 + int i; 4893 + 3871 + 4894 3872 + dev->allocatedObjectList = NULL; 4895 3873 + dev->freeObjects = NULL; 4896 3874 + dev->nFreeObjects = 0; 4897 + 4898 + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { 3875 + 3876 + for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) 3877 + { 4899 3878 + INIT_LIST_HEAD(&dev->objectBucket[i].list); 4900 + dev->objectBucket[i].count = 0; 4901 + } 4902 + 4903 +} 4904 + 4905 +static int yaffs_FindNiceObjectBucket(yaffs_Device * dev) 3879 + dev->objectBucket[i].count = 0; 3880 + } 3881 + 3882 +} 3883 + 3884 + 3885 + 3886 + 3887 + 3888 + 3889 +static int yaffs_FindNiceObjectBucket(yaffs_Device *dev) 4906 3890 +{ 4907 3891 + static int x = 0; … … 4910 3894 + int lowest = 999999; 4911 3895 + 4912 + /* First let's see if we can find one that's empty. */ 4913 + 4914 + for (i = 0; i < 10 && lowest > 0; i++) { 3896 + 3897 + // First let's see if we can find one that's empty. 3898 + 3899 + for(i = 0; i < 10 && lowest > 0; i++) 3900 + { 4915 3901 + x++; 4916 + x %= YAFFS_NOBJECT_BUCKETS; 4917 + if (dev->objectBucket[x].count < lowest) { 3902 + x %= YAFFS_NOBJECT_BUCKETS; 3903 + if(dev->objectBucket[x].count < lowest) 3904 + { 4918 3905 + lowest = dev->objectBucket[x].count; 4919 3906 + l = x; 4920 3907 + } 4921 + 4922 + } 4923 + 4924 + / *If we didn't find an empty list, then try4925 + *looking a bit further for a short one4926 + */4927 + 4928 + for (i = 0; i < 10 && lowest > 3; i++){3908 + 3909 + } 3910 + 3911 + // If we didn't find an empty list, then try 3912 + // looking a bit further for a short one 3913 + 3914 + for(i = 0; i < 10 && lowest > 3; i++) 3915 + { 4929 3916 + x++; 4930 + x %= YAFFS_NOBJECT_BUCKETS; 4931 + if (dev->objectBucket[x].count < lowest) { 3917 + x %= YAFFS_NOBJECT_BUCKETS; 3918 + if(dev->objectBucket[x].count < lowest) 3919 + { 4932 3920 + lowest = dev->objectBucket[x].count; 4933 3921 + l = x; 4934 3922 + } 4935 + 4936 + } 4937 + 3923 + 3924 + } 3925 + 4938 3926 + return l; 4939 3927 +} 4940 3928 + 4941 +static int yaffs_CreateNewObjectNumber(yaffs_Device * dev)3929 +static int yaffs_CreateNewObjectNumber(yaffs_Device *dev) 4942 3930 +{ 4943 3931 + int bucket = yaffs_FindNiceObjectBucket(dev); 4944 + 4945 + /* Now find an object value that has not already been taken 4946 + * by scanning the list. 4947 + */ 4948 + 3932 + 3933 + // Now find an object value that has not already been taken 3934 + // by scanning the list. 3935 + 4949 3936 + int found = 0; 4950 3937 + struct list_head *i; 4951 + 4952 + __u32 n = (__u32) bucket; 4953 + 4954 + /* yaffs_CheckObjectHashSanity(); */ 4955 + 4956 + while (!found) { 3938 + 3939 + __u32 n = (__u32)bucket; 3940 + 3941 + //yaffs_CheckObjectHashSanity(); 3942 + 3943 + while(!found) 3944 + { 4957 3945 + found = 1; 4958 + n += YAFFS_NOBJECT_BUCKETS; 4959 + if (1 || dev->objectBucket[bucket].count > 0) { 4960 + list_for_each(i, &dev->objectBucket[bucket].list) { 4961 + /* If there is already one in the list */ 4962 + if (i 4963 + && list_entry(i, yaffs_Object, 4964 + hashLink)->objectId == n) { 3946 + n += YAFFS_NOBJECT_BUCKETS; 3947 + if(1 ||dev->objectBucket[bucket].count > 0) 3948 + { 3949 + list_for_each(i,&dev->objectBucket[bucket].list) 3950 + { 3951 + // If there is already one in the list 3952 + if(i && list_entry(i, yaffs_Object,hashLink)->objectId == n) 3953 + { 4965 3954 + found = 0; 4966 3955 + } … … 4968 3957 + } 4969 3958 + } 4970 + 4971 + 4972 + return n; 4973 +} 4974 + 4975 +static void yaffs_HashObject(yaffs_Object * in) 3959 + 3960 + //T(("bucket %d count %d inode %d\n",bucket,yaffs_objectBucket[bucket].count,n); 3961 + 3962 + return n; 3963 +} 3964 + 3965 +static void yaffs_HashObject(yaffs_Object *in) 4976 3966 +{ 4977 3967 + int bucket = yaffs_HashFunction(in->objectId); 4978 3968 + yaffs_Device *dev = in->myDev; 4979 + 4980 + list_add(&in->hashLink, &dev->objectBucket[bucket].list); 3969 + 3970 + if(!list_empty(&in->hashLink)) 3971 + { 3972 + //YINFO("!!!"); 3973 + } 3974 + 3975 + 3976 + list_add(&in->hashLink,&dev->objectBucket[bucket].list); 4981 3977 + dev->objectBucket[bucket].count++; 4982 3978 + 4983 3979 +} 4984 3980 + 4985 +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev,__u32 number)3981 +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number) 4986 3982 +{ 4987 3983 + int bucket = yaffs_HashFunction(number); 4988 3984 + struct list_head *i; 4989 3985 + yaffs_Object *in; 4990 + 4991 + list_for_each(i, &dev->objectBucket[bucket].list) { 4992 + /* Look if it is in the list */ 4993 + if (i) { 4994 + in = list_entry(i, yaffs_Object, hashLink); 4995 + if (in->objectId == number) { 3986 + 3987 + list_for_each(i,&dev->objectBucket[bucket].list) 3988 + { 3989 + // Look if it is in the list 3990 + if(i) 3991 + { 3992 + in = list_entry(i, yaffs_Object,hashLink); 3993 + if(in->objectId == number) 3994 + { 4996 3995 +#ifdef __KERNEL__ 4997 + / * Don't tell the VFS about this one if it is defered free */4998 + if (in->deferedFree)4999 + return NULL;5000 +#endif 5001 + 3996 + // Don't tell the VFS about this one if it is defered free 3997 + if(in->deferedFree) 3998 + return NULL; 3999 +#endif 4000 + 5002 4001 + return in; 5003 4002 + } 5004 4003 + } 5005 4004 + } 5006 + 4005 + 5007 4006 + return NULL; 5008 4007 +} 5009 4008 + 5010 +yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, 5011 + yaffs_ObjectType type) 5012 +{ 5013 + 4009 + 4010 + 4011 +yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type) 4012 +{ 4013 + 5014 4014 + yaffs_Object *theObject; 5015 4015 + 5016 + if (number < 0) { 4016 + if(number < 0) 4017 + { 5017 4018 + number = yaffs_CreateNewObjectNumber(dev); 5018 4019 + } 5019 + 4020 + 5020 4021 + theObject = yaffs_AllocateEmptyObject(dev); 5021 + 5022 + if (theObject) { 4022 + 4023 + if(theObject) 4024 + { 5023 4025 + theObject->fake = 0; 5024 4026 + theObject->renameAllowed = 1; … … 5029 4031 +#ifdef CONFIG_YAFFS_WINCE 5030 4032 + yfsd_WinFileTimeNow(theObject->win_atime); 5031 + theObject->win_ctime[0] = theObject->win_mtime[0] = 5032 + theObject->win_atime[0]; 5033 + theObject->win_ctime[1] = theObject->win_mtime[1] = 5034 + theObject->win_atime[1]; 4033 + theObject->win_ctime[0] = theObject->win_mtime[0] = theObject->win_atime[0]; 4034 + theObject->win_ctime[1] = theObject->win_mtime[1] = theObject->win_atime[1]; 5035 4035 + 5036 4036 +#else 5037 4037 + 5038 + theObject->yst_atime = theObject->yst_mtime = 5039 + theObject->yst_ctime = Y_CURRENT_TIME; 5040 +#endif 5041 + switch (type) { 5042 + case YAFFS_OBJECT_TYPE_FILE: 5043 + theObject->variant.fileVariant.fileSize = 0; 5044 + theObject->variant.fileVariant.scannedFileSize = 0; 5045 + theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */ 5046 + theObject->variant.fileVariant.topLevel = 0; 5047 + theObject->variant.fileVariant.top = 5048 + yaffs_GetTnode(dev); 5049 + break; 5050 + case YAFFS_OBJECT_TYPE_DIRECTORY: 5051 + INIT_LIST_HEAD(&theObject->variant.directoryVariant. 5052 + children); 5053 + break; 5054 + case YAFFS_OBJECT_TYPE_SYMLINK: 5055 + case YAFFS_OBJECT_TYPE_HARDLINK: 5056 + case YAFFS_OBJECT_TYPE_SPECIAL: 5057 + /* No action required */ 5058 + break; 5059 + case YAFFS_OBJECT_TYPE_UNKNOWN: 5060 + /* todo this should not happen */ 5061 + break; 5062 + } 5063 + } 5064 + 4038 + theObject->yst_atime = theObject->yst_mtime = theObject->yst_ctime = Y_CURRENT_TIME; 4039 +#endif 4040 + switch(type) 4041 + { 4042 + case YAFFS_OBJECT_TYPE_FILE: 4043 + theObject->variant.fileVariant.fileSize = 0; 4044 + theObject->variant.fileVariant.scannedFileSize = 0; 4045 + theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; // max __u32 4046 + theObject->variant.fileVariant.topLevel = 0; 4047 + theObject->variant.fileVariant.top = yaffs_GetTnode(dev); 4048 + break; 4049 + case YAFFS_OBJECT_TYPE_DIRECTORY: 4050 + INIT_LIST_HEAD(&theObject->variant.directoryVariant.children); 4051 + break; 4052 + case YAFFS_OBJECT_TYPE_SYMLINK: 4053 + // No action required 4054 + break; 4055 + case YAFFS_OBJECT_TYPE_HARDLINK: 4056 + // No action required 4057 + break; 4058 + case YAFFS_OBJECT_TYPE_SPECIAL: 4059 + // No action required 4060 + break; 4061 + case YAFFS_OBJECT_TYPE_UNKNOWN: 4062 + // todo this should not happen 4063 + break; 4064 + } 4065 + } 4066 + 5065 4067 + return theObject; 5066 4068 +} 5067 4069 + 5068 +static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev, 5069 + int number, 5070 + yaffs_ObjectType type) 4070 +static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int number,yaffs_ObjectType type) 5071 4071 +{ 5072 4072 + yaffs_Object *theObject = NULL; 5073 + 5074 + if (number > 0) { 5075 + theObject = yaffs_FindObjectByNumber(dev, number); 5076 + } 5077 + 5078 + if (!theObject) { 5079 + theObject = yaffs_CreateNewObject(dev, number, type); 5080 + } 5081 + 4073 + 4074 + if(number > 0) 4075 + { 4076 + theObject = yaffs_FindObjectByNumber(dev,number); 4077 + } 4078 + 4079 + if(!theObject) 4080 + { 4081 + theObject = yaffs_CreateNewObject(dev,number,type); 4082 + } 4083 + 5082 4084 + return theObject; 5083 4085 + 5084 4086 +} 5085 + 5086 + 5087 +static YCHAR *yaffs_CloneString(const YCHAR * str) 4087 + 4088 +static YCHAR *yaffs_CloneString(const YCHAR *str) 5088 4089 +{ 5089 4090 + YCHAR *newStr = NULL; 5090 + 5091 + if (str && *str) { 4091 + 4092 + if(str && *str) 4093 + { 5092 4094 + newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR)); 5093 + yaffs_strcpy(newStr, str);4095 + yaffs_strcpy(newStr,str); 5094 4096 + } 5095 4097 + 5096 4098 + return newStr; 5097 + 5098 +} 5099 + 5100 +/* 5101 + * Mknod (create) a new object. 5102 + * equivalentObject only has meaning for a hard link; 5103 + * aliasString only has meaning for a sumlink. 5104 + * rdev only has meaning for devices (a subset of special objects) 5105 + */ 5106 + 5107 +static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, 5108 + yaffs_Object * parent, 5109 + const YCHAR * name, 5110 + __u32 mode, 5111 + __u32 uid, 5112 + __u32 gid, 5113 + yaffs_Object * equivalentObject, 5114 + const YCHAR * aliasString, __u32 rdev) 4099 + 4100 +} 4101 + 4102 +// 4103 +// Mknod (create) a new object. 4104 +// equivalentObject only has meaning for a hard link; 4105 +// aliasString only has meaning for a sumlink. 4106 +// rdev only has meaning for devices (a subset of special objects) 4107 +static yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, 4108 + yaffs_Object *parent, 4109 + const YCHAR *name, 4110 + __u32 mode, 4111 + __u32 uid, 4112 + __u32 gid, 4113 + yaffs_Object *equivalentObject, 4114 + const YCHAR *aliasString, 4115 + __u32 rdev) 5115 4116 +{ 5116 4117 + yaffs_Object *in; 5117 4118 + 5118 4119 + yaffs_Device *dev = parent->myDev; 5119 + 5120 + /* Check if the entry exists. If it does then fail the call since we don't want a dup.*/ 5121 + if (yaffs_FindObjectByName(parent, name)) { 4120 + 4121 + // Check if the entry exists. If it does then fail the call since we don't want a dup. 4122 + if(yaffs_FindObjectByName(parent,name)) 4123 + { 5122 4124 + return NULL; 5123 4125 + } 5124 + 5125 + in = yaffs_CreateNewObject(dev, -1, type); 5126 + 5127 + if (in) { 4126 + 4127 + in = yaffs_CreateNewObject(dev,-1,type); 4128 + 4129 + if(in) 4130 + { 5128 4131 + in->chunkId = -1; 5129 4132 + in->valid = 1; 5130 4133 + in->variantType = type; 5131 4134 + 5132 + in->yst_mode = mode;5133 + 4135 + in->yst_mode = mode; 4136 + 5134 4137 +#ifdef CONFIG_YAFFS_WINCE 5135 4138 + yfsd_WinFileTimeNow(in->win_atime); 5136 4139 + in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0]; 5137 4140 + in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1]; 5138 + 4141 + 5139 4142 +#else 5140 4143 + in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME; 5141 4144 + 5142 + in->yst_rdev = rdev;5143 + in->yst_uid = uid;5144 + in->yst_gid = gid;5145 +#endif 4145 + in->yst_rdev = rdev; 4146 + in->yst_uid = uid; 4147 + in->yst_gid = gid; 4148 +#endif 5146 4149 + in->nDataChunks = 0; 5147 4150 + 5148 + yaffs_SetObjectName(in, name);4151 + yaffs_SetObjectName(in,name); 5149 4152 + in->dirty = 1; 5150 + 5151 + yaffs_AddObjectToDirectory(parent, in);5152 + 4153 + 4154 + yaffs_AddObjectToDirectory(parent,in); 4155 + 5153 4156 + in->myDev = parent->myDev; 5154 + 5155 + switch (type) {5156 + case YAFFS_OBJECT_TYPE_SYMLINK:5157 + in->variant.symLinkVariant.alias =5158 + yaffs_CloneString(aliasString);5159 + break;5160 + case YAFFS_OBJECT_TYPE_HARDLINK:5161 + in->variant.hardLinkVariant.equivalentObject =5162 + equivalentObject;5163 + in->variant.hardLinkVariant.equivalentObjectId =5164 + equivalentObject->objectId;5165 + list_add(&in->hardLinks, &equivalentObject->hardLinks);5166 + break;5167 + case YAFFS_OBJECT_TYPE_FILE:5168 + case YAFFS_OBJECT_TYPE_DIRECTORY:5169 + case YAFFS_OBJECT_TYPE_SPECIAL:5170 + case YAFFS_OBJECT_TYPE_UNKNOWN:5171 + /* do nothing */5172 + break;5173 + }5174 + 5175 + if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0){5176 + / * Could not create the object header, fail the creation */4157 + 4158 + 4159 + switch(type) 4160 + { 4161 + case YAFFS_OBJECT_TYPE_SYMLINK: 4162 + in->variant.symLinkVariant.alias = yaffs_CloneString(aliasString); 4163 + break; 4164 + case YAFFS_OBJECT_TYPE_HARDLINK: 4165 + in->variant.hardLinkVariant.equivalentObject = equivalentObject; 4166 + in->variant.hardLinkVariant.equivalentObjectId = equivalentObject->objectId; 4167 + list_add(&in->hardLinks,&equivalentObject->hardLinks); 4168 + break; 4169 + case YAFFS_OBJECT_TYPE_FILE: // do nothing 4170 + case YAFFS_OBJECT_TYPE_DIRECTORY: // do nothing 4171 + case YAFFS_OBJECT_TYPE_SPECIAL: // do nothing 4172 + case YAFFS_OBJECT_TYPE_UNKNOWN: 4173 + break; 4174 + } 4175 + 4176 + if(/*yaffs_GetNumberOfFreeChunks(dev) <= 0 || */ 4177 + yaffs_UpdateObjectHeader(in,name,0,0,0) < 0) 4178 + { 4179 + // Could not create the object header, fail the creation 5177 4180 + yaffs_DestroyObject(in); 5178 4181 + in = NULL; … … 5180 4183 + 5181 4184 + } 5182 + 4185 + 5183 4186 + return in; 5184 4187 +} 5185 4188 + 5186 +yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, 5187 + __u32 mode, __u32 uid, __u32 gid) 5188 +{ 5189 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE, parent, name, mode, 5190 + uid, gid, NULL, NULL, 0); 5191 +} 5192 + 5193 +yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, 5194 + __u32 mode, __u32 uid, __u32 gid) 5195 +{ 5196 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name, 5197 + mode, uid, gid, NULL, NULL, 0); 5198 +} 5199 + 5200 +yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name, 5201 + __u32 mode, __u32 uid, __u32 gid, __u32 rdev) 5202 +{ 5203 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode, 5204 + uid, gid, NULL, NULL, rdev); 5205 +} 5206 + 5207 +yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, 5208 + __u32 mode, __u32 uid, __u32 gid, 5209 + const YCHAR * alias) 5210 +{ 5211 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode, 5212 + uid, gid, NULL, alias, 0); 5213 +} 5214 + 5215 +/* yaffs_Link returns the object id of the equivalent object.*/ 5216 +yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name, 5217 + yaffs_Object * equivalentObject) 5218 +{ 5219 + /* Get the real object in case we were fed a hard link as an equivalent object */ 4189 +yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid) 4190 +{ 4191 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE,parent,name,mode,uid,gid,NULL,NULL,0); 4192 +} 4193 + 4194 +yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid) 4195 +{ 4196 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY,parent,name,mode,uid,gid,NULL,NULL,0); 4197 +} 4198 + 4199 +yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid, __u32 rdev) 4200 +{ 4201 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL,parent,name,mode,uid,gid,NULL,NULL,rdev); 4202 +} 4203 + 4204 +yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid,const YCHAR *alias) 4205 +{ 4206 + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK,parent,name,mode,uid,gid,NULL,alias,0); 4207 +} 4208 + 4209 +// NB yaffs_Link returns the object id of the equivalent object. 4210 +yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, yaffs_Object *equivalentObject) 4211 +{ 4212 + // Get the real object in case we were fed a hard link as an equivalent object 5220 4213 + equivalentObject = yaffs_GetEquivalentObject(equivalentObject); 5221 + 5222 + if (yaffs_MknodObject 5223 + (YAFFS_OBJECT_TYPE_HARDLINK, parent, name, 0, 0, 0, 5224 + equivalentObject, NULL, 0)) { 4214 + 4215 + if(yaffs_MknodObject(YAFFS_OBJECT_TYPE_HARDLINK,parent,name,0,0,0,equivalentObject,NULL,0)) 4216 + { 5225 4217 + return equivalentObject; 5226 + } else { 4218 + } 4219 + else 4220 + { 5227 4221 + return NULL; 5228 4222 + } 5229 + 5230 +} 5231 + 5232 + static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir,5233 + const YCHAR * newName, int force,int shadows)4223 + 4224 +} 4225 + 4226 + 4227 +static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const YCHAR *newName,int force,int shadows) 5234 4228 +{ 5235 4229 + int unlinkOp; 5236 4230 + int deleteOp; 5237 + 5238 + yaffs_Object *existingTarget; 5239 + 5240 + if (newDir == NULL) { 5241 + newDir = obj->parent; /* use the old directory */ 5242 + } 5243 + 5244 + if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { 5245 + T(YAFFS_TRACE_ALWAYS, 5246 + (TSTR 5247 + ("tragendy: yaffs_ChangeObjectName: newDir is not a directory" 5248 + TENDSTR))); 4231 + 4232 + yaffs_Object * existingTarget; 4233 + 4234 + if(newDir == NULL) 4235 + { 4236 + newDir = obj->parent; // use the old directory 4237 + } 4238 + 4239 + if(newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) 4240 + { 4241 + T(YAFFS_TRACE_ALWAYS,(TSTR("tragendy: yaffs_ChangeObjectName: newDir is not a directory"TENDSTR))); 5249 4242 + YBUG(); 5250 4243 + } 5251 + 5252 + /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */ 5253 + if (obj->myDev->isYaffs2) { 4244 + 4245 + // TODO: Do we need this different handling for YAFFS2 and YAFFS1?? 4246 + if(obj->myDev->isYaffs2) 4247 + { 5254 4248 + unlinkOp = (newDir == obj->myDev->unlinkedDir); 5255 + } else { 5256 + unlinkOp = (newDir == obj->myDev->unlinkedDir 5257 + && obj->variantType == YAFFS_OBJECT_TYPE_FILE); 4249 + } 4250 + else 4251 + { 4252 + unlinkOp = (newDir == obj->myDev->unlinkedDir && obj->variantType == YAFFS_OBJECT_TYPE_FILE); 5258 4253 + } 5259 4254 + 5260 4255 + deleteOp = (newDir == obj->myDev->deletedDir); 5261 + 5262 + existingTarget = yaffs_FindObjectByName(newDir, newName); 5263 + 5264 + /* If the object is a file going into the unlinked directory, 5265 + * then it is OK to just stuff it in since duplicate names are allowed. 5266 + * else only proceed if the new name does not exist and if we're putting 5267 + * it into a directory. 5268 + */ 5269 + if ((unlinkOp || 5270 + deleteOp || 5271 + force || 5272 + (shadows > 0) || 5273 + !existingTarget) && 5274 + newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) { 5275 + yaffs_SetObjectName(obj, newName); 4256 + 4257 + existingTarget = yaffs_FindObjectByName(newDir,newName); 4258 + 4259 + // If the object is a file going into the unlinked directory, then it is OK to just stuff it in since 4260 + // duplicate names are allowed. 4261 + // Otherwise only proceed if the new name does not exist and if we're putting it into a directory. 4262 + if( (unlinkOp|| 4263 + deleteOp || 4264 + force || 4265 + (shadows > 0) || 4266 + !existingTarget) && 4267 + newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) 4268 + { 4269 + yaffs_SetObjectName(obj,newName); 5276 4270 + obj->dirty = 1; 5277 + 5278 + yaffs_AddObjectToDirectory(newDir, obj);5279 + 5280 + if (unlinkOp)5281 + obj->unlinked = 1;5282 + 5283 + /* If it is a deletion then we mark it as a shrink for gc purposes. */5284 + if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 0)4271 + 4272 + yaffs_AddObjectToDirectory(newDir,obj); 4273 + 4274 + if(unlinkOp) obj->unlinked = 1; 4275 + 4276 + // If it is a deletion then we mark it as a shrink for gc purposes. 4277 + if(yaffs_UpdateObjectHeader(obj,newName,0,deleteOp,shadows) >= 0) 4278 + { 5285 4279 + return YAFFS_OK; 5286 + } 5287 + 4280 + } 4281 + } 4282 + 5288 4283 + return YAFFS_FAIL; 5289 4284 +} 5290 4285 + 5291 +int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, 5292 + yaffs_Object * newDir, const YCHAR * newName) 4286 + 4287 + 4288 +int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object *newDir, const YCHAR *newName) 5293 4289 +{ 5294 4290 + yaffs_Object *obj; 5295 4291 + yaffs_Object *existingTarget; 5296 4292 + int force = 0; 5297 + 4293 + 5298 4294 +#ifdef CONFIG_YAFFS_CASE_INSENSITIVE 5299 + / *Special case for case insemsitive systems (eg. WinCE).5300 + *While look-up is case insensitive, the name isn't.5301 + * Therefore we might want to change x.txt to X.txt5302 + */5303 + if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0){4295 + // Special case for case insemsitive systems (eg. WinCE). 4296 + // While look-up is case insensitive, the name isn't. 4297 + // THerefore we might want to change x.txt to X.txt 4298 + if(oldDir == newDir && yaffs_strcmp(oldName,newName) == 0) 4299 + { 5304 4300 + force = 1; 5305 + } 5306 +#endif 5307 + 5308 + obj = yaffs_FindObjectByName(oldDir, oldName); 5309 + /* Check new name to long. */ 5310 + if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK && 5311 + yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH) 5312 + /* ENAMETOOLONG */ 5313 + return YAFFS_FAIL; 5314 + else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK && 5315 + yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) 5316 + /* ENAMETOOLONG */ 5317 + return YAFFS_FAIL; 5318 + 5319 + if (obj && obj->renameAllowed) { 5320 + 5321 + /* Now do the handling for an existing target, if there is one */ 5322 + 5323 + existingTarget = yaffs_FindObjectByName(newDir, newName); 5324 + if (existingTarget && 5325 + existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && 5326 + !list_empty(&existingTarget->variant.directoryVariant.children)) { 5327 + /* There is a target that is a non-empty directory, so we fail */ 5328 + return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */ 5329 + } else if (existingTarget && existingTarget != obj) { 5330 + /* Nuke the target first, using shadowing, 5331 + * but only if it isn't the same object 5332 + */ 5333 + yaffs_ChangeObjectName(obj, newDir, newName, force, 5334 + existingTarget->objectId); 5335 + yaffs_UnlinkObject(existingTarget); 5336 + } 5337 + 5338 + return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0); 4301 + } 4302 +#endif 4303 + 4304 + obj = yaffs_FindObjectByName(oldDir,oldName); 4305 + 4306 + if(obj && obj->renameAllowed) 4307 + { 4308 + 4309 + // Now do the handling for an existing target, if there is one 4310 + 4311 + existingTarget = yaffs_FindObjectByName(newDir,newName); 4312 + if(existingTarget && 4313 + existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && 4314 + !list_empty(&existingTarget->variant.directoryVariant.children)) 4315 + { 4316 + // There is a target that is a non-empty directory, so we have to fail 4317 + return YAFFS_FAIL; // EEXIST or ENOTEMPTY 4318 + } 4319 + else if(existingTarget) 4320 + { 4321 + // Nuke the target first, using shadowing 4322 + yaffs_ChangeObjectName(obj,newDir,newName,force,existingTarget->objectId); 4323 + yaffs_Unlink(newDir,newName); 4324 + } 4325 + 4326 + 4327 + return yaffs_ChangeObjectName(obj,newDir,newName,force,0); 5339 4328 + } 5340 4329 + return YAFFS_FAIL; 5341 4330 +} 5342 4331 + 5343 +/*------------------------- Block Management and Page Allocation ----------------*/ 5344 + 5345 +static int yaffs_InitialiseBlocks(yaffs_Device * dev) 5346 +{ 5347 + int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; 5348 + 5349 + dev->allocationBlock = -1; /* force it to get a new one */ 5350 + 5351 + /* Todo we're assuming the malloc will pass. */ 4332 + 4333 +#if 0 4334 + 4335 +static int yaffs_CheckObjectHashSanity(yaffs_Device *dev) 4336 +{ 4337 + // Scan the buckets and check that the lists 4338 + // have as many members as the count says there are 4339 + int bucket; 4340 + int countEm; 4341 + struct list_head *j; 4342 + int ok = YAFFS_OK; 4343 + 4344 + for(bucket = 0; bucket < YAFFS_NOBJECT_BUCKETS; bucket++) 4345 + { 4346 + countEm = 0; 4347 + 4348 + list_for_each(j,&dev->objectBucket[bucket].list) 4349 + { 4350 + countEm++; 4351 + } 4352 + 4353 + if(countEm != dev->objectBucket[bucket].count) 4354 + { 4355 + T(YAFFS_TRACE_ERROR,(TSTR("Inode hash inconsistency" TENDSTR))); 4356 + ok = YAFFS_FAIL; 4357 + } 4358 + } 4359 + 4360 + return ok; 4361 +} 4362 + 4363 + 4364 +void yaffs_ObjectTest(yaffs_Device *dev) 4365 +{ 4366 + yaffs_Object *in[1000]; 4367 + int inNo[1000]; 4368 + yaffs_Object *inold[1000]; 4369 + int i; 4370 + int j; 4371 + 4372 + memset(in,0,1000*sizeof(yaffs_Object *)); 4373 + memset(inold,0,1000*sizeof(yaffs_Object *)); 4374 + 4375 + yaffs_CheckObjectHashSanity(dev); 4376 + 4377 + for(j = 0; j < 10; j++) 4378 + { 4379 + //T(("%d\n",j)); 4380 + 4381 + for(i = 0; i < 1000; i++) 4382 + { 4383 + in[i] = yaffs_CreateNewObject(dev,-1,YAFFS_OBJECT_TYPE_FILE); 4384 + if(!in[i]) 4385 + { 4386 + YINFO("No more inodes"); 4387 + } 4388 + else 4389 + { 4390 + inNo[i] = in[i]->objectId; 4391 + } 4392 + } 4393 + 4394 + for(i = 0; i < 1000; i++) 4395 + { 4396 + if(yaffs_FindObjectByNumber(dev,inNo[i]) != in[i]) 4397 + { 4398 + //T(("Differnce in look up test\n")); 4399 + } 4400 + else 4401 + { 4402 + // T(("Look up ok\n")); 4403 + } 4404 + } 4405 + 4406 + yaffs_CheckObjectHashSanity(dev); 4407 + 4408 + for(i = 0; i < 1000; i+=3) 4409 + { 4410 + yaffs_FreeObject(in[i]); 4411 + in[i] = NULL; 4412 + } 4413 + 4414 + 4415 + yaffs_CheckObjectHashSanity(dev); 4416 + } 4417 + 4418 +} 4419 + 4420 +#endif 4421 + 4422 +/////////////////////////// Block Management and Page Allocation /////////////////// 4423 + 4424 + 4425 +static int yaffs_InitialiseBlocks(yaffs_Device *dev,int nBlocks) 4426 +{ 4427 + dev->allocationBlock = -1; // force it to get a new one 4428 + //Todo we're assuming the malloc will pass. 5352 4429 + dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); 5353 + if(!dev->blockInfo){ 5354 + dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo)); 5355 + dev->blockInfoAlt = 1; 5356 + } 5357 + else 5358 + dev->blockInfoAlt = 0; 5359 + 5360 + /* Set up dynamic blockinfo stuff. */ 5361 + dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */ 4430 + // Set up dynamic blockinfo stuff. 4431 + dev->chunkBitmapStride = (dev->nChunksPerBlock+7)/8; 5362 4432 + dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); 5363 + if(!dev->chunkBits){ 5364 + dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); 5365 + dev->chunkBitsAlt = 1; 5366 + } 5367 + else 5368 + dev->chunkBitsAlt = 0; 5369 + 5370 + if (dev->blockInfo && dev->chunkBits) { 5371 + memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo)); 5372 + memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks); 4433 + if(dev->blockInfo && dev->chunkBits) 4434 + { 4435 + memset(dev->blockInfo,0,nBlocks * sizeof(yaffs_BlockInfo)); 4436 + memset(dev->chunkBits,0,dev->chunkBitmapStride * nBlocks); 5373 4437 + return YAFFS_OK; 5374 4438 + } 5375 + 4439 + 5376 4440 + return YAFFS_FAIL; 5377 + 5378 +} 5379 + 5380 +static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) 5381 +{ 5382 + if(dev->blockInfoAlt) 5383 + YFREE_ALT(dev->blockInfo); 5384 + else 5385 + YFREE(dev->blockInfo); 5386 + dev->blockInfoAlt = 0; 5387 + 4441 + 4442 +} 4443 + 4444 +static void yaffs_DeinitialiseBlocks(yaffs_Device *dev) 4445 +{ 4446 + YFREE(dev->blockInfo); 5388 4447 + dev->blockInfo = NULL; 5389 + 5390 + if(dev->chunkBitsAlt) 5391 + YFREE_ALT(dev->chunkBits); 5392 + else 5393 + YFREE(dev->chunkBits); 5394 + dev->chunkBitsAlt = 0; 4448 + YFREE(dev->chunkBits); 5395 4449 + dev->chunkBits = NULL; 5396 4450 +} 5397 4451 + 5398 + static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev,5399 + yaffs_BlockInfo *bi)4452 + 4453 +static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, yaffs_BlockInfo *bi) 5400 4454 +{ 5401 4455 + int i; 5402 4456 + __u32 seq; 5403 4457 + yaffs_BlockInfo *b; 5404 + 5405 + if (!dev->isYaffs2) 5406 + return 1; /* disqualification only applies to yaffs2. */ 5407 + 5408 + if (!bi->hasShrinkHeader) 5409 + return 1; /* can gc */ 5410 + 5411 + /* Find the oldest dirty sequence number if we don't know it and save it 5412 + * so we don't have to keep recomputing it. 5413 + */ 5414 + if (!dev->oldestDirtySequence) { 4458 + 4459 + if(!dev->isYaffs2) return 1; // disqualification only applies to yaffs2. 4460 + 4461 + if(!bi->hasShrinkHeader) return 1; // can gc 4462 + 4463 + 4464 + // Find the oldest dirty sequence number if we don't know it and save it 4465 + // so we don't have to keep recomputing it. 4466 + if(!dev->oldestDirtySequence) 4467 + { 5415 4468 + seq = dev->sequenceNumber; 5416 4469 + 5417 + for (i = dev->internalStartBlock; i <= dev->internalEndBlock; 5418 + i++) { 5419 + b = yaffs_GetBlockInfo(dev, i); 5420 + if (b->blockState == YAFFS_BLOCK_STATE_FULL && 5421 + (b->pagesInUse - b->softDeletions) < 5422 + dev->nChunksPerBlock && b->sequenceNumber < seq) { 5423 + seq = b->sequenceNumber; 4470 + for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) 4471 + { 4472 + b = yaffs_GetBlockInfo(dev,i); 4473 + if(b->blockState == YAFFS_BLOCK_STATE_FULL && 4474 + (b->pagesInUse - b->softDeletions )< dev->nChunksPerBlock && 4475 + b->sequenceNumber < seq) 4476 + { 4477 + seq = b->sequenceNumber; 5424 4478 + } 5425 4479 + } … … 5427 4481 + } 5428 4482 + 5429 + /* Can't do gc of this block if there are any blocks older than this one that have5430 + * discarded pages.5431 + */4483 + 4484 + // Can't do gc of this block if there are any blocks older than this one that have 4485 + // discarded pages. 5432 4486 + return (bi->sequenceNumber <= dev->oldestDirtySequence); 5433 + 5434 +} 5435 + 5436 +/* FindDiretiestBlock is used to select the dirtiest block (or close enough) 5437 + * for garbage collection. 5438 + */ 5439 + 5440 +static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev, 5441 + int aggressive) 4487 + 4488 + 4489 + return 1; 4490 + 4491 +} 4492 + 4493 +// FindDiretiestBlock is used to select the dirtiest block (or close enough) 4494 +// for garbage collection. 4495 +// 4496 + 4497 + 4498 + 4499 +static int yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,int aggressive) 5442 4500 +{ 5443 4501 + 5444 4502 + int b = dev->currentDirtyChecker; 5445 + 4503 + 5446 4504 + int i; 5447 4505 + int iterations; 5448 4506 + int dirtiest = -1; 5449 + int pagesInUse; 5450 + int prioritised=0; 4507 + int pagesInUse; 5451 4508 + yaffs_BlockInfo *bi; 5452 + static int nonAggressiveSkip = 0; 5453 + int pendingPrioritisedExist = 0; 5454 + 5455 + /* First let's see if we need to grab a prioritised block */ 5456 + if(dev->hasPendingPrioritisedGCs){ 5457 + for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){ 5458 + 5459 + bi = yaffs_GetBlockInfo(dev, i); 5460 + if(bi->gcPrioritise) { 5461 + pendingPrioritisedExist = 1; 5462 + if(bi->blockState == YAFFS_BLOCK_STATE_FULL && 5463 + yaffs_BlockNotDisqualifiedFromGC(dev, bi)){ 5464 + pagesInUse = (bi->pagesInUse - bi->softDeletions); 5465 + dirtiest = i; 5466 + prioritised = 1; 5467 + aggressive = 1; /* Fool the non-aggressive skip logiv below */ 5468 + } 5469 + } 5470 + } 5471 + 5472 + if(!pendingPrioritisedExist) /* None found, so we can clear this */ 5473 + dev->hasPendingPrioritisedGCs = 0; 5474 + } 5475 + 5476 + /* If we're doing aggressive GC then we are happy to take a less-dirty block, and 5477 + * search harder. 5478 + * else (we're doing a leasurely gc), then we only bother to do this if the 5479 + * block has only a few pages in use. 5480 + */ 4509 + static int nonAggressiveSkip = 0; 4510 + 4511 + // If we're doing aggressive GC then we are happy to take a less-dirty block, and 4512 + // search harder. 4513 + // else (we're doing a leasurely gc), then we only bother to do this if the 4514 + // block has only a few pages in use. 4515 + 5481 4516 + 5482 4517 + nonAggressiveSkip--; 5483 4518 + 5484 + if (!aggressive && (nonAggressiveSkip > 0)) { 4519 + if(!aggressive &&(nonAggressiveSkip > 0)) 4520 + { 5485 4521 + return -1; 5486 4522 + } 5487 4523 + 5488 + if(!prioritised)5489 + pagesInUse =5490 + (aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;5491 + 5492 + if (aggressive) {5493 + iterations =5494 + dev->internalEndBlock - dev->internalStartBlock + 1;5495 + } else{5496 + iterations = 5497 + dev->internalEndBlock - dev->internalStartBlock + 1;5498 + i terations = iterations / 16;5499 + if (iterations > 200){4524 + pagesInUse = (aggressive)? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; 4525 + 4526 + if(aggressive) 4527 + { 4528 + iterations = dev->internalEndBlock - dev->internalStartBlock + 1; 4529 + } 4530 + else 4531 + { 4532 + iterations = dev->internalEndBlock - dev->internalStartBlock + 1; 4533 + iterations = iterations / 16; 4534 + if(iterations > 200) 4535 + { 5500 4536 + iterations = 200; 5501 4537 + } 5502 4538 + } 5503 + 5504 + for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) { 4539 + 4540 + for(i = 0; i <= iterations && pagesInUse > 0 ; i++) 4541 + { 5505 4542 + b++; 5506 + if (b < dev->internalStartBlock || b > dev->internalEndBlock) { 5507 + b = dev->internalStartBlock; 5508 + } 5509 + 5510 + if (b < dev->internalStartBlock || b > dev->internalEndBlock) { 5511 + T(YAFFS_TRACE_ERROR, 5512 + (TSTR("**>> Block %d is not valid" TENDSTR), b)); 4543 + if ( b < dev->internalStartBlock || b > dev->internalEndBlock) 4544 + { 4545 + b = dev->internalStartBlock; 4546 + } 4547 + 4548 + if(b < dev->internalStartBlock || b > dev->internalEndBlock) 4549 + { 4550 + T(YAFFS_TRACE_ERROR,(TSTR("**>> Block %d is not valid" TENDSTR),b)); 5513 4551 + YBUG(); 5514 4552 + } 5515 + 5516 + bi = yaffs_GetBlockInfo(dev, b); 5517 + 5518 +#if 0 5519 + if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) { 5520 + dirtiest = b; 5521 + pagesInUse = 0; 5522 + } 5523 + else 5524 +#endif 5525 + 5526 + if (bi->blockState == YAFFS_BLOCK_STATE_FULL && 5527 + (bi->pagesInUse - bi->softDeletions) < pagesInUse && 5528 + yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { 4553 + 4554 + bi = yaffs_GetBlockInfo(dev,b); 4555 + 4556 + if(bi->blockState == YAFFS_BLOCK_STATE_FULL && 4557 + (bi->pagesInUse - bi->softDeletions )< pagesInUse && 4558 + yaffs_BlockNotDisqualifiedFromGC(dev,bi)) 4559 + { 5529 4560 + dirtiest = b; 5530 4561 + pagesInUse = (bi->pagesInUse - bi->softDeletions); 5531 4562 + } 5532 4563 + } 5533 + 4564 + 5534 4565 + dev->currentDirtyChecker = b; 5535 + 5536 + if (dirtiest > 0) {5537 + T(YAFFS_TRACE_GC,5538 + (TSTR("GC Selected block %d with %d free, prioritised:%d" TENDSTR), dirtiest,5539 + dev->nChunksPerBlock - pagesInUse,prioritised));5540 + }5541 + 5542 + dev->oldestDirtySequence = 0;5543 + 5544 + if (dirtiest > 0){4566 + 4567 + if(dirtiest > 0) 4568 + { 4569 + T(YAFFS_TRACE_GC,(TSTR("GC Selected block %d with %d free" TENDSTR),dirtiest,dev->nChunksPerBlock - pagesInUse)); 4570 + } 4571 + 4572 + dev->oldestDirtySequence = 0; // clear this 4573 + 4574 + if(dirtiest > 0) 4575 + { 5545 4576 + nonAggressiveSkip = 4; 5546 4577 + } … … 5549 4580 +} 5550 4581 + 5551 +static void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo) 5552 +{ 5553 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockNo); 5554 + 4582 + 4583 +static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo) 4584 +{ 4585 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,blockNo); 4586 + 5555 4587 + int erasedOk = 0; 5556 + 5557 + /* If the block is still healthy erase it and mark as clean. 5558 + * If the block has had a data failure, then retire it. 5559 + */ 5560 + 5561 + T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE, 5562 + (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR), 5563 + blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : "")); 5564 + 4588 + 4589 + // If the block is still healthy erase it and mark as clean. 4590 + // If the block has had a data failure, then retire it. 5565 4591 + bi->blockState = YAFFS_BLOCK_STATE_DIRTY; 5566 4592 + 5567 + if (!bi->needsRetiring) { 5568 + yaffs_InvalidateCheckpoint(dev); 5569 + erasedOk = yaffs_EraseBlockInNAND(dev, blockNo); 5570 + if (!erasedOk) { 4593 + if(!bi->needsRetiring) 4594 + { 4595 + erasedOk = yaffs_EraseBlockInNAND(dev,blockNo); 4596 + if(!erasedOk) 4597 + { 5571 4598 + dev->nErasureFailures++; 5572 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, 5573 + (TSTR("**>> Erasure failed %d" TENDSTR), blockNo)); 5574 + } 5575 + } 5576 + 5577 + if (erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE)) { 5578 + int i; 5579 + for (i = 0; i < dev->nChunksPerBlock; i++) { 5580 + if (!yaffs_CheckChunkErased 5581 + (dev, blockNo * dev->nChunksPerBlock + i)) { 5582 + T(YAFFS_TRACE_ERROR, 5583 + (TSTR 5584 + (">>Block %d erasure supposedly OK, but chunk %d not erased" 5585 + TENDSTR), blockNo, i)); 4599 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Erasure failed %d" TENDSTR),blockNo)); 4600 + } 4601 + } 4602 + 4603 + if(erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE)) 4604 + { 4605 + int i; 4606 + for(i = 0; i < dev->nChunksPerBlock; i++) 4607 + { 4608 + if(!yaffs_CheckChunkErased(dev,blockNo * dev->nChunksPerBlock + i)) 4609 + { 4610 + T(YAFFS_TRACE_ERROR,(TSTR(">>Block %d erasure supposedly OK, but chunk %d not erased" TENDSTR),blockNo,i)); 4611 + } 5586 4612 + } 5587 + }5588 + }5589 + 5590 + if (erasedOk){5591 + / * Clean it up... */4613 + } 4614 + 4615 + if( erasedOk ) 4616 + { 4617 + // Clean it up... 5592 4618 + bi->blockState = YAFFS_BLOCK_STATE_EMPTY; 5593 4619 + dev->nErasedBlocks++; 5594 4620 + bi->pagesInUse = 0; 5595 4621 + bi->softDeletions = 0; 5596 + bi->hasShrinkHeader = 0; 5597 + bi->skipErasedCheck = 1; /* This is clean, so no need to check */ 5598 + bi->gcPrioritise = 0; 5599 + yaffs_ClearChunkBits(dev, blockNo); 5600 + 5601 + T(YAFFS_TRACE_ERASE, 5602 + (TSTR("Erased block %d" TENDSTR), blockNo)); 5603 + } else { 5604 + dev->nFreeChunks -= dev->nChunksPerBlock; /* We lost a block of free space */ 5605 + 5606 + yaffs_RetireBlock(dev, blockNo); 5607 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, 5608 + (TSTR("**>> Block %d retired" TENDSTR), blockNo)); 5609 + } 5610 +} 5611 + 5612 +static int yaffs_FindBlockForAllocation(yaffs_Device * dev) 4622 + bi->hasShrinkHeader=0; 4623 + yaffs_ClearChunkBits(dev,blockNo); 4624 + 4625 + T(YAFFS_TRACE_ERASE,(TSTR("Erased block %d" TENDSTR),blockNo)); 4626 + } 4627 + else 4628 + { 4629 + dev->nFreeChunks -= dev->nChunksPerBlock; // We lost a block of free space 4630 + 4631 + yaffs_RetireBlock(dev,blockNo); 4632 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Block %d retired" TENDSTR),blockNo)); 4633 + } 4634 +} 4635 + 4636 +#if 0 4637 +static void yaffs_DumpBlockStats(yaffs_Device *dev) 4638 +{ 4639 + int i,j; 4640 + yaffs_BlockInfo *bi; 4641 + 4642 + for(i= dev->internalStartBlock; i <=dev->internalEndBlock; i++) 4643 + { 4644 + bi = yaffs_GetBlockInfo(dev,i); 4645 + T(YAFFS_TRACE_ALLOCATE,(TSTR("%3d state %d shrink %d inuse %d/%d seq %d pages"),i, 4646 + bi->blockState,bi->hasShrinkHeader,bi->pagesInUse,bi->softDeletions,bi->sequenceNumber)); 4647 + 4648 + for(j = 0; j < dev->nChunksPerBlock; j++) 4649 + { 4650 + if(yaffs_CheckChunkBit(dev,i,j)) 4651 + { 4652 + T(YAFFS_TRACE_ALLOCATE,(TSTR(" %d"),j)); 4653 + 4654 + } 4655 + } 4656 + T(YAFFS_TRACE_ALLOCATE,(TSTR(" " TENDSTR))); 4657 + 4658 + } 4659 +} 4660 +#endif 4661 + 4662 + 4663 +static int yaffs_FindBlockForAllocation(yaffs_Device *dev) 5613 4664 +{ 5614 4665 + int i; 5615 + 4666 + 5616 4667 + yaffs_BlockInfo *bi; 5617 + 5618 + if (dev->nErasedBlocks < 1) { 5619 + /* Hoosterman we've got a problem. 5620 + * Can't get space to gc 5621 + */ 5622 + T(YAFFS_TRACE_ERROR, 5623 + (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR))); 4668 + 4669 +#if 0 4670 + static int j = 0; 4671 + j++; 4672 + if(j < 0 || j > 100) 4673 + { 4674 + j = 0; 4675 + yaffs_DumpBlockStats(dev); 4676 + } 4677 + 4678 +#endif 4679 + 4680 + if(dev->nErasedBlocks < 1) 4681 + { 4682 + // Hoosterman we've got a problem. 4683 + // Can't get space to gc 4684 + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR))); 5624 4685 + 5625 4686 + return -1; 5626 4687 + } 5627 4688 + 5628 + /* Find an empty block. */ 5629 + 5630 + for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { 4689 + // Find an empty block. 4690 + 4691 + for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) 4692 + { 5631 4693 + dev->allocationBlockFinder++; 5632 + if (dev->allocationBlockFinder < dev->internalStartBlock5633 + || dev->allocationBlockFinder > dev->internalEndBlock){4694 + if(dev->allocationBlockFinder < dev->internalStartBlock || dev->allocationBlockFinder> dev->internalEndBlock) 4695 + { 5634 4696 + dev->allocationBlockFinder = dev->internalStartBlock; 5635 4697 + } 5636 + 5637 + bi = yaffs_GetBlockInfo(dev, dev->allocationBlockFinder); 5638 + 5639 + if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) { 4698 + 4699 + bi = yaffs_GetBlockInfo(dev,dev->allocationBlockFinder); 4700 + 4701 + if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY) 4702 + { 5640 4703 + bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING; 5641 4704 + dev->sequenceNumber++; 5642 4705 + bi->sequenceNumber = dev->sequenceNumber; 5643 + dev->nErasedBlocks--; 5644 + T(YAFFS_TRACE_ALLOCATE, 5645 + (TSTR("Allocated block %d, seq %d, %d left" TENDSTR), 5646 + dev->allocationBlockFinder, dev->sequenceNumber, 5647 + dev->nErasedBlocks)); 4706 + dev->nErasedBlocks--; 4707 + T(YAFFS_TRACE_ALLOCATE,(TSTR("Allocated block %d, seq %d, %d left" TENDSTR),dev->allocationBlockFinder,dev->sequenceNumber, dev->nErasedBlocks)); 5648 4708 + return dev->allocationBlockFinder; 5649 4709 + } 5650 4710 + } 5651 + 5652 + T(YAFFS_TRACE_ALWAYS, 5653 + (TSTR 5654 + ("yaffs tragedy: no more eraased blocks, but there should have been %d" 5655 + TENDSTR), dev->nErasedBlocks)); 5656 + 5657 + return -1; 5658 +} 5659 + 5660 + 5661 +// Check if there's space to allocate... 5662 +// Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()? 5663 +static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev) 5664 +{ 5665 + int reservedChunks; 5666 + int reservedBlocks = dev->nReservedBlocks; 5667 + int checkpointBlocks; 5668 + 5669 + checkpointBlocks = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; 5670 + if(checkpointBlocks < 0) 5671 + checkpointBlocks = 0; 5672 + 5673 + reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock); 5674 + 4711 + 4712 + 4713 + T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs tragedy: no more eraased blocks, but there should have been %d" TENDSTR),dev->nErasedBlocks)); 4714 + 4715 + 4716 + 4717 + 4718 + 4719 + return -1; 4720 +} 4721 + 4722 + 4723 +// To determine if we have enough space we just look at the 4724 +// number of erased blocks. 4725 + 4726 +static int yaffs_CheckSpaceForAllocation(yaffs_Device *dev) 4727 +{ 4728 + int reservedChunks = (dev->nReservedBlocks * dev->nChunksPerBlock); 5675 4729 + return (dev->nFreeChunks > reservedChunks); 5676 4730 +} 5677 4731 + 5678 +static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr) 4732 + 4733 +static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve) 5679 4734 +{ 5680 4735 + int retVal; 5681 4736 + yaffs_BlockInfo *bi; 5682 + 5683 + if (dev->allocationBlock < 0) { 5684 + /* Get next block to allocate off */ 4737 + 4738 + if(dev->allocationBlock < 0) 4739 + { 4740 + // Get next block to allocate off 5685 4741 + dev->allocationBlock = yaffs_FindBlockForAllocation(dev); 5686 4742 + dev->allocationPage = 0; 5687 4743 + } 5688 + 5689 + if (!useReserve && !yaffs_CheckSpaceForAllocation(dev)) { 5690 + /* Not enough space to allocate unless we're allowed to use the reserve. */ 4744 + 4745 + if(!useReserve && !yaffs_CheckSpaceForAllocation(dev)) 4746 + { 4747 + // Not enough space to allocate unless we're allowed to use the reserve. 5691 4748 + return -1; 5692 4749 + } 5693 4750 + 5694 + if (dev->nErasedBlocks < dev->nReservedBlocks 5695 + && dev->allocationPage == 0) { 5696 + T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR))); 5697 + } 5698 + 5699 + /* Next page please.... */ 5700 + if (dev->allocationBlock >= 0) { 5701 + bi = yaffs_GetBlockInfo(dev, dev->allocationBlock); 5702 + 5703 + retVal = (dev->allocationBlock * dev->nChunksPerBlock) + 5704 + dev->allocationPage; 4751 + if(dev->nErasedBlocks < dev->nReservedBlocks && dev->allocationPage == 0) 4752 + { 4753 + T(YAFFS_TRACE_ALLOCATE,(TSTR("Allocating reserve" TENDSTR))); 4754 + } 4755 + 4756 + 4757 + // Next page please.... 4758 + if(dev->allocationBlock >= 0) 4759 + { 4760 + bi = yaffs_GetBlockInfo(dev,dev->allocationBlock); 4761 + 4762 + retVal = (dev->allocationBlock * dev->nChunksPerBlock) + 4763 + dev->allocationPage; 5705 4764 + bi->pagesInUse++; 5706 + yaffs_SetChunkBit(dev, dev->allocationBlock, 5707 + dev->allocationPage); 4765 + yaffs_SetChunkBit(dev,dev->allocationBlock,dev->allocationPage); 5708 4766 + 5709 4767 + dev->allocationPage++; 5710 + 4768 + 5711 4769 + dev->nFreeChunks--; 5712 + 5713 + /* If the block is full set the state to full */ 5714 + if (dev->allocationPage >= dev->nChunksPerBlock) { 4770 + 4771 + // If the block is full set the state to full 4772 + if(dev->allocationPage >= dev->nChunksPerBlock) 4773 + { 5715 4774 + bi->blockState = YAFFS_BLOCK_STATE_FULL; 5716 4775 + dev->allocationBlock = -1; 5717 4776 + } 5718 4777 + 5719 + if(blockUsedPtr) 5720 + *blockUsedPtr = bi; 5721 + 4778 + 5722 4779 + return retVal; 5723 + } 5724 + 5725 + T(YAFFS_TRACE_ERROR, 5726 + (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR))); 5727 + 5728 + return -1; 5729 +} 5730 + 5731 +static int yaffs_GetErasedChunks(yaffs_Device * dev) 5732 +{ 5733 + int n; 5734 + 5735 + n = dev->nErasedBlocks * dev->nChunksPerBlock; 5736 + 5737 + if (dev->allocationBlock > 0) { 5738 + n += (dev->nChunksPerBlock - dev->allocationPage); 5739 + } 5740 + 5741 + return n; 5742 + 5743 +} 5744 + 5745 +static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) 4780 + 4781 + } 4782 + T(YAFFS_TRACE_ERROR,(TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR))); 4783 + 4784 + return -1; 4785 +} 4786 + 4787 + 4788 + 4789 + 4790 +static int yaffs_GetErasedChunks(yaffs_Device *dev) 4791 +{ 4792 + int n; 4793 + 4794 + n = dev->nErasedBlocks * dev->nChunksPerBlock; 4795 + 4796 + if(dev->allocationBlock> 0) 4797 + { 4798 + n += (dev->nChunksPerBlock - dev->allocationPage); 4799 + } 4800 + 4801 + return n; 4802 + 4803 +} 4804 + 4805 +static int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block) 5746 4806 +{ 5747 4807 + int oldChunk; … … 5752 4812 + int cleanups = 0; 5753 4813 + int i; 5754 + int isCheckpointBlock;5755 4814 + 5756 4815 + int chunksBefore = yaffs_GetErasedChunks(dev); 5757 4816 + int chunksAfter; 5758 4817 + 5759 + yaffs_ExtendedTags tags;5760 + 5761 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, block);5762 + 4818 + yaffs_ExtendedTags tags; 4819 + 4820 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,block); 4821 + 5763 4822 + yaffs_Object *object; 5764 +5765 + isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);5766 4823 + 5767 4824 + bi->blockState = YAFFS_BLOCK_STATE_COLLECTING; 5768 4825 + 5769 + T(YAFFS_TRACE_TRACING, 5770 + (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block, 5771 + bi->pagesInUse, bi->hasShrinkHeader)); 5772 + 5773 + /*yaffs_VerifyFreeChunks(dev); */ 5774 + 5775 + bi->hasShrinkHeader = 0; /* clear the flag so that the block can erase */ 5776 + 5777 + /* Take off the number of soft deleted entries because 5778 + * they're going to get really deleted during GC. 5779 + */ 5780 + dev->nFreeChunks -= bi->softDeletions; 4826 + T(YAFFS_TRACE_TRACING,(TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR),block,bi->pagesInUse,bi->hasShrinkHeader)); 4827 + //T(("Collecting block %d n %d bits %x\n",block, bi->pagesInUse, bi->pageBits)); 4828 + 4829 + //yaffs_VerifyFreeChunks(dev); 4830 + 4831 + bi->hasShrinkHeader = 0; // clear the flag so that the block can erase 4832 + 4833 + dev->nFreeChunks -= bi->softDeletions; // Take off the number of soft deleted entries because 4834 + // they're going to get really deleted during GC. 5781 4835 + 5782 4836 + dev->isDoingGC = 1; 5783 4837 + 5784 + if (isCheckpointBlock || 5785 + !yaffs_StillSomeChunkBits(dev, block)) { 5786 + T(YAFFS_TRACE_TRACING, 5787 + (TSTR 5788 + ("Collecting block %d that has no chunks in use" TENDSTR), 5789 + block)); 5790 + yaffs_BlockBecameDirty(dev, block); 5791 + } else { 5792 + 5793 + __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); 5794 + 5795 + for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock; 5796 + chunkInBlock < dev->nChunksPerBlock 5797 + && yaffs_StillSomeChunkBits(dev, block); 5798 + chunkInBlock++, oldChunk++) { 5799 + if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) { 5800 + 5801 + /* This page is in use and might need to be copied off */ 5802 + 5803 + markNAND = 1; 5804 + 5805 + yaffs_InitialiseTags(&tags); 5806 + 5807 + yaffs_ReadChunkWithTagsFromNAND(dev, oldChunk, 5808 + buffer, &tags); 5809 + 5810 + object = 5811 + yaffs_FindObjectByNumber(dev, 5812 + tags.objectId); 5813 + 5814 + T(YAFFS_TRACE_GC_DETAIL, 5815 + (TSTR 5816 + ("Collecting page %d, %d %d %d " TENDSTR), 5817 + chunkInBlock, tags.objectId, tags.chunkId, 5818 + tags.byteCount)); 5819 + 5820 + if (!object) { 5821 + T(YAFFS_TRACE_ERROR, 5822 + (TSTR 5823 + ("page %d in gc has no object " 5824 + TENDSTR), oldChunk)); 4838 + if(!yaffs_StillSomeChunkBits(dev,block)) 4839 + { 4840 + T(YAFFS_TRACE_TRACING,(TSTR("Collecting block %d that has no chunks in use" TENDSTR),block)); 4841 + yaffs_BlockBecameDirty(dev,block); 4842 + } 4843 + else 4844 + { 4845 + 4846 + __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); 4847 + 4848 + for(chunkInBlock = 0,oldChunk = block * dev->nChunksPerBlock; 4849 + chunkInBlock < dev->nChunksPerBlock && yaffs_StillSomeChunkBits(dev,block); 4850 + chunkInBlock++, oldChunk++ ) 4851 + { 4852 + if(yaffs_CheckChunkBit(dev,block,chunkInBlock)) 4853 + { 4854 + 4855 + // This page is in use and might need to be copied off 4856 + 4857 + markNAND = 1; 4858 + 4859 + //T(("copying page %x from %d to %d\n",mask,oldChunk,newChunk)); 4860 + 4861 + yaffs_InitialiseTags(&tags); 4862 + 4863 + yaffs_ReadChunkWithTagsFromNAND(dev,oldChunk,buffer, &tags); 4864 + 4865 + object = yaffs_FindObjectByNumber(dev,tags.objectId); 4866 + 4867 + T(YAFFS_TRACE_GC_DETAIL,(TSTR("Collecting page %d, %d %d %d " TENDSTR),chunkInBlock,tags.objectId,tags.chunkId,tags.byteCount)); 4868 + 4869 + if(!object) 4870 + { 4871 + T(YAFFS_TRACE_ERROR,(TSTR("page %d in gc has no object " TENDSTR),oldChunk)); 4872 + } 4873 + 4874 + if(object && object->deleted && tags.chunkId != 0) 4875 + { 4876 + // Data chunk in a deleted file, throw it away 4877 + // It's a soft deleted data chunk, 4878 + // No need to copy this, just forget about it and fix up the 4879 + // object. 4880 + 4881 + //yaffs_PutChunkIntoFile(object, tags.chunkId, 0,0); 4882 + object->nDataChunks--; 4883 + 4884 + if(object->nDataChunks <= 0) 4885 + { 4886 + // remeber to clean up the object 4887 + dev->gcCleanupList[cleanups] = tags.objectId; 4888 + cleanups++; 4889 + } 4890 + markNAND = 0; 4891 + } 4892 + else if( 0 /* Todo object && object->deleted && object->nDataChunks == 0 */) 4893 + { 4894 + // Deleted object header with no data chunks. 4895 + // Can be discarded and the file deleted. 4896 + object->chunkId = 0; 4897 + yaffs_FreeTnode(object->myDev,object->variant.fileVariant.top); 4898 + object->variant.fileVariant.top = NULL; 4899 + yaffs_DoGenericObjectDeletion(object); 4900 + 4901 + } 4902 + else if(object) 4903 + { 4904 + // It's either a data chunk in a live file or 4905 + // an ObjectHeader, so we're interested in it. 4906 + // NB Need to keep the ObjectHeaders of deleted files 4907 + // until the whole file has been deleted off 4908 + tags.serialNumber++; 4909 + 4910 + dev->nGCCopies++; 4911 + 4912 + if(tags.chunkId == 0) 4913 + { 4914 + // It is an object Id, 4915 + // We need to nuke the shrinkheader flags first 4916 + // We no longer want the shrinkHeader flag since its work is done 4917 + // and if it is left in place it will mess up scanning. 4918 + 4919 + yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)buffer; 4920 + oh->isShrink = 0; 4921 + tags.extraIsShrinkHeader = 0; 5825 4922 + } 5826 4923 + 5827 + if (object && object->deleted 5828 + && tags.chunkId != 0) { 5829 + /* Data chunk in a deleted file, throw it away 5830 + * It's a soft deleted data chunk, 5831 + * No need to copy this, just forget about it and 5832 + * fix up the object. 5833 + */ 5834 + 5835 + object->nDataChunks--; 5836 + 5837 + if (object->nDataChunks <= 0) { 5838 + /* remeber to clean up the object */ 5839 + dev->gcCleanupList[cleanups] = 5840 + tags.objectId; 5841 + cleanups++; 4924 + newChunk = yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags,1); 4925 + 4926 + if(newChunk < 0) 4927 + { 4928 + retVal = YAFFS_FAIL; 4929 + } 4930 + else 4931 + { 4932 + 4933 + // Ok, now fix up the Tnodes etc. 4934 + 4935 + if(tags.chunkId == 0) 4936 + { 4937 + // It's a header 4938 + object->chunkId = newChunk; 4939 + object->serial = tags.serialNumber; 5842 4940 + } 5843 + markNAND = 0; 5844 + } else if (0 5845 + /* Todo object && object->deleted && object->nDataChunks == 0 */ 5846 + ) { 5847 + /* Deleted object header with no data chunks. 5848 + * Can be discarded and the file deleted. 5849 + */ 5850 + object->chunkId = 0; 5851 + yaffs_FreeTnode(object->myDev, 5852 + object->variant. 5853 + fileVariant.top); 5854 + object->variant.fileVariant.top = NULL; 5855 + yaffs_DoGenericObjectDeletion(object); 5856 + 5857 + } else if (object) { 5858 + /* It's either a data chunk in a live file or 5859 + * an ObjectHeader, so we're interested in it. 5860 + * NB Need to keep the ObjectHeaders of deleted files 5861 + * until the whole file has been deleted off 5862 + */ 5863 + tags.serialNumber++; 5864 + 5865 + dev->nGCCopies++; 5866 + 5867 + if (tags.chunkId == 0) { 5868 + /* It is an object Id, 5869 + * We need to nuke the shrinkheader flags first 5870 + * We no longer want the shrinkHeader flag since its work is done 5871 + * and if it is left in place it will mess up scanning. 5872 + * Also, clear out any shadowing stuff 5873 + */ 5874 + 5875 + yaffs_ObjectHeader *oh; 5876 + oh = (yaffs_ObjectHeader *)buffer; 5877 + oh->isShrink = 0; 5878 + oh->shadowsObject = -1; 5879 + tags.extraShadows = 0; 5880 + tags.extraIsShrinkHeader = 0; 5881 + } 5882 + 5883 + newChunk = 5884 + yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags, 1); 5885 + 5886 + if (newChunk < 0) { 5887 + retVal = YAFFS_FAIL; 5888 + } else { 5889 + 5890 + /* Ok, now fix up the Tnodes etc. */ 5891 + 5892 + if (tags.chunkId == 0) { 5893 + /* It's a header */ 5894 + object->chunkId = newChunk; 5895 + object->serial = tags.serialNumber; 5896 + } else { 5897 + /* It's a data chunk */ 5898 + yaffs_PutChunkIntoFile 5899 + (object, 5900 + tags.chunkId, 5901 + newChunk, 0); 5902 + } 4941 + else 4942 + { 4943 + // It's a data chunk 4944 + yaffs_PutChunkIntoFile(object, tags.chunkId, newChunk,0); 5903 4945 + } 5904 4946 + } 5905 +5906 + yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);5907 +5908 4947 + } 5909 + } 5910 + 5911 + yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); 5912 + 5913 + 5914 + /* Do any required cleanups */ 5915 + for (i = 0; i < cleanups; i++) { 5916 + /* Time to delete the file too */ 5917 + object = 5918 + yaffs_FindObjectByNumber(dev, 5919 + dev->gcCleanupList[i]); 5920 + if (object) { 5921 + yaffs_FreeTnode(dev, 5922 + object->variant.fileVariant. 5923 + top); 5924 + object->variant.fileVariant.top = NULL; 5925 + T(YAFFS_TRACE_GC, 5926 + (TSTR 5927 + ("yaffs: About to finally delete object %d" 5928 + TENDSTR), object->objectId)); 5929 + yaffs_DoGenericObjectDeletion(object); 5930 + object->myDev->nDeletedFiles--; 4948 + 4949 + yaffs_DeleteChunk(dev,oldChunk,markNAND,__LINE__); 4950 + 4951 + } 4952 + } 4953 + 4954 + yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); 4955 + 4956 + //yaffs_VerifyFreeChunks(dev); 4957 + 4958 + // Do any required cleanups 4959 + for(i = 0; i < cleanups; i++) 4960 + { 4961 + // Time to delete the file too 4962 + object = yaffs_FindObjectByNumber(dev,dev->gcCleanupList[i]); 4963 + if(object) 4964 + { 4965 + yaffs_FreeTnode(dev,object->variant.fileVariant.top); 4966 + object->variant.fileVariant.top = NULL; 4967 + T(YAFFS_TRACE_GC,(TSTR("yaffs: About to finally delete object %d" TENDSTR),object->objectId)); 4968 + yaffs_DoGenericObjectDeletion(object); 4969 + } 4970 + 4971 + } 4972 + 4973 + } 4974 + 4975 + if(chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) 4976 + { 4977 + T(YAFFS_TRACE_GC,(TSTR("gc did not increase free chunks before %d after %d" TENDSTR),chunksBefore,chunksAfter)); 4978 + } 4979 + 4980 + 4981 + dev->isDoingGC = 0; 4982 + 4983 + //yaffs_VerifyFreeChunks(dev); 4984 + 4985 + return YAFFS_OK; 4986 +} 4987 + 4988 +#if 0 4989 +static yaffs_Object *yaffs_FindDeletedUnlinkedFile(yaffs_Device *dev) 4990 +{ 4991 + // find a file to delete 4992 + struct list_head *i; 4993 + yaffs_Object *l; 4994 + 4995 + 4996 + //Scan the unlinked files looking for one to delete 4997 + list_for_each(i,&dev->unlinkedDir->variant.directoryVariant.children) 4998 + { 4999 + if(i) 5000 + { 5001 + l = list_entry(i, yaffs_Object,siblings); 5002 + if(l->deleted) 5003 + { 5004 + return l; 5931 5005 + } 5932 + 5933 + } 5934 + 5935 + } 5936 + 5937 + if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) { 5938 + T(YAFFS_TRACE_GC, 5939 + (TSTR 5940 + ("gc did not increase free chunks before %d after %d" 5941 + TENDSTR), chunksBefore, chunksAfter)); 5942 + } 5943 + 5944 + dev->isDoingGC = 0; 5945 + 5946 + return YAFFS_OK; 5947 +} 5948 + 5949 +/* New garbage collector 5950 + * If we're very low on erased blocks then we do aggressive garbage collection 5951 + * otherwise we do "leasurely" garbage collection. 5952 + * Aggressive gc looks further (whole array) and will accept less dirty blocks. 5953 + * Passive gc only inspects smaller areas and will only accept more dirty blocks. 5954 + * 5955 + * The idea is to help clear out space in a more spread-out manner. 5956 + * Dunno if it really does anything useful. 5957 + */ 5958 +static int yaffs_CheckGarbageCollection(yaffs_Device * dev) 5006 + } 5007 + } 5008 + return NULL; 5009 +} 5010 + 5011 + 5012 +static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev) 5013 +{ 5014 + // This does background deletion on unlinked files.. only deleted ones. 5015 + // If we don't have a file we're working on then find one 5016 + if(!dev->unlinkedDeletion && dev->nDeletedFiles > 0) 5017 + { 5018 + dev->unlinkedDeletion = yaffs_FindDeletedUnlinkedFile(dev); 5019 + } 5020 + 5021 + // OK, we're working on a file... 5022 + if(dev->unlinkedDeletion) 5023 + { 5024 + yaffs_Object *obj = dev->unlinkedDeletion; 5025 + int delresult; 5026 + int limit; // Number of chunks to delete in a file. 5027 + // NB this can be exceeded, but not by much. 5028 + 5029 + limit = -1; 5030 + 5031 + delresult = yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit); 5032 + 5033 + if(obj->nDataChunks == 0) 5034 + { 5035 + // Done all the deleting of data chunks. 5036 + // Now dump the header and clean up 5037 + yaffs_FreeTnode(dev,obj->variant.fileVariant.top); 5038 + obj->variant.fileVariant.top = NULL; 5039 + yaffs_DoGenericObjectDeletion(obj); 5040 + dev->nDeletedFiles--; 5041 + dev->nUnlinkedFiles--; 5042 + dev->nBackgroundDeletions++; 5043 + dev->unlinkedDeletion = NULL; 5044 + } 5045 + } 5046 +} 5047 + 5048 +#endif 5049 + 5050 + 5051 + 5052 +// New garbage collector 5053 +// If we're very low on erased blocks then we do aggressive garbage collection 5054 +// otherwise we do "leasurely" garbage collection. 5055 +// Aggressive gc looks further (whole array) and will accept dirtier blocks. 5056 +// Passive gc only inspects smaller areas and will only accept cleaner blocks. 5057 +// 5058 +// The idea is to help clear out space in a more spread-out manner. 5059 +// Dunno if it really does anything useful. 5060 +// 5061 +static int yaffs_CheckGarbageCollection(yaffs_Device *dev) 5959 5062 +{ 5960 5063 + int block; 5961 + int aggressive; 5064 + int aggressive; 5962 5065 + int gcOk = YAFFS_OK; 5963 5066 + int maxTries = 0; 5964 5067 + 5965 + int checkpointBlockAdjust; 5966 + 5967 + if (dev->isDoingGC) { 5968 + /* Bail out so we don't get recursive gc */ 5068 + //yaffs_VerifyFreeChunks(dev); 5069 + 5070 + if(dev->isDoingGC) 5071 + { 5072 + // Bail out so we don't get recursive gc 5969 5073 + return YAFFS_OK; 5970 5074 + } 5971 + 5972 + /* This loop should pass the first time. 5973 + * We'll only see looping here if the erase of the collected block fails. 5974 + */ 5975 + 5976 + do { 5075 + 5076 + // This loop should pass the first time. 5077 + // We'll only see looping here if the erase of the collected block fails. 5078 + 5079 + do{ 5977 5080 + maxTries++; 5978 + 5979 + checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint); 5980 + if(checkpointBlockAdjust < 0) 5981 + checkpointBlockAdjust = 0; 5982 + 5983 + if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) { 5984 + /* We need a block soon...*/ 5081 + if(dev->nErasedBlocks < dev->nReservedBlocks) 5082 + { 5083 + // We need a block soon... 5985 5084 + aggressive = 1; 5986 + } else { 5987 + /* We're in no hurry */ 5085 + } 5086 + else 5087 + { 5088 + // We're in no hurry 5988 5089 + aggressive = 0; 5989 5090 + } 5990 + 5991 + block = yaffs_FindBlockForGarbageCollection(dev, aggressive); 5992 + 5993 + if (block > 0) { 5091 + 5092 + block = yaffs_FindBlockForGarbageCollection(dev,aggressive); 5093 + 5094 + if(block > 0) 5095 + { 5994 5096 + dev->garbageCollections++; 5995 + if (!aggressive) { 5097 + if(!aggressive) 5098 + { 5996 5099 + dev->passiveGarbageCollections++; 5997 5100 + } 5998 5101 + 5999 + T(YAFFS_TRACE_GC, 6000 + (TSTR 6001 + ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR), 6002 + dev->nErasedBlocks, aggressive)); 6003 + 6004 + gcOk = yaffs_GarbageCollectBlock(dev, block); 6005 + } 6006 + 6007 + if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) { 6008 + T(YAFFS_TRACE_GC, 6009 + (TSTR 6010 + ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d" 6011 + TENDSTR), dev->nErasedBlocks, maxTries, block)); 6012 + } 6013 + } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0) 6014 + && (maxTries < 2)); 6015 + 6016 + return aggressive ? gcOk : YAFFS_OK; 6017 +} 6018 + 6019 +/*------------------------- TAGS --------------------------------*/ 6020 + 6021 +static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId, 6022 + int chunkInObject) 6023 +{ 6024 + return (tags->chunkId == chunkInObject && 6025 + tags->objectId == objectId && !tags->chunkDeleted) ? 1 : 0; 6026 + 6027 +} 6028 + 6029 + 6030 +/*-------------------- Data file manipulation -----------------*/ 6031 + 6032 +static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode, 6033 + yaffs_ExtendedTags * tags) 6034 +{ 6035 + /*Get the Tnode, then get the level 0 offset chunk offset */ 6036 + yaffs_Tnode *tn; 6037 + int theChunk = -1; 6038 + yaffs_ExtendedTags localTags; 6039 + int retVal = -1; 6040 + 6041 + yaffs_Device *dev = in->myDev; 6042 + 6043 + if (!tags) { 6044 + /* Passed a NULL, so use our own tags space */ 6045 + tags = &localTags; 6046 + } 6047 + 6048 + tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode); 6049 + 6050 + if (tn) { 6051 + theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); 6052 + 6053 + retVal = 6054 + yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, 6055 + chunkInInode); 6056 + } 6057 + return retVal; 6058 +} 6059 + 6060 +static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode, 6061 + yaffs_ExtendedTags * tags) 6062 +{ 6063 + /* Get the Tnode, then get the level 0 offset chunk offset */ 6064 + yaffs_Tnode *tn; 6065 + int theChunk = -1; 6066 + yaffs_ExtendedTags localTags; 6067 + 6068 + yaffs_Device *dev = in->myDev; 6069 + int retVal = -1; 6070 + 6071 + if (!tags) { 6072 + /* Passed a NULL, so use our own tags space */ 6073 + tags = &localTags; 6074 + } 6075 + 6076 + tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode); 6077 + 6078 + if (tn) { 6079 + 6080 + theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); 6081 + 6082 + retVal = 6083 + yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, 6084 + chunkInInode); 6085 + 6086 + /* Delete the entry in the filestructure (if found) */ 6087 + if (retVal != -1) { 6088 + yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0); 6089 + } 6090 + } else { 6091 + /*T(("No level 0 found for %d\n", chunkInInode)); */ 6092 + } 6093 + 6094 + if (retVal == -1) { 6095 + /* T(("Could not find %d to delete\n",chunkInInode)); */ 6096 + } 6097 + return retVal; 6098 +} 5102 + T(YAFFS_TRACE_GC,(TSTR("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),dev->nErasedBlocks,aggressive)); 5103 + 5104 + gcOk = yaffs_GarbageCollectBlock(dev,block); 5105 + } 5106 + 5107 + if(dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) 5108 + { 5109 + T(YAFFS_TRACE_GC,(TSTR("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d" TENDSTR),dev->nErasedBlocks,maxTries,block)); 5110 + } 5111 + } while((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0) && (maxTries < 2)); 5112 + 5113 + return aggressive ? gcOk: YAFFS_OK; 5114 +} 5115 + 5116 + 5117 +//////////////////////////// TAGS /////////////////////////////////////// 5118 + 5119 + 5120 + 5121 +#if 0 5122 + 5123 +void yaffs_CalcTagsECC(yaffs_Tags *tags) 5124 +{ 5125 + // Calculate an ecc 5126 + 5127 + unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; 5128 + unsigned i,j; 5129 + unsigned ecc = 0; 5130 + unsigned bit = 0; 5131 + 5132 + tags->ecc = 0; 5133 + 5134 + for(i = 0; i < 8; i++) 5135 + { 5136 + for(j = 1; j &0xff; j<<=1) 5137 + { 5138 + bit++; 5139 + if(b[i] & j) 5140 + { 5141 + ecc ^= bit; 5142 + } 5143 + } 5144 + } 5145 + 5146 + tags->ecc = ecc; 5147 + 5148 + 5149 +} 5150 + 5151 +int yaffs_CheckECCOnTags(yaffs_Tags *tags) 5152 +{ 5153 + unsigned ecc = tags->ecc; 5154 + 5155 + yaffs_CalcTagsECC(tags); 5156 + 5157 + ecc ^= tags->ecc; 5158 + 5159 + if(ecc && ecc <= 64) 5160 + { 5161 + // TODO: Handle the failure better. Retire? 5162 + unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; 5163 + 5164 + ecc--; 5165 + 5166 + b[ecc / 8] ^= (1 << (ecc & 7)); 5167 + 5168 + // Now recvalc the ecc 5169 + yaffs_CalcTagsECC(tags); 5170 + 5171 + return 1; // recovered error 5172 + } 5173 + else if(ecc) 5174 + { 5175 + // Wierd ecc failure value 5176 + // TODO Need to do somethiong here 5177 + return -1; //unrecovered error 5178 + } 5179 + 5180 + return 0; 5181 +} 5182 + 5183 +static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr) 5184 +{ 5185 + yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; 5186 + 5187 + yaffs_CalcTagsECC(tagsPtr); 5188 + 5189 + sparePtr->tagByte0 = tu->asBytes[0]; 5190 + sparePtr->tagByte1 = tu->asBytes[1]; 5191 + sparePtr->tagByte2 = tu->asBytes[2]; 5192 + sparePtr->tagByte3 = tu->asBytes[3]; 5193 + sparePtr->tagByte4 = tu->asBytes[4]; 5194 + sparePtr->tagByte5 = tu->asBytes[5]; 5195 + sparePtr->tagByte6 = tu->asBytes[6]; 5196 + sparePtr->tagByte7 = tu->asBytes[7]; 5197 +} 5198 + 5199 +static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr) 5200 +{ 5201 + yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; 5202 + int result; 5203 + 5204 + tu->asBytes[0]= sparePtr->tagByte0; 5205 + tu->asBytes[1]= sparePtr->tagByte1; 5206 + tu->asBytes[2]= sparePtr->tagByte2; 5207 + tu->asBytes[3]= sparePtr->tagByte3; 5208 + tu->asBytes[4]= sparePtr->tagByte4; 5209 + tu->asBytes[5]= sparePtr->tagByte5; 5210 + tu->asBytes[6]= sparePtr->tagByte6; 5211 + tu->asBytes[7]= sparePtr->tagByte7; 5212 + 5213 + result = yaffs_CheckECCOnTags(tagsPtr); 5214 + if(result> 0) 5215 + { 5216 + dev->tagsEccFixed++; 5217 + } 5218 + else if(result <0) 5219 + { 5220 + dev->tagsEccUnfixed++; 5221 + } 5222 +} 5223 + 5224 +static void yaffs_SpareInitialise(yaffs_Spare *spare) 5225 +{ 5226 + memset(spare,0xFF,sizeof(yaffs_Spare)); 5227 +} 5228 + 5229 +#endif 5230 + 5231 +#if 0 5232 +static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_ExtendedTags *tags, int useReserve) 5233 +{ 5234 + // NB There must be tags, data is optional 5235 + // If there is data, then an ECC is calculated on it. 5236 + 5237 + yaffs_Spare spare; 5238 + 5239 + if(!tags) 5240 + { 5241 + return YAFFS_FAIL; 5242 + } 5243 + 5244 + //yaffs_SpareInitialise(&spare); 5245 + 5246 + //if(!dev->useNANDECC && buffer) 5247 + //{ 5248 + // yaffs_CalcECC(buffer,&spare); 5249 + //} 5250 + 5251 + //yaffs_LoadTagsIntoSpare(&spare,tags); 5252 + 5253 + return yaffs_WriteNewChunkToNAND(dev,buffer,&spare,useReserve); 5254 + 5255 +} 5256 +#endif 5257 + 5258 +static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, int chunkInObject) 5259 +{ 5260 + return ( tags->chunkId == chunkInObject && 5261 + tags->objectId == objectId && 5262 + !tags->chunkDeleted) ? 1 : 0; 5263 + 5264 +} 5265 + 5266 +///////////////////////////////////////////////////////////////////////////////////////////////////////// 5267 + 5268 + 5269 +static int yaffs_FindChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags) 5270 +{ 5271 + //Get the Tnode, then get the level 0 offset chunk offset 5272 + yaffs_Tnode *tn; 5273 + int theChunk = -1; 5274 + yaffs_ExtendedTags localTags; 5275 + int retVal = -1; 5276 + 5277 + yaffs_Device *dev = in->myDev; 5278 + 5279 + 5280 + if(!tags) 5281 + { 5282 + // Passed a NULL, so use our own tags space 5283 + tags = &localTags; 5284 + } 5285 + 5286 + tn = yaffs_FindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode); 5287 + 5288 + if(tn) 5289 + { 5290 + theChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev->chunkGroupBits; 5291 + 5292 + retVal = yaffs_FindChunkInGroup(dev,theChunk,tags,in->objectId,chunkInInode); 5293 + } 5294 + return retVal; 5295 +} 5296 + 5297 +static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags) 5298 +{ 5299 + //Get the Tnode, then get the level 0 offset chunk offset 5300 + yaffs_Tnode *tn; 5301 + int theChunk = -1; 5302 + yaffs_ExtendedTags localTags; 5303 + 5304 + yaffs_Device *dev = in->myDev; 5305 + int retVal = -1; 5306 + 5307 + if(!tags) 5308 + { 5309 + // Passed a NULL, so use our own tags space 5310 + tags = &localTags; 5311 + } 5312 + 5313 + tn = yaffs_FindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode); 5314 + 5315 + if(tn) 5316 + { 5317 + 5318 + theChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev->chunkGroupBits; 5319 + 5320 + retVal = yaffs_FindChunkInGroup(dev,theChunk,tags,in->objectId,chunkInInode); 5321 + 5322 + // Delete the entry in the filestructure (if found) 5323 + if(retVal != -1) 5324 + { 5325 + tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = 0; 5326 + } 5327 + } 5328 + else 5329 + { 5330 + //T(("No level 0 found for %d\n", chunkInInode)); 5331 + } 5332 + 5333 + if(retVal == -1) 5334 + { 5335 + //T(("Could not find %d to delete\n",chunkInInode)); 5336 + } 5337 + return retVal; 5338 +} 5339 + 6099 5340 + 6100 5341 +#ifdef YAFFS_PARANOID 6101 5342 + 6102 +static int yaffs_CheckFileSanity(yaffs_Object * in)5343 +static int yaffs_CheckFileSanity(yaffs_Object *in) 6103 5344 +{ 6104 5345 + int chunk; … … 6108 5349 + int objId; 6109 5350 + yaffs_Tnode *tn; 6110 + yaffs_Tags localTags; 6111 + yaffs_Tags *tags = &localTags; 6112 + int theChunk; 6113 + int chunkDeleted; 6114 + 6115 + if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { 6116 + /* T(("Object not a file\n")); */ 5351 + yaffs_Tags localTags; 5352 + yaffs_Tags *tags = &localTags; 5353 + int theChunk; 5354 + int chunkDeleted; 5355 + 5356 + 5357 + if(in->variantType != YAFFS_OBJECT_TYPE_FILE) 5358 + { 5359 + //T(("Object not a file\n")); 6117 5360 + return YAFFS_FAIL; 6118 5361 + } 6119 + 5362 + 6120 5363 + objId = in->objectId; 6121 + fSize = in->variant.fileVariant.fileSize; 6122 + nChunks = 6123 + (fSize + in->myDev->nDataBytesPerChunk - 1) / in->myDev->nDataBytesPerChunk; 6124 + 6125 + for (chunk = 1; chunk <= nChunks; chunk++) { 6126 + tn = yaffs_FindLevel0Tnode(in->myDev, &in->variant.fileVariant, 6127 + chunk); 6128 + 6129 + if (tn) { 6130 + 6131 + theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk); 6132 + 6133 + if (yaffs_CheckChunkBits 6134 + (dev, theChunk / dev->nChunksPerBlock, 6135 + theChunk % dev->nChunksPerBlock)) { 6136 + 6137 + yaffs_ReadChunkTagsFromNAND(in->myDev, theChunk, 6138 + tags, 6139 + &chunkDeleted); 6140 + if (yaffs_TagsMatch 6141 + (tags, in->objectId, chunk, chunkDeleted)) { 6142 + /* found it; */ 6143 + 5364 + fSize = in->variant.fileVariant.fileSize; 5365 + nChunks = (fSize + in->myDev->nBytesPerChunk -1)/in->myDev->nBytesPerChunk; 5366 + 5367 + for(chunk = 1; chunk <= nChunks; chunk++) 5368 + { 5369 + tn = yaffs_FindLevel0Tnode(in->myDev,&in->variant.fileVariant, chunk); 5370 + 5371 + if(tn) 5372 + { 5373 + 5374 + theChunk = tn->level0[chunk & YAFFS_TNODES_LEVEL0_MASK] << in->myDev->chunkGroupBits; 5375 + 5376 + if(yaffs_CheckChunkBits(dev,theChunk/dev->nChunksPerBlock,theChunk%dev->nChunksPerBlock)) 5377 + { 5378 + 5379 + 5380 + yaffs_ReadChunkTagsFromNAND(in->myDev,theChunk,tags,&chunkDeleted); 5381 + if(yaffs_TagsMatch(tags,in->objectId,chunk,chunkDeleted)) 5382 + { 5383 + // found it; 5384 + 6144 5385 + } 6145 + } else { 6146 + 5386 + } 5387 + else 5388 + { 5389 + //T(("File problem file [%d,%d] NAND %d tags[%d,%d]\n", 5390 + // objId,chunk,theChunk,tags->chunkId,tags->objectId); 5391 + 6147 5392 + failed = 1; 5393 + 6148 5394 + } 6149 + 6150 + } else { 6151 + /* T(("No level 0 found for %d\n", chunk)); */ 6152 + } 6153 + } 6154 + 5395 + 5396 + } 5397 + else 5398 + { 5399 + //T(("No level 0 found for %d\n", chunk)); 5400 + } 5401 + } 5402 + 6155 5403 + return failed ? YAFFS_FAIL : YAFFS_OK; 6156 5404 +} … … 6158 5406 +#endif 6159 5407 + 6160 +static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, 6161 + int chunkInNAND, int inScan) 6162 +{ 6163 + /* NB inScan is zero unless scanning. 6164 + * For forward scanning, inScan is > 0; 6165 + * for backward scanning inScan is < 0 6166 + */ 6167 + 5408 +static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkInNAND, int inScan) 5409 +{ 5410 + // NB inScan is zero unless scanning. For forward scanning, inScan is > 0; for backward scanning inScan is < 0 6168 5411 + yaffs_Tnode *tn; 6169 5412 + yaffs_Device *dev = in->myDev; … … 6172 5415 + yaffs_ExtendedTags newTags; 6173 5416 + unsigned existingSerial, newSerial; 6174 + 6175 + if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { 6176 + /* Just ignore an attempt at putting a chunk into a non-file during scanning 6177 + * If it is not during Scanning then something went wrong! 6178 + */ 6179 + if (!inScan) { 6180 + T(YAFFS_TRACE_ERROR, 6181 + (TSTR 6182 + ("yaffs tragedy:attempt to put data chunk into a non-file" 6183 + TENDSTR))); 5417 + 5418 + if(in->variantType != YAFFS_OBJECT_TYPE_FILE) 5419 + { 5420 + // Just ignore an attempt at putting a chunk into a non-file during scanning 5421 + // If it is not during Scanning then something went wrong! 5422 + if(!inScan) 5423 + { 5424 + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy:attempt to put data chunk into a non-file" TENDSTR))); 6184 5425 + YBUG(); 6185 5426 + } 6186 + 6187 + yaffs_DeleteChunk(dev, chunkInNAND, 1,__LINE__);5427 + 5428 + yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__); 6188 5429 + return YAFFS_OK; 6189 5430 + } 6190 + 6191 + tn = yaffs_AddOrFindLevel0Tnode(dev, 6192 + &in->variant.fileVariant, 6193 + chunkInInode, 6194 + NULL); 6195 + if (!tn) { 5431 + 5432 + tn = yaffs_AddOrFindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode); 5433 + if(!tn) 5434 + { 6196 5435 + return YAFFS_FAIL; 6197 5436 + } 6198 5437 + 6199 + existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); 6200 + 6201 + if (inScan != 0) { 6202 + /* If we're scanning then we need to test for duplicates 6203 + * NB This does not need to be efficient since it should only ever 6204 + * happen when the power fails during a write, then only one 6205 + * chunk should ever be affected. 6206 + * 6207 + * Correction for YAFFS2: This could happen quite a lot and we need to think about efficiency! TODO 6208 + * Update: For backward scanning we don't need to re-read tags so this is quite cheap. 6209 + */ 6210 + 6211 + if (existingChunk != 0) { 6212 + /* NB Right now existing chunk will not be real chunkId if the device >= 32MB 6213 + * thus we have to do a FindChunkInFile to get the real chunk id. 6214 + * 6215 + * We have a duplicate now we need to decide which one to use: 6216 + * 6217 + * Backwards scanning YAFFS2: The old one is what we use, dump the new one. 6218 + * Forward scanning YAFFS2: The new one is what we use, dump the old one. 6219 + * YAFFS1: Get both sets of tags and compare serial numbers. 6220 + */ 6221 + 6222 + if (inScan > 0) { 6223 + /* Only do this for forward scanning */ 6224 + yaffs_ReadChunkWithTagsFromNAND(dev, 6225 + chunkInNAND, 6226 + NULL, &newTags); 6227 + 6228 + /* Do a proper find */ 6229 + existingChunk = 6230 + yaffs_FindChunkInFile(in, chunkInInode, 6231 + &existingTags); 5438 + existingChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK]; 5439 + 5440 + if(inScan != 0) 5441 + { 5442 + // If we're scanning then we need to test for duplicates 5443 + // NB This does not need to be efficient since it should only ever 5444 + // happen when the power fails during a write, then only one 5445 + // chunk should ever be affected. 5446 + // 5447 + // Correction for YAFFS2: This could happen quite a lot and we need to think about efficiency! TODO 5448 + // Update: For backward scanning we don't need to re-read tags so this is quite cheap. 5449 + 5450 + 5451 + 5452 + if(existingChunk != 0) 5453 + { 5454 + // NB Right now existing chunk will not be real chunkId if the device >= 32MB 5455 + // thus we have to do a FindChunkInFile to get the real chunk id. 5456 + // 5457 + // We have a duplicate now we need to decide which one to use: 5458 + // 5459 + // Backwards scanning YAFFS2: The old one is what we use, dump the new one. 5460 + // Forward scanning YAFFS2: The new one is what we use, dump the old one. 5461 + // YAFFS1: Get both sets of tags and compare serial numbers. 5462 + // 5463 + // 5464 + 5465 + if(inScan > 0) 5466 + { 5467 + // Only do this for forward scanning 5468 + yaffs_ReadChunkWithTagsFromNAND(dev,chunkInNAND, NULL,&newTags); 5469 + 5470 + 5471 + // Do a proper find 5472 + existingChunk = yaffs_FindChunkInFile(in,chunkInInode, &existingTags); 6232 5473 + } 6233 5474 + 6234 + if (existingChunk <= 0) { 6235 + /*Hoosterman - how did this happen? */ 6236 + 6237 + T(YAFFS_TRACE_ERROR, 6238 + (TSTR 6239 + ("yaffs tragedy: existing chunk < 0 in scan" 6240 + TENDSTR))); 5475 + if(existingChunk <=0) 5476 + { 5477 + //Hoosterman - how did this happen? 5478 + 5479 + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: existing chunk < 0 in scan" TENDSTR))); 6241 5480 + 6242 5481 + } 6243 5482 + 6244 + /* NB The deleted flags should be false, otherwise the chunks will6245 + * not be loaded during a scan6246 + */6247 + 5483 + 5484 + // NB The deleted flags should be false, otherwise the chunks will 5485 + // not be loaded during a scan 5486 + 6248 5487 + newSerial = newTags.serialNumber; 6249 5488 + existingSerial = existingTags.serialNumber; 6250 + 6251 + if ((inScan > 0) && 6252 + (in->myDev->isYaffs2 || 6253 + existingChunk <= 0 || 6254 + ((existingSerial + 1) & 3) == newSerial)) { 6255 + /* Forward scanning. 6256 + * Use new 6257 + * Delete the old one and drop through to update the tnode 6258 + */ 6259 + yaffs_DeleteChunk(dev, existingChunk, 1, 6260 + __LINE__); 6261 + } else { 6262 + /* Backward scanning or we want to use the existing one 6263 + * Use existing. 6264 + * Delete the new one and return early so that the tnode isn't changed 6265 + */ 6266 + yaffs_DeleteChunk(dev, chunkInNAND, 1, 6267 + __LINE__); 5489 + 5490 + if( (inScan > 0) && 5491 + ( in->myDev->isYaffs2 || 5492 + existingChunk <= 0 || 5493 + ((existingSerial+1) & 3) == newSerial)) 5494 + { 5495 + // Forward scanning. 5496 + // Use new 5497 + // Delete the old one and drop through to update the tnode 5498 + yaffs_DeleteChunk(dev,existingChunk,1,__LINE__); 5499 + } 5500 + else 5501 + { 5502 + // Backward scanning or we want to use the existing one 5503 + // Use existing. 5504 + // Delete the new one and return early so that the tnode isn't changed 5505 + yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__); 6268 5506 + return YAFFS_OK; 6269 5507 + } … … 6271 5509 + 6272 5510 + } 6273 + 6274 + if (existingChunk == 0) { 5511 + 5512 + if(existingChunk == 0) 5513 + { 6275 5514 + in->nDataChunks++; 6276 5515 + } 6277 + 6278 + yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND);6279 + 5516 + 5517 + tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = (chunkInNAND >> dev->chunkGroupBits); 5518 + 6280 5519 + return YAFFS_OK; 6281 5520 +} 6282 5521 + 6283 +static int yaffs_ReadChunkDataFromObject(yaffs_Object * in, int chunkInInode, 6284 + __u8 * buffer) 6285 +{ 6286 + int chunkInNAND = yaffs_FindChunkInFile(in, chunkInInode, NULL); 6287 + 6288 + if (chunkInNAND >= 0) { 6289 + return yaffs_ReadChunkWithTagsFromNAND(in->myDev, chunkInNAND, 6290 + buffer,NULL); 6291 + } else { 6292 + T(YAFFS_TRACE_NANDACCESS, 6293 + (TSTR("Chunk %d not found zero instead" TENDSTR), 6294 + chunkInNAND)); 6295 + /* get sane (zero) data if you read a hole */ 6296 + memset(buffer, 0, in->myDev->nDataBytesPerChunk); 5522 + 5523 + 5524 +static int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffer) 5525 +{ 5526 + int chunkInNAND = yaffs_FindChunkInFile(in,chunkInInode,NULL); 5527 + 5528 + if(chunkInNAND >= 0) 5529 + { 5530 + return yaffs_ReadChunkWithTagsFromNAND(in->myDev,chunkInNAND,buffer,NULL); 5531 + } 5532 + else 5533 + { 5534 + T(YAFFS_TRACE_NANDACCESS,(TSTR("Chunk %d not found zero instead" TENDSTR),chunkInNAND)); 5535 + 5536 + memset(buffer,0,in->myDev->nBytesPerChunk); // get sane data if you read a hole 6297 5537 + return 0; 6298 5538 + } … … 6300 5540 +} 6301 5541 + 6302 +void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn) 5542 + 5543 +void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND,int lyn) 6303 5544 +{ 6304 5545 + int block; … … 6306 5547 + yaffs_ExtendedTags tags; 6307 5548 + yaffs_BlockInfo *bi; 6308 + 6309 + if (chunkId <= 0) 6310 + return; 6311 + 5549 + 5550 + if(chunkId <= 0) return; 5551 + 6312 5552 + dev->nDeletions++; 6313 5553 + block = chunkId / dev->nChunksPerBlock; 6314 5554 + page = chunkId % dev->nChunksPerBlock; 6315 + 6316 + bi = yaffs_GetBlockInfo(dev, block); 6317 + 6318 + T(YAFFS_TRACE_DELETION, 6319 + (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId)); 6320 + 6321 + if (markNAND && 6322 + bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->isYaffs2) { 5555 + 5556 + bi = yaffs_GetBlockInfo(dev,block); 5557 + 5558 + T(YAFFS_TRACE_DELETION,(TSTR("line %d delete of chunk %d" TENDSTR),lyn,chunkId)); 5559 + 5560 + if(markNAND && 5561 + bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && 5562 + !dev->isYaffs2) 5563 + { 5564 +// yaffs_SpareInitialise(&spare); 5565 + 5566 +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE 5567 + 5568 + //read data before write, to ensure correct ecc 5569 + //if we're using MTD verification under Linux 5570 +// yaffs_ReadChunkFromNAND(dev,chunkId,NULL,&spare,0); 5571 +#endif 6323 5572 + 6324 5573 + yaffs_InitialiseTags(&tags); … … 6326 5575 + tags.chunkDeleted = 1; 6327 5576 + 6328 + yaffs_WriteChunkWithTagsToNAND(dev, chunkId, NULL, &tags); 6329 + yaffs_HandleUpdateChunk(dev, chunkId, &tags); 6330 + } else { 6331 + dev->nUnmarkedDeletions++; 6332 + } 6333 + 6334 + /* Pull out of the management area. 6335 + * If the whole block became dirty, this will kick off an erasure. 6336 + */ 6337 + if (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || 6338 + bi->blockState == YAFFS_BLOCK_STATE_FULL || 5577 + 5578 + yaffs_WriteChunkWithTagsToNAND(dev,chunkId,NULL,&tags); 5579 + yaffs_HandleUpdateChunk(dev,chunkId,&tags); 5580 + } 5581 + else 5582 + { 5583 + dev->nUnmarkedDeletions++; 5584 + } 5585 + 5586 + 5587 + // Pull out of the management area. 5588 + // If the whole block became dirty, this will kick off an erasure. 5589 + if( bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || 5590 + bi->blockState == YAFFS_BLOCK_STATE_FULL || 6339 5591 + bi->blockState == YAFFS_BLOCK_STATE_NEEDS_SCANNING || 6340 + bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) { 6341 + dev->nFreeChunks++; 6342 + 6343 + yaffs_ClearChunkBit(dev, block, page); 6344 + 5592 + bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) 5593 + { 5594 + dev->nFreeChunks++; 5595 + 5596 + yaffs_ClearChunkBit(dev,block,page); 5597 + 6345 5598 + bi->pagesInUse--; 6346 + 6347 + if (bi->pagesInUse == 0 && 6348 + !bi->hasShrinkHeader && 6349 + bi->blockState != YAFFS_BLOCK_STATE_ALLOCATING && 6350 + bi->blockState != YAFFS_BLOCK_STATE_NEEDS_SCANNING) { 6351 + yaffs_BlockBecameDirty(dev, block); 6352 + } 6353 + 6354 + } else { 6355 + /* T(("Bad news deleting chunk %d\n",chunkId)); */ 6356 + } 6357 + 6358 +} 6359 + 6360 +static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode, 6361 + const __u8 * buffer, int nBytes, 6362 + int useReserve) 6363 +{ 6364 + /* Find old chunk Need to do this to get serial number 6365 + * Write new one and patch into tree. 6366 + * Invalidate old tags. 6367 + */ 6368 + 6369 + int prevChunkId; 6370 + yaffs_ExtendedTags prevTags; 6371 + 6372 + int newChunkId; 6373 + yaffs_ExtendedTags newTags; 6374 + 5599 + 5600 + if(bi->pagesInUse == 0 && 5601 + !bi->hasShrinkHeader && 5602 + bi->blockState != YAFFS_BLOCK_STATE_ALLOCATING && 5603 + bi->blockState != YAFFS_BLOCK_STATE_NEEDS_SCANNING) 5604 + { 5605 + yaffs_BlockBecameDirty(dev,block); 5606 + } 5607 + 5608 + } 5609 + else 5610 + { 5611 + // T(("Bad news deleting chunk %d\n",chunkId)); 5612 + } 5613 + 5614 +} 5615 + 5616 + 5617 + 5618 + 5619 +static int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 *buffer,int nBytes,int useReserve) 5620 +{ 5621 + // Find old chunk Need to do this to get serial number 5622 + // Write new one and patch into tree. 5623 + // Invalidate old tags. 5624 + 5625 + int prevChunkId; 5626 + yaffs_ExtendedTags prevTags; 5627 + 5628 + int newChunkId; 5629 + yaffs_ExtendedTags newTags; 5630 + 5631 + yaffs_Device *dev = in->myDev; 5632 + 5633 + yaffs_CheckGarbageCollection(dev); 5634 + 5635 + // Get the previous chunk at this location in the file if it exists 5636 + prevChunkId = yaffs_FindChunkInFile(in,chunkInInode,&prevTags); 5637 + 5638 + // Set up new tags 5639 + yaffs_InitialiseTags(&newTags); 5640 + 5641 + newTags.chunkId = chunkInInode; 5642 + newTags.objectId = in->objectId; 5643 + newTags.serialNumber = (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1; 5644 + newTags.byteCount = nBytes; 5645 + 5646 +// yaffs_CalcTagsECC(&newTags); 5647 + 5648 + newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev,buffer,&newTags,useReserve); 5649 + 5650 + if(newChunkId >= 0) 5651 + { 5652 + yaffs_PutChunkIntoFile(in,chunkInInode,newChunkId,0); 5653 + 5654 + 5655 + if(prevChunkId >= 0) 5656 + { 5657 + yaffs_DeleteChunk(dev,prevChunkId,1,__LINE__); 5658 + 5659 + } 5660 + 5661 + yaffs_CheckFileSanity(in); 5662 + } 5663 + return newChunkId; 5664 + 5665 + 5666 + 5667 + 5668 + 5669 +} 5670 + 5671 + 5672 +// UpdateObjectHeader updates the header on NAND for an object. 5673 +// If name is not NULL, then that new name is used. 5674 +// 5675 +int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink,int shadows) 5676 +{ 5677 + 5678 + yaffs_BlockInfo *bi; 5679 + 6375 5680 + yaffs_Device *dev = in->myDev; 6376 + 6377 + yaffs_CheckGarbageCollection(dev); 6378 + 6379 + /* Get the previous chunk at this location in the file if it exists */ 6380 + prevChunkId = yaffs_FindChunkInFile(in, chunkInInode, &prevTags); 6381 + 6382 + /* Set up new tags */ 6383 + yaffs_InitialiseTags(&newTags); 6384 + 6385 + newTags.chunkId = chunkInInode; 6386 + newTags.objectId = in->objectId; 6387 + newTags.serialNumber = 6388 + (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1; 6389 + newTags.byteCount = nBytes; 6390 + 6391 + newChunkId = 6392 + yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, 6393 + useReserve); 6394 + 6395 + if (newChunkId >= 0) { 6396 + yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0); 6397 + 6398 + if (prevChunkId >= 0) { 6399 + yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__); 6400 + 6401 + } 6402 + 6403 + yaffs_CheckFileSanity(in); 6404 + } 6405 + return newChunkId; 6406 + 6407 +} 6408 + 6409 +/* UpdateObjectHeader updates the header on NAND for an object. 6410 + * If name is not NULL, then that new name is used. 6411 + */ 6412 +int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, 6413 + int isShrink, int shadows) 6414 +{ 6415 + 6416 + yaffs_BlockInfo *bi; 6417 + 6418 + yaffs_Device *dev = in->myDev; 6419 + 6420 + int prevChunkId; 6421 + int retVal = 0; 6422 + int result = 0; 6423 + 6424 + int newChunkId; 6425 + yaffs_ExtendedTags newTags; 6426 + 6427 + __u8 *buffer = NULL; 6428 + YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1]; 6429 + 6430 + yaffs_ObjectHeader *oh = NULL; 6431 + 6432 + if (!in->fake || force) { 6433 + 6434 + yaffs_CheckGarbageCollection(dev); 6435 + 6436 + buffer = yaffs_GetTempBuffer(in->myDev, __LINE__); 6437 + oh = (yaffs_ObjectHeader *) buffer; 6438 + 5681 + 5682 + int prevChunkId; 5683 + int retVal = 0; 5684 + 5685 + int newChunkId; 5686 + yaffs_ExtendedTags newTags; 5687 + 5688 + __u8 *buffer = NULL; 5689 + YCHAR oldName[YAFFS_MAX_NAME_LENGTH+1]; 5690 + 5691 + // __u8 bufferOld[YAFFS_BYTES_PER_CHUNK]; 5692 + 5693 + yaffs_ObjectHeader *oh = NULL; 5694 + // yaffs_ObjectHeader *ohOld = (yaffs_ObjectHeader *)bufferOld; 5695 + 5696 + 5697 + if(!in->fake || force) 5698 + { 5699 + 5700 + yaffs_CheckGarbageCollection(dev); 5701 + 5702 + buffer = yaffs_GetTempBuffer(in->myDev,__LINE__); 5703 + oh = (yaffs_ObjectHeader *)buffer; 5704 + 6439 5705 + prevChunkId = in->chunkId; 6440 + 6441 + if (prevChunkId >= 0) { 6442 + result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId, 6443 + buffer, NULL); 6444 + memcpy(oldName, oh->name, sizeof(oh->name)); 6445 + } 6446 + 6447 + memset(buffer, 0xFF, dev->nDataBytesPerChunk); 6448 + 5706 + 5707 + if(prevChunkId >= 0) 5708 + { 5709 + yaffs_ReadChunkWithTagsFromNAND(dev,prevChunkId,buffer,NULL); 5710 + memcpy(oldName,oh->name,sizeof(oh->name)); 5711 + } 5712 + 5713 + memset(buffer,0xFF,dev->nBytesPerChunk); 5714 + 5715 + // Header data 6449 5716 + oh->type = in->variantType; 5717 + 6450 5718 + oh->yst_mode = in->yst_mode; 5719 + 5720 + // shadowing 6451 5721 + oh->shadowsObject = shadows; 6452 5722 + … … 6465 5735 + oh->yst_ctime = in->yst_ctime; 6466 5736 + oh->yst_rdev = in->yst_rdev; 6467 +#endif 6468 + if (in->parent) { 5737 +#endif 5738 + if(in->parent) 5739 + { 6469 5740 + oh->parentObjectId = in->parent->objectId; 6470 + } else { 5741 + } 5742 + else 5743 + { 6471 5744 + oh->parentObjectId = 0; 6472 5745 + } 6473 + 6474 + if (name && *name) { 6475 + memset(oh->name, 0, sizeof(oh->name)); 6476 + yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH); 6477 + } else if (prevChunkId) { 6478 + memcpy(oh->name, oldName, sizeof(oh->name)); 6479 + } else { 6480 + memset(oh->name, 0, sizeof(oh->name)); 6481 + } 6482 + 5746 + 5747 + //oh->sum = in->sum; 5748 + if(name && *name) 5749 + { 5750 + memset(oh->name,0,sizeof(oh->name)); 5751 + yaffs_strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); 5752 + } 5753 + else if(prevChunkId) 5754 + { 5755 + memcpy(oh->name, oldName,sizeof(oh->name)); 5756 + } 5757 + else 5758 + { 5759 + memset(oh->name,0,sizeof(oh->name)); 5760 + } 5761 + 6483 5762 + oh->isShrink = isShrink; 6484 + 6485 + switch (in->variantType) { 6486 + case YAFFS_OBJECT_TYPE_UNKNOWN: 6487 + /* Should not happen */ 6488 + break; 6489 + case YAFFS_OBJECT_TYPE_FILE: 6490 + oh->fileSize = 6491 + (oh->parentObjectId == YAFFS_OBJECTID_DELETED 6492 + || oh->parentObjectId == 6493 + YAFFS_OBJECTID_UNLINKED) ? 0 : in->variant. 6494 + fileVariant.fileSize; 6495 + break; 6496 + case YAFFS_OBJECT_TYPE_HARDLINK: 6497 + oh->equivalentObjectId = 6498 + in->variant.hardLinkVariant.equivalentObjectId; 6499 + break; 6500 + case YAFFS_OBJECT_TYPE_SPECIAL: 6501 + /* Do nothing */ 6502 + break; 6503 + case YAFFS_OBJECT_TYPE_DIRECTORY: 6504 + /* Do nothing */ 6505 + break; 6506 + case YAFFS_OBJECT_TYPE_SYMLINK: 6507 + yaffs_strncpy(oh->alias, 6508 + in->variant.symLinkVariant.alias, 6509 + YAFFS_MAX_ALIAS_LENGTH); 6510 + oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0; 6511 + break; 6512 + } 6513 + 6514 + /* Tags */ 5763 + 5764 + switch(in->variantType) 5765 + { 5766 + case YAFFS_OBJECT_TYPE_UNKNOWN: 5767 + // Should not happen 5768 + break; 5769 + case YAFFS_OBJECT_TYPE_FILE: 5770 + oh->fileSize = (oh->parentObjectId == YAFFS_OBJECTID_DELETED || 5771 + oh->parentObjectId == YAFFS_OBJECTID_UNLINKED) ? 0 : in->variant.fileVariant.fileSize; 5772 + break; 5773 + case YAFFS_OBJECT_TYPE_HARDLINK: 5774 + oh->equivalentObjectId = in->variant.hardLinkVariant.equivalentObjectId; 5775 + break; 5776 + case YAFFS_OBJECT_TYPE_SPECIAL: 5777 + // Do nothing 5778 + break; 5779 + case YAFFS_OBJECT_TYPE_DIRECTORY: 5780 + // Do nothing 5781 + break; 5782 + case YAFFS_OBJECT_TYPE_SYMLINK: 5783 + yaffs_strncpy(oh->alias,in->variant.symLinkVariant.alias,YAFFS_MAX_ALIAS_LENGTH); 5784 + oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0; 5785 + break; 5786 + } 5787 + 5788 + // Tags 6515 5789 + yaffs_InitialiseTags(&newTags); 6516 5790 + in->serial++; … … 6518 5792 + newTags.objectId = in->objectId; 6519 5793 + newTags.serialNumber = in->serial; 6520 + 6521 + / * Add extra info for file header */6522 + 5794 + 5795 + // Add extra info for file header 5796 + 6523 5797 + newTags.extraHeaderInfoAvailable = 1; 6524 5798 + newTags.extraParentObjectId = oh->parentObjectId; … … 6527 5801 + newTags.extraEquivalentObjectId = oh->equivalentObjectId; 6528 5802 + newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0; 6529 + newTags.extraObjectType = in->variantType; 6530 + 6531 + /* Create new chunk in NAND */ 6532 + newChunkId = 6533 + yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, 6534 + (prevChunkId >= 0) ? 1 : 0); 6535 + 6536 + if (newChunkId >= 0) { 6537 + 6538 + in->chunkId = newChunkId; 6539 + 6540 + if (prevChunkId >= 0) { 6541 + yaffs_DeleteChunk(dev, prevChunkId, 1, 6542 + __LINE__); 5803 + newTags.extraObjectType = in->variantType; 5804 + 5805 + // Create new chunk in NAND 5806 + newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev,buffer,&newTags, (prevChunkId >= 0) ? 1 : 0 ); 5807 + 5808 + if(newChunkId >= 0) 5809 + { 5810 + 5811 + in->chunkId = newChunkId; 5812 + 5813 + if(prevChunkId >= 0) 5814 + { 5815 + yaffs_DeleteChunk(dev,prevChunkId,1,__LINE__); 6543 5816 + } 6544 + 6545 + if(!yaffs_ObjectHasCachedWriteData(in)) 6546 + in->dirty = 0; 6547 + 6548 + /* If this was a shrink, then mark the block that the chunk lives on */ 6549 + if (isShrink) { 6550 + bi = yaffs_GetBlockInfo(in->myDev, 6551 + newChunkId /in->myDev-> nChunksPerBlock); 5817 + 5818 + in->dirty = 0; 5819 + 5820 + // If this was a shrink, then mark the block that the chunk lives on 5821 + if(isShrink) 5822 + { 5823 + bi = yaffs_GetBlockInfo(in->myDev,newChunkId / in->myDev->nChunksPerBlock); 6552 5824 + bi->hasShrinkHeader = 1; 6553 5825 + } 6554 + 6555 + } 6556 + 6557 + retVal = newChunkId; 6558 + 6559 + } 6560 + 6561 + if (buffer) 6562 + yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); 6563 + 6564 + return retVal; 6565 +} 6566 + 6567 +/*------------------------ Short Operations Cache ---------------------------------------- 6568 + * In many situations where there is no high level buffering (eg WinCE) a lot of 6569 + * reads might be short sequential reads, and a lot of writes may be short 6570 + * sequential writes. eg. scanning/writing a jpeg file. 6571 + * In these cases, a short read/write cache can provide a huge perfomance benefit 6572 + * with dumb-as-a-rock code. 6573 + * In Linux, the page cache provides read buffering aand the short op cache provides write 6574 + * buffering. 6575 + * 6576 + * There are a limited number (~10) of cache chunks per device so that we don't 6577 + * need a very intelligent search. 6578 + */ 6579 + 6580 +static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj) 5826 + 5827 + } 5828 + 5829 + retVal = newChunkId; 5830 + 5831 + } 5832 + 5833 + if(buffer) 5834 + yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); 5835 + 5836 + return retVal; 5837 +} 5838 + 5839 + 5840 +/////////////////////// Short Operations Cache //////////////////////////////// 5841 +// In many siturations where there is no high level buffering (eg WinCE) a lot of 5842 +// reads might be short sequential reads, and a lot of writes may be short 5843 +// sequential writes. eg. scanning/writing a jpeg file. 5844 +// In these cases, a short read/write cache can provide a huge perfomance benefit 5845 +// with dumb-as-a-rock code. 5846 +// There are a limited number (~10) of cache chunks per device so that we don't 5847 +// need a very intelligent search. 5848 + 5849 + 5850 + 5851 + 5852 + 5853 +static void yaffs_FlushFilesChunkCache(yaffs_Object *obj) 6581 5854 +{ 6582 5855 + yaffs_Device *dev = obj->myDev; 6583 + int i; 6584 + yaffs_ChunkCache *cache; 6585 + int nCaches = obj->myDev->nShortOpCaches; 6586 + 6587 + for(i = 0; i < nCaches; i++){ 6588 + cache = &dev->srCache[i]; 6589 + if (cache->object == obj && 6590 + cache->dirty) 6591 + return 1; 6592 + } 6593 + 6594 + return 0; 6595 +} 6596 + 6597 + 6598 +static void yaffs_FlushFilesChunkCache(yaffs_Object * obj) 6599 +{ 6600 + yaffs_Device *dev = obj->myDev; 6601 + int lowest = -99; /* Stop compiler whining. */ 5856 + int lowest = -99; // Stop compiler whining. 6602 5857 + int i; 6603 5858 + yaffs_ChunkCache *cache; 6604 5859 + int chunkWritten = 0; 5860 + //int nBytes; 6605 5861 + int nCaches = obj->myDev->nShortOpCaches; 6606 + 6607 + if (nCaches > 0) { 6608 + do { 5862 + 5863 + if (nCaches > 0) 5864 + { 5865 + do{ 6609 5866 + cache = NULL; 6610 + 6611 + /* Find the dirty cache for this object with the lowest chunk id. */ 6612 + for (i = 0; i < nCaches; i++) { 6613 + if (dev->srCache[i].object == obj && 6614 + dev->srCache[i].dirty) { 6615 + if (!cache 6616 + || dev->srCache[i].chunkId < 6617 + lowest) { 5867 + 5868 + // Find the dirty cache for this object with the lowest chunk id. 5869 + for(i = 0; i < nCaches; i++) 5870 + { 5871 + if(dev->srCache[i].object == obj && 5872 + dev->srCache[i].dirty) 5873 + { 5874 + if(!cache || dev->srCache[i].chunkId < lowest) 5875 + { 6618 5876 + cache = &dev->srCache[i]; 6619 5877 + lowest = cache->chunkId; … … 6621 5879 + } 6622 5880 + } 6623 + 6624 + if (cache && !cache->locked) { 6625 + /* Write it out and free it up */ 6626 + 6627 + chunkWritten = 6628 + yaffs_WriteChunkDataToObject(cache->object, 6629 + cache->chunkId, 6630 + cache->data, 6631 + cache->nBytes, 6632 + 1); 5881 + 5882 + if(cache && !cache->locked) 5883 + { 5884 + //Write it out and free it up 5885 + 5886 +#if 0 5887 + nBytes = cache->object->variant.fileVariant.fileSize - ((cache->chunkId -1) * YAFFS_BYTES_PER_CHUNK); 5888 + 5889 + if(nBytes > YAFFS_BYTES_PER_CHUNK) 5890 + { 5891 + nBytes= YAFFS_BYTES_PER_CHUNK; 5892 + } 5893 +#endif 5894 + chunkWritten = yaffs_WriteChunkDataToObject(cache->object, 5895 + cache->chunkId, 5896 + cache->data, 5897 + cache->nBytes,1); 5898 + 6633 5899 + cache->dirty = 0; 6634 5900 + cache->object = NULL; 6635 5901 + } 6636 + 6637 + } while (cache && chunkWritten > 0); 6638 + 6639 + if (cache) { 6640 + /* Hoosterman, disk full while writing cache out. */ 6641 + T(YAFFS_TRACE_ERROR, 6642 + (TSTR("yaffs tragedy: no space during cache write" TENDSTR))); 6643 + 6644 + } 6645 + } 6646 + 6647 +} 6648 + 6649 +/*yaffs_FlushEntireDeviceCache(dev) 6650 + * 6651 + * 6652 + */ 6653 + 6654 +void yaffs_FlushEntireDeviceCache(yaffs_Device *dev) 6655 +{ 6656 + yaffs_Object *obj; 6657 + int nCaches = dev->nShortOpCaches; 6658 + int i; 6659 + 6660 + /* Find a dirty object in the cache and flush it... 6661 + * until there are no further dirty objects. 6662 + */ 6663 + do { 6664 + obj = NULL; 6665 + for( i = 0; i < nCaches && !obj; i++) { 6666 + if (dev->srCache[i].object && 6667 + dev->srCache[i].dirty) 6668 + obj = dev->srCache[i].object; 6669 + 6670 + } 6671 + if(obj) 6672 + yaffs_FlushFilesChunkCache(obj); 6673 + 6674 + } while(obj); 6675 + 6676 +} 6677 + 6678 + 6679 +/* Grab us a cache chunk for use. 6680 + * First look for an empty one. 6681 + * Then look for the least recently used non-dirty one. 6682 + * Then look for the least recently used dirty one...., flush and look again. 6683 + */ 6684 +static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev) 5902 + 5903 + } while(cache && chunkWritten > 0); 5904 + 5905 + if(cache) 5906 + { 5907 + //Hoosterman, disk full while writing cache out. 5908 + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no space during cache write" TENDSTR))); 5909 + 5910 + } 5911 + } 5912 + 5913 +} 5914 + 5915 + 5916 +// Grab us a chunk for use. 5917 +// First look for an empty one. 5918 +// Then look for the least recently used non-dirty one. 5919 +// Then look for the least recently used dirty one...., flush and look again. 5920 +static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev) 6685 5921 +{ 6686 5922 + int i; 6687 5923 + int usage; 6688 5924 + int theOne; 6689 + 6690 + if (dev->nShortOpCaches > 0) { 6691 + for (i = 0; i < dev->nShortOpCaches; i++) { 6692 + if (!dev->srCache[i].object) 5925 + 5926 + if(dev->nShortOpCaches > 0) 5927 + { 5928 + for(i = 0; i < dev->nShortOpCaches; i++) 5929 + { 5930 + if(!dev->srCache[i].object) 5931 + { 5932 + //T(("Grabbing empty %d\n",i)); 5933 + 5934 + //printf("Grabbing empty %d\n",i); 5935 + 6693 5936 + return &dev->srCache[i]; 6694 + } 6695 + 5937 + } 5938 + } 5939 + 6696 5940 + return NULL; 6697 + 6698 + theOne = -1; 6699 + usage = 0; /* just to stop the compiler grizzling */ 6700 + 6701 + for (i = 0; i < dev->nShortOpCaches; i++) { 6702 + if (!dev->srCache[i].dirty && 6703 + ((dev->srCache[i].lastUse < usage && theOne >= 0) || 6704 + theOne < 0)) { 5941 + 5942 + theOne = -1; 5943 + usage = 0; // just to stop the compiler grizzling 5944 + 5945 + for(i = 0; i < dev->nShortOpCaches; i++) 5946 + { 5947 + if(!dev->srCache[i].dirty && 5948 + ((dev->srCache[i].lastUse < usage && theOne >= 0)|| 5949 + theOne < 0)) 5950 + { 6705 5951 + usage = dev->srCache[i].lastUse; 6706 5952 + theOne = i; 6707 5953 + } 6708 5954 + } 6709 + 6710 + 6711 + return theOne >= 0 ? &dev->srCache[theOne] : NULL; 6712 + } else { 5955 + 5956 + //T(("Grabbing non-empty %d\n",theOne)); 5957 + 5958 + //if(theOne >= 0) printf("Grabbed non-empty cache %d\n",theOne); 5959 + 5960 + return theOne >= 0 ? &dev->srCache[theOne] : NULL; 5961 + } 5962 + else 5963 + { 6713 5964 + return NULL; 6714 5965 + } 6715 + 6716 +} 6717 + 6718 +static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev) 5966 + 5967 +} 5968 + 5969 + 5970 +static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev) 6719 5971 +{ 6720 5972 + yaffs_ChunkCache *cache; … … 6723 5975 + int i; 6724 5976 + int pushout; 6725 + 6726 + if (dev->nShortOpCaches > 0) { 6727 + /* Try find a non-dirty one... */ 6728 + 5977 + 5978 + if(dev->nShortOpCaches > 0) 5979 + { 5980 + // Try find a non-dirty one... 5981 + 6729 5982 + cache = yaffs_GrabChunkCacheWorker(dev); 6730 + 6731 + if (!cache) { 6732 + /* They were all dirty, find the last recently used object and flush 6733 + * its cache, then find again. 6734 + * NB what's here is not very accurate, we actually flush the object 6735 + * the last recently used page. 6736 + */ 6737 + 6738 + /* With locking we can't assume we can use entry zero */ 6739 + 5983 + 5984 + if(!cache) 5985 + { 5986 + // They were all dirty, find the last recently used object and flush 5987 + // its cache, then find again. 5988 + // NB what's here is not very accurate, we actually flush the object 5989 + // the last recently used page. 5990 + 5991 + // With locking we can't assume we can use entry zero 5992 + 5993 + 6740 5994 + theObj = NULL; 6741 5995 + usage = -1; 6742 5996 + cache = NULL; 6743 5997 + pushout = -1; 6744 + 6745 + for (i = 0; i < dev->nShortOpCaches; i++) { 6746 + if (dev->srCache[i].object && 6747 + !dev->srCache[i].locked && 6748 + (dev->srCache[i].lastUse < usage || !cache)) 5998 + 5999 + for(i = 0; i < dev->nShortOpCaches; i++) 6000 + { 6001 + if( dev->srCache[i].object && 6002 + !dev->srCache[i].locked && 6003 + (dev->srCache[i].lastUse < usage || !cache)) 6749 6004 + { 6750 + usage = dev->srCache[i].lastUse;6005 + usage = dev->srCache[i].lastUse; 6751 6006 + theObj = dev->srCache[i].object; 6752 6007 + cache = &dev->srCache[i]; … … 6754 6009 + } 6755 6010 + } 6756 + 6757 + if (!cache || cache->dirty) { 6758 + /* Flush and try again */ 6011 + 6012 + if(!cache || cache->dirty) 6013 + { 6014 + 6015 + //printf("Dirty "); 6759 6016 + yaffs_FlushFilesChunkCache(theObj); 6017 + 6018 + // Try again 6760 6019 + cache = yaffs_GrabChunkCacheWorker(dev); 6761 6020 + } 6762 + 6021 + else 6022 + { 6023 + //printf(" pushout %d\n",pushout); 6024 + } 6025 + 6763 6026 + } 6764 6027 + return cache; 6765 + } else 6028 + } 6029 + else 6766 6030 + return NULL; 6767 6031 + 6768 6032 +} 6769 6033 + 6770 + /* Find a cached chunk */6771 + static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object * obj,6772 + int chunkId)6034 + 6035 +// Find a cached chunk 6036 +static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object *obj, int chunkId) 6773 6037 +{ 6774 6038 + yaffs_Device *dev = obj->myDev; 6775 6039 + int i; 6776 + if (dev->nShortOpCaches > 0) { 6777 + for (i = 0; i < dev->nShortOpCaches; i++) { 6778 + if (dev->srCache[i].object == obj && 6779 + dev->srCache[i].chunkId == chunkId) { 6040 + if(dev->nShortOpCaches > 0) 6041 + { 6042 + for(i = 0; i < dev->nShortOpCaches; i++) 6043 + { 6044 + if(dev->srCache[i].object == obj && 6045 + dev->srCache[i].chunkId == chunkId) 6046 + { 6780 6047 + dev->cacheHits++; 6781 + 6048 + 6782 6049 + return &dev->srCache[i]; 6783 6050 + } … … 6787 6054 +} 6788 6055 + 6789 +/* Mark the chunk for the least recently used algorithym */ 6790 +static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache, 6791 + int isAWrite) 6792 +{ 6793 + 6794 + if (dev->nShortOpCaches > 0) { 6795 + if (dev->srLastUse < 0 || dev->srLastUse > 100000000) { 6796 + /* Reset the cache usages */ 6056 +// Mark the chunk for the least recently used algorithym 6057 +static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache, int isAWrite) 6058 +{ 6059 + 6060 + if(dev->nShortOpCaches > 0) 6061 + { 6062 + if( dev->srLastUse < 0 || 6063 + dev->srLastUse > 100000000) 6064 + { 6065 + // Reset the cache usages 6797 6066 + int i; 6798 + for (i = 1; i < dev->nShortOpCaches; i++) { 6067 + for(i = 1; i < dev->nShortOpCaches; i++) 6068 + { 6799 6069 + dev->srCache[i].lastUse = 0; 6800 6070 + } … … 6803 6073 + 6804 6074 + dev->srLastUse++; 6805 + 6075 + 6806 6076 + cache->lastUse = dev->srLastUse; 6807 6077 + 6808 + if (isAWrite) { 6078 + if(isAWrite) 6079 + { 6809 6080 + cache->dirty = 1; 6810 6081 + } … … 6812 6083 +} 6813 6084 + 6814 +/* Invalidate a single cache page. 6815 + * Do this when a whole page gets written, 6816 + * ie the short cache for this page is no longer valid. 6817 + */ 6818 +static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId) 6819 +{ 6820 + if (object->myDev->nShortOpCaches > 0) { 6821 + yaffs_ChunkCache *cache = yaffs_FindChunkCache(object, chunkId); 6822 + 6823 + if (cache) { 6085 +// Invalidate a single cache page. 6086 +// Do this when a whole page gets written, 6087 +// ie the short cache for this page is no longer valid. 6088 +static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId) 6089 +{ 6090 + if(object->myDev->nShortOpCaches > 0) 6091 + { 6092 + yaffs_ChunkCache *cache = yaffs_FindChunkCache(object,chunkId); 6093 + 6094 + if(cache) 6095 + { 6824 6096 + cache->object = NULL; 6825 6097 + } … … 6827 6099 +} 6828 6100 + 6829 + /* Invalidate all the cache pages associated with this object6830 + * Do this whenever ther file is deleted or resized.6831 + */6832 +static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in)6101 + 6102 +// Invalidate all the cache pages associated with this object 6103 +// Do this whenever ther file is deleted or resized. 6104 +static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in) 6833 6105 +{ 6834 6106 + int i; 6835 6107 + yaffs_Device *dev = in->myDev; 6836 + 6837 + if (dev->nShortOpCaches > 0) { 6838 + /* Invalidate it. */ 6839 + for (i = 0; i < dev->nShortOpCaches; i++) { 6840 + if (dev->srCache[i].object == in) { 6108 + 6109 + if(dev->nShortOpCaches > 0) 6110 + { 6111 + // Now invalidate it. 6112 + for(i = 0; i < dev->nShortOpCaches; i++) 6113 + { 6114 + if(dev->srCache[i].object == in) 6115 + { 6841 6116 + dev->srCache[i].object = NULL; 6842 6117 + } … … 6845 6120 +} 6846 6121 + 6847 +/*--------------------- Checkpointing --------------------*/ 6848 + 6849 + 6850 +static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head) 6851 +{ 6852 + yaffs_CheckpointValidity cp; 6853 + cp.structType = sizeof(cp); 6854 + cp.magic = YAFFS_MAGIC; 6855 + cp.version = YAFFS_CHECKPOINT_VERSION; 6856 + cp.head = (head) ? 1 : 0; 6857 + 6858 + return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))? 6859 + 1 : 0; 6860 +} 6861 + 6862 +static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head) 6863 +{ 6864 + yaffs_CheckpointValidity cp; 6865 + int ok; 6866 + 6867 + ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); 6868 + 6869 + if(ok) 6870 + ok = (cp.structType == sizeof(cp)) && 6871 + (cp.magic == YAFFS_MAGIC) && 6872 + (cp.version == YAFFS_CHECKPOINT_VERSION) && 6873 + (cp.head == ((head) ? 1 : 0)); 6874 + return ok ? 1 : 0; 6875 +} 6876 + 6877 +static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, 6878 + yaffs_Device *dev) 6879 +{ 6880 + cp->nErasedBlocks = dev->nErasedBlocks; 6881 + cp->allocationBlock = dev->allocationBlock; 6882 + cp->allocationPage = dev->allocationPage; 6883 + cp->nFreeChunks = dev->nFreeChunks; 6884 + 6885 + cp->nDeletedFiles = dev->nDeletedFiles; 6886 + cp->nUnlinkedFiles = dev->nUnlinkedFiles; 6887 + cp->nBackgroundDeletions = dev->nBackgroundDeletions; 6888 + cp->sequenceNumber = dev->sequenceNumber; 6889 + cp->oldestDirtySequence = dev->oldestDirtySequence; 6890 + 6891 +} 6892 + 6893 +static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev, 6894 + yaffs_CheckpointDevice *cp) 6895 +{ 6896 + dev->nErasedBlocks = cp->nErasedBlocks; 6897 + dev->allocationBlock = cp->allocationBlock; 6898 + dev->allocationPage = cp->allocationPage; 6899 + dev->nFreeChunks = cp->nFreeChunks; 6900 + 6901 + dev->nDeletedFiles = cp->nDeletedFiles; 6902 + dev->nUnlinkedFiles = cp->nUnlinkedFiles; 6903 + dev->nBackgroundDeletions = cp->nBackgroundDeletions; 6904 + dev->sequenceNumber = cp->sequenceNumber; 6905 + dev->oldestDirtySequence = cp->oldestDirtySequence; 6906 +} 6907 + 6908 + 6909 +static int yaffs_WriteCheckpointDevice(yaffs_Device *dev) 6910 +{ 6911 + yaffs_CheckpointDevice cp; 6912 + __u32 nBytes; 6913 + __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1); 6914 + 6915 + int ok; 6916 + 6917 + /* Write device runtime values*/ 6918 + yaffs_DeviceToCheckpointDevice(&cp,dev); 6919 + cp.structType = sizeof(cp); 6920 + 6921 + ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); 6922 + 6923 + /* Write block info */ 6924 + if(ok) { 6925 + nBytes = nBlocks * sizeof(yaffs_BlockInfo); 6926 + ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes); 6927 + } 6928 + 6929 + /* Write chunk bits */ 6930 + if(ok) { 6931 + nBytes = nBlocks * dev->chunkBitmapStride; 6932 + ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes); 6933 + } 6934 + return ok ? 1 : 0; 6935 + 6936 +} 6937 + 6938 +static int yaffs_ReadCheckpointDevice(yaffs_Device *dev) 6939 +{ 6940 + yaffs_CheckpointDevice cp; 6941 + __u32 nBytes; 6942 + __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1); 6943 + 6944 + int ok; 6945 + 6946 + ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); 6947 + if(!ok) 6948 + return 0; 6949 + 6950 + if(cp.structType != sizeof(cp)) 6951 + return 0; 6952 + 6953 + 6954 + yaffs_CheckpointDeviceToDevice(dev,&cp); 6955 + 6956 + nBytes = nBlocks * sizeof(yaffs_BlockInfo); 6957 + 6958 + ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes); 6959 + 6960 + if(!ok) 6961 + return 0; 6962 + nBytes = nBlocks * dev->chunkBitmapStride; 6963 + 6964 + ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes); 6965 + 6966 + return ok ? 1 : 0; 6967 +} 6968 + 6969 +static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp, 6970 + yaffs_Object *obj) 6971 +{ 6972 + 6973 + cp->objectId = obj->objectId; 6974 + cp->parentId = (obj->parent) ? obj->parent->objectId : 0; 6975 + cp->chunkId = obj->chunkId; 6976 + cp->variantType = obj->variantType; 6977 + cp->deleted = obj->deleted; 6978 + cp->softDeleted = obj->softDeleted; 6979 + cp->unlinked = obj->unlinked; 6980 + cp->fake = obj->fake; 6981 + cp->renameAllowed = obj->renameAllowed; 6982 + cp->unlinkAllowed = obj->unlinkAllowed; 6983 + cp->serial = obj->serial; 6984 + cp->nDataChunks = obj->nDataChunks; 6985 + 6986 + if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) 6987 + cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize; 6988 + else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) 6989 + cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId; 6990 +} 6991 + 6992 +static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp) 6993 +{ 6994 + 6995 + yaffs_Object *parent; 6996 + 6997 + obj->objectId = cp->objectId; 6998 + 6999 + if(cp->parentId) 7000 + parent = yaffs_FindOrCreateObjectByNumber( 7001 + obj->myDev, 7002 + cp->parentId, 7003 + YAFFS_OBJECT_TYPE_DIRECTORY); 7004 + else 7005 + parent = NULL; 7006 + 7007 + if(parent) 7008 + yaffs_AddObjectToDirectory(parent, obj); 7009 + 7010 + obj->chunkId = cp->chunkId; 7011 + obj->variantType = cp->variantType; 7012 + obj->deleted = cp->deleted; 7013 + obj->softDeleted = cp->softDeleted; 7014 + obj->unlinked = cp->unlinked; 7015 + obj->fake = cp->fake; 7016 + obj->renameAllowed = cp->renameAllowed; 7017 + obj->unlinkAllowed = cp->unlinkAllowed; 7018 + obj->serial = cp->serial; 7019 + obj->nDataChunks = cp->nDataChunks; 7020 + 7021 + if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) 7022 + obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId; 7023 + else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) 7024 + obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId; 7025 + 7026 + if(obj->objectId >= YAFFS_NOBJECT_BUCKETS) 7027 + obj->lazyLoaded = 1; 7028 +} 7029 + 7030 + 7031 + 7032 +static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn, 7033 + __u32 level, int chunkOffset) 7034 +{ 7035 + int i; 7036 + yaffs_Device *dev = in->myDev; 7037 + int ok = 1; 7038 + int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; 7039 + 7040 + if (tn) { 7041 + if (level > 0) { 7042 + 7043 + for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ 7044 + if (tn->internal[i]) { 7045 + ok = yaffs_CheckpointTnodeWorker(in, 7046 + tn->internal[i], 7047 + level - 1, 7048 + (chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i); 7049 + } 7050 + } 7051 + } else if (level == 0) { 7052 + __u32 baseOffset = chunkOffset << YAFFS_TNODES_LEVEL0_BITS; 7053 + /* printf("write tnode at %d\n",baseOffset); */ 7054 + ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset)); 7055 + if(ok) 7056 + ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes); 7057 + } 7058 + } 7059 + 7060 + return ok; 7061 + 7062 +} 7063 + 7064 +static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj) 7065 +{ 7066 + __u32 endMarker = ~0; 7067 + int ok = 1; 7068 + 7069 + if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){ 7070 + ok = yaffs_CheckpointTnodeWorker(obj, 7071 + obj->variant.fileVariant.top, 7072 + obj->variant.fileVariant.topLevel, 7073 + 0); 7074 + if(ok) 7075 + ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == 7076 + sizeof(endMarker)); 7077 + } 7078 + 7079 + return ok ? 1 : 0; 7080 +} 7081 + 7082 +static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj) 7083 +{ 7084 + __u32 baseChunk; 7085 + int ok = 1; 7086 + yaffs_Device *dev = obj->myDev; 7087 + yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant; 7088 + yaffs_Tnode *tn; 7089 + 7090 + ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); 7091 + 7092 + while(ok && (~baseChunk)){ 7093 + /* Read level 0 tnode */ 7094 + 7095 + /* printf("read tnode at %d\n",baseChunk); */ 7096 + tn = yaffs_GetTnodeRaw(dev); 7097 + if(tn) 7098 + ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) == 7099 + (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); 7100 + else 7101 + ok = 0; 7102 + 7103 + if(tn && ok){ 7104 + ok = yaffs_AddOrFindLevel0Tnode(dev, 7105 + fileStructPtr, 7106 + baseChunk, 7107 + tn) ? 1 : 0; 7108 + } 7109 + 7110 + if(ok) 7111 + ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); 7112 + 7113 + } 7114 + 7115 + return ok ? 1 : 0; 7116 +} 7117 + 7118 + 7119 +static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) 7120 +{ 7121 + yaffs_Object *obj; 7122 + yaffs_CheckpointObject cp; 7123 + int i; 7124 + int ok = 1; 7125 + struct list_head *lh; 7126 + 7127 + 7128 + /* Iterate through the objects in each hash entry, 7129 + * dumping them to the checkpointing stream. 7130 + */ 7131 + 7132 + for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){ 7133 + list_for_each(lh, &dev->objectBucket[i].list) { 7134 + if (lh) { 7135 + obj = list_entry(lh, yaffs_Object, hashLink); 7136 + if (!obj->deferedFree) { 7137 + yaffs_ObjectToCheckpointObject(&cp,obj); 7138 + cp.structType = sizeof(cp); 7139 + 7140 + T(YAFFS_TRACE_CHECKPOINT,( 7141 + TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR), 7142 + cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); 7143 + 7144 + ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); 7145 + 7146 + if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){ 7147 + ok = yaffs_WriteCheckpointTnodes(obj); 7148 + } 7149 + } 7150 + } 7151 + } 7152 + } 7153 + 7154 + /* Dump end of list */ 7155 + memset(&cp,0xFF,sizeof(yaffs_CheckpointObject)); 7156 + cp.structType = sizeof(cp); 7157 + 7158 + if(ok) 7159 + ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); 7160 + 7161 + return ok ? 1 : 0; 7162 +} 7163 + 7164 +static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) 7165 +{ 7166 + yaffs_Object *obj; 7167 + yaffs_CheckpointObject cp; 7168 + int ok = 1; 7169 + int done = 0; 7170 + yaffs_Object *hardList = NULL; 7171 + 7172 + while(ok && !done) { 7173 + ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); 7174 + if(cp.structType != sizeof(cp)) { 7175 + /* printf("structure parsing failed\n"); */ 7176 + ok = 0; 7177 + } 7178 + 7179 + if(ok && cp.objectId == ~0) 7180 + done = 1; 7181 + else if(ok){ 7182 + obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType); 7183 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d obj addr %x" TENDSTR), 7184 + cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); 7185 + if(obj) { 7186 + yaffs_CheckpointObjectToObject(obj,&cp); 7187 + if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) { 7188 + ok = yaffs_ReadCheckpointTnodes(obj); 7189 + } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { 7190 + obj->hardLinks.next = 7191 + (struct list_head *) 7192 + hardList; 7193 + hardList = obj; 7194 + } 7195 + 7196 + } 7197 + } 7198 + } 7199 + 7200 + if(ok) 7201 + yaffs_HardlinkFixup(dev,hardList); 7202 + 7203 + return ok ? 1 : 0; 7204 +} 7205 + 7206 +static int yaffs_WriteCheckpointData(yaffs_Device *dev) 7207 +{ 7208 + 7209 + int ok; 7210 + 7211 + ok = yaffs_CheckpointOpen(dev,1); 7212 + 7213 + if(ok) 7214 + ok = yaffs_WriteCheckpointValidityMarker(dev,1); 7215 + if(ok) 7216 + ok = yaffs_WriteCheckpointDevice(dev); 7217 + if(ok) 7218 + ok = yaffs_WriteCheckpointObjects(dev); 7219 + if(ok) 7220 + ok = yaffs_WriteCheckpointValidityMarker(dev,0); 7221 + 7222 + if(!yaffs_CheckpointClose(dev)) 7223 + ok = 0; 7224 + 7225 + if(ok) 7226 + dev->isCheckpointed = 1; 7227 + else 7228 + dev->isCheckpointed = 0; 7229 + 7230 + return dev->isCheckpointed; 7231 +} 7232 + 7233 +static int yaffs_ReadCheckpointData(yaffs_Device *dev) 7234 +{ 7235 + int ok; 7236 + 7237 + ok = yaffs_CheckpointOpen(dev,0); /* open for read */ 7238 + 7239 + if(ok) 7240 + ok = yaffs_ReadCheckpointValidityMarker(dev,1); 7241 + if(ok) 7242 + ok = yaffs_ReadCheckpointDevice(dev); 7243 + if(ok) 7244 + ok = yaffs_ReadCheckpointObjects(dev); 7245 + if(ok) 7246 + ok = yaffs_ReadCheckpointValidityMarker(dev,0); 7247 + 7248 + 7249 + 7250 + if(!yaffs_CheckpointClose(dev)) 7251 + ok = 0; 7252 + 7253 + if(ok) 7254 + dev->isCheckpointed = 1; 7255 + else 7256 + dev->isCheckpointed = 0; 7257 + 7258 + return ok ? 1 : 0; 7259 + 7260 +} 7261 + 7262 +static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) 7263 +{ 7264 + if(dev->isCheckpointed || 7265 + dev->blocksInCheckpoint > 0){ 7266 + dev->isCheckpointed = 0; 7267 + yaffs_CheckpointInvalidateStream(dev); 7268 + if(dev->superBlock && dev->markSuperBlockDirty) 7269 + dev->markSuperBlockDirty(dev->superBlock); 7270 + } 7271 +} 7272 + 7273 + 7274 +int yaffs_CheckpointSave(yaffs_Device *dev) 7275 +{ 7276 + yaffs_ReportOddballBlocks(dev); 7277 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); 7278 + 7279 + if(!dev->isCheckpointed) 7280 + yaffs_WriteCheckpointData(dev); 7281 + 7282 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); 7283 + 7284 + return dev->isCheckpointed; 7285 +} 7286 + 7287 +int yaffs_CheckpointRestore(yaffs_Device *dev) 7288 +{ 7289 + int retval; 7290 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); 7291 + 7292 + retval = yaffs_ReadCheckpointData(dev); 7293 + 7294 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); 7295 + 7296 + yaffs_ReportOddballBlocks(dev); 7297 + 7298 + return retval; 7299 +} 7300 + 7301 +/*--------------------- File read/write ------------------------ 7302 + * Read and write have very similar structures. 7303 + * In general the read/write has three parts to it 7304 + * An incomplete chunk to start with (if the read/write is not chunk-aligned) 7305 + * Some complete chunks 7306 + * An incomplete chunk to end off with 7307 + * 7308 + * Curve-balls: the first chunk might also be the last chunk. 7309 + */ 7310 + 7311 +int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset, 7312 + int nBytes) 7313 +{ 7314 + 6122 + 6123 + 6124 + 6125 + 6126 +///////////////////////// File read/write /////////////////////////////// 6127 +// Read and write have very similar structures. 6128 +// In general the read/write has three parts to it 6129 +// * An incomplete chunk to start with (if the read/write is not chunk-aligned) 6130 +// * Some complete chunks 6131 +// * An incomplete chunk to end off with 6132 +// 6133 +// Curve-balls: the first chunk might also be the last chunk. 6134 + 6135 +int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nBytes) 6136 +{ 6137 + 6138 + 7315 6139 + int chunk; 7316 6140 + int start; … … 7319 6143 + int nDone = 0; 7320 6144 + yaffs_ChunkCache *cache; 7321 + 6145 + 7322 6146 + yaffs_Device *dev; 7323 + 6147 + 7324 6148 + dev = in->myDev; 7325 + 7326 + while (n > 0) { 7327 + //chunk = offset / dev->nDataBytesPerChunk + 1; 7328 + //start = offset % dev->nDataBytesPerChunk; 7329 + yaffs_AddrToChunk(dev,offset,&chunk,&start); 7330 + chunk++; 7331 + 7332 + /* OK now check for the curveball where the start and end are in 7333 + * the same chunk. 7334 + */ 7335 + if ((start + n) < dev->nDataBytesPerChunk) { 6149 + 6150 + while(n > 0) 6151 + { 6152 + chunk = offset / dev->nBytesPerChunk + 1; // The first chunk is 1 6153 + start = offset % dev->nBytesPerChunk; 6154 + 6155 + // OK now check for the curveball where the start and end are in 6156 + // the same chunk. 6157 + if( (start + n) < dev->nBytesPerChunk) 6158 + { 7336 6159 + nToCopy = n; 7337 + } else { 7338 + nToCopy = dev->nDataBytesPerChunk - start; 7339 + } 7340 + 7341 + cache = yaffs_FindChunkCache(in, chunk); 7342 + 7343 + /* If the chunk is already in the cache or it is less than a whole chunk 7344 + * then use the cache (if there is caching) 7345 + * else bypass the cache. 7346 + */ 7347 + if (cache || nToCopy != dev->nDataBytesPerChunk) { 7348 + if (dev->nShortOpCaches > 0) { 7349 + 7350 + /* If we can't find the data in the cache, then load it up. */ 7351 + 7352 + if (!cache) { 6160 + } 6161 + else 6162 + { 6163 + nToCopy = dev->nBytesPerChunk - start; 6164 + } 6165 + 6166 + cache = yaffs_FindChunkCache(in,chunk); 6167 + 6168 + // If the chunk is already in the cache or it is less than a whole chunk 6169 + // then use the cache (if there is caching) 6170 + // else bypass the cache. 6171 + if( cache || nToCopy != dev->nBytesPerChunk) 6172 + { 6173 + if(dev->nShortOpCaches > 0) 6174 + { 6175 + 6176 + // If we can't find the data in the cache, then load it up. 6177 + 6178 + if(!cache) 6179 + { 7353 6180 + cache = yaffs_GrabChunkCache(in->myDev); 7354 6181 + cache->object = in; … … 7356 6183 + cache->dirty = 0; 7357 6184 + cache->locked = 0; 7358 + yaffs_ReadChunkDataFromObject(in, chunk, 7359 + cache-> 7360 + data); 7361 + cache->nBytes = 0; 6185 + yaffs_ReadChunkDataFromObject(in,chunk,cache->data); 6186 + cache->nBytes = 0; 7362 6187 + } 7363 + 7364 + yaffs_UseChunkCache(dev, cache,0);6188 + 6189 + yaffs_UseChunkCache(dev,cache,0); 7365 6190 + 7366 6191 + cache->locked = 1; … … 7369 6194 + yfsd_UnlockYAFFS(TRUE); 7370 6195 +#endif 7371 + memcpy(buffer, &cache->data[start],nToCopy);6196 + memcpy(buffer,&cache->data[start],nToCopy); 7372 6197 + 7373 6198 +#ifdef CONFIG_YAFFS_WINCE … … 7375 6200 +#endif 7376 6201 + cache->locked = 0; 7377 + } else {7378 + /* Read into the local buffer then copy..*/7379 + 7380 + __u8 *localBuffer =7381 + yaffs_GetTempBuffer(dev, __LINE__);7382 + yaffs_ReadChunkDataFromObject(in, chunk,7383 + localBuffer);6202 + } 6203 + else 6204 + { 6205 + // Read into the local buffer then copy... 6206 + 6207 + __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__); 6208 + yaffs_ReadChunkDataFromObject(in,chunk,localBuffer); 7384 6209 +#ifdef CONFIG_YAFFS_WINCE 7385 6210 + yfsd_UnlockYAFFS(TRUE); 7386 6211 +#endif 7387 + memcpy(buffer, &localBuffer[start],nToCopy);6212 + memcpy(buffer,&localBuffer[start],nToCopy); 7388 6213 + 7389 6214 +#ifdef CONFIG_YAFFS_WINCE 7390 6215 + yfsd_LockYAFFS(TRUE); 7391 6216 +#endif 7392 + yaffs_ReleaseTempBuffer(dev, localBuffer, 7393 + __LINE__); 6217 + yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__); 7394 6218 + } 7395 6219 + 7396 + } else { 6220 + } 6221 + else 6222 + { 7397 6223 +#ifdef CONFIG_YAFFS_WINCE 7398 + __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); 7399 + 7400 + /* Under WinCE can't do direct transfer. Need to use a local buffer. 7401 + * This is because we otherwise screw up WinCE's memory mapper 7402 + */ 7403 + yaffs_ReadChunkDataFromObject(in, chunk, localBuffer); 6224 + __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__); 6225 + 6226 + // Under WinCE can't do direct transfer. Need to use a local buffer. 6227 + // This is because we otherwise screw up WinCE's memory mapper 6228 + yaffs_ReadChunkDataFromObject(in,chunk,localBuffer); 7404 6229 + 7405 6230 +#ifdef CONFIG_YAFFS_WINCE 7406 + yfsd_UnlockYAFFS(TRUE);7407 +#endif 7408 + memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);6231 + yfsd_UnlockYAFFS(TRUE); 6232 +#endif 6233 + memcpy(buffer,localBuffer,dev->nBytesPerChunk); 7409 6234 + 7410 6235 +#ifdef CONFIG_YAFFS_WINCE 7411 + yfsd_LockYAFFS(TRUE);7412 + yaffs_ReleaseTempBuffer(dev, localBuffer,__LINE__);6236 + yfsd_LockYAFFS(TRUE); 6237 + yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__); 7413 6238 +#endif 7414 6239 + 7415 6240 +#else 7416 + / * A full chunk. Read directly into the supplied buffer. */7417 + yaffs_ReadChunkDataFromObject(in, chunk,buffer);7418 +#endif 7419 + } 7420 + 6241 + // A full chunk. Read directly into the supplied buffer. 6242 + yaffs_ReadChunkDataFromObject(in,chunk,buffer); 6243 +#endif 6244 + } 6245 + 7421 6246 + n -= nToCopy; 7422 6247 + offset += nToCopy; 7423 6248 + buffer += nToCopy; 7424 6249 + nDone += nToCopy; 7425 + 7426 + } 7427 + 6250 + 6251 + } 6252 + 7428 6253 + return nDone; 7429 6254 +} 7430 6255 + 7431 +int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, 7432 + int nBytes, int writeThrough) 7433 +{ 7434 + 6256 + 6257 + 6258 +int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, int nBytes, int writeThrough) 6259 +{ 6260 + 7435 6261 + int chunk; 7436 6262 + int start; … … 7442 6268 + int chunkWritten = 0; 7443 6269 + int nBytesRead; 7444 + 6270 + 7445 6271 + yaffs_Device *dev; 7446 + 6272 + 7447 6273 + dev = in->myDev; 7448 + 7449 + while (n > 0 && chunkWritten >= 0) { 7450 + //chunk = offset / dev->nDataBytesPerChunk + 1; 7451 + //start = offset % dev->nDataBytesPerChunk; 7452 + yaffs_AddrToChunk(dev,offset,&chunk,&start); 7453 + chunk++; 7454 + 7455 + /* OK now check for the curveball where the start and end are in 7456 + * the same chunk. 7457 + */ 7458 + 7459 + if ((start + n) < dev->nDataBytesPerChunk) { 6274 + 6275 + 6276 + while(n > 0 && chunkWritten >= 0) 6277 + { 6278 + chunk = offset / dev->nBytesPerChunk + 1; 6279 + start = offset % dev->nBytesPerChunk; 6280 + 6281 + 6282 + // OK now check for the curveball where the start and end are in 6283 + // the same chunk. 6284 + 6285 + if((start + n) < dev->nBytesPerChunk) 6286 + { 7460 6287 + nToCopy = n; 7461 + 7462 + /* Now folks, to calculate how many bytes to write back.... 7463 + * If we're overwriting and not writing to then end of file then 7464 + * we need to write back as much as was there before. 7465 + */ 7466 + 7467 + nBytesRead = 7468 + in->variant.fileVariant.fileSize - 7469 + ((chunk - 1) * dev->nDataBytesPerChunk); 7470 + 7471 + if (nBytesRead > dev->nDataBytesPerChunk) { 7472 + nBytesRead = dev->nDataBytesPerChunk; 6288 + 6289 + // Now folks, to calculate how many bytes to write back.... 6290 + // If we're overwriting and not writing to then end of file then 6291 + // we need to write back as much as was there before. 6292 + 6293 + nBytesRead = in->variant.fileVariant.fileSize - ((chunk -1) * dev->nBytesPerChunk); 6294 + 6295 + if(nBytesRead > dev->nBytesPerChunk) 6296 + { 6297 + nBytesRead = dev->nBytesPerChunk; 7473 6298 + } 7474 + 7475 + nToWriteBack = 7476 + (nBytesRead > 7477 + (start + n)) ? nBytesRead : (start + n); 7478 + 7479 + } else { 7480 + nToCopy = dev->nDataBytesPerChunk - start; 7481 + nToWriteBack = dev->nDataBytesPerChunk; 7482 + } 7483 + 7484 + if (nToCopy != dev->nDataBytesPerChunk) { 7485 + /* An incomplete start or end chunk (or maybe both start and end chunk) */ 7486 + if (dev->nShortOpCaches > 0) { 6299 + 6300 + nToWriteBack = (nBytesRead > (start + n)) ? nBytesRead : (start +n); 6301 + 6302 + } 6303 + else 6304 + { 6305 + nToCopy = dev->nBytesPerChunk - start; 6306 + nToWriteBack = dev->nBytesPerChunk; 6307 + } 6308 + 6309 + if(nToCopy != dev->nBytesPerChunk) 6310 + { 6311 + // An incomplete start or end chunk (or maybe both start and end chunk) 6312 + if(dev->nShortOpCaches > 0) 6313 + { 7487 6314 + yaffs_ChunkCache *cache; 7488 + /* If we can't find the data in the cache, then load the cache */ 7489 + cache = yaffs_FindChunkCache(in, chunk); 7490 + 7491 + if (!cache 7492 + && yaffs_CheckSpaceForAllocation(in-> 7493 + myDev)) { 6315 + // If we can't find the data in the cache, then load it up. 6316 + cache = yaffs_FindChunkCache(in,chunk); 6317 + if(!cache && yaffs_CheckSpaceForAllocation(in->myDev)) 6318 + { 7494 6319 + cache = yaffs_GrabChunkCache(in->myDev); 7495 6320 + cache->object = in; … … 7497 6322 + cache->dirty = 0; 7498 6323 + cache->locked = 0; 7499 + yaffs_ReadChunkDataFromObject(in, chunk, 7500 + cache-> 7501 + data); 6324 + yaffs_ReadChunkDataFromObject(in,chunk,cache->data); 7502 6325 + } 7503 + else if(cache && 7504 + !cache->dirty && 7505 + !yaffs_CheckSpaceForAllocation(in->myDev)){ 7506 + /* Drop the cache if it was a read cache item and 7507 + * no space check has been made for it. 7508 + */ 7509 + cache = NULL; 7510 + } 7511 + 7512 + if (cache) { 7513 + yaffs_UseChunkCache(dev, cache, 1); 6326 + 6327 + if(cache) 6328 + { 6329 + yaffs_UseChunkCache(dev,cache,1); 7514 6330 + cache->locked = 1; 7515 6331 +#ifdef CONFIG_YAFFS_WINCE 7516 + yfsd_UnlockYAFFS(TRUE); 7517 +#endif 7518 + 7519 + memcpy(&cache->data[start], buffer, 7520 + nToCopy); 6332 + yfsd_UnlockYAFFS(TRUE); 6333 +#endif 6334 + 6335 + memcpy(&cache->data[start],buffer,nToCopy); 7521 6336 + 7522 6337 +#ifdef CONFIG_YAFFS_WINCE 7523 + yfsd_LockYAFFS(TRUE);6338 + yfsd_LockYAFFS(TRUE); 7524 6339 +#endif 7525 6340 + cache->locked = 0; 7526 6341 + cache->nBytes = nToWriteBack; 7527 + 7528 + if (writeThrough) { 7529 + chunkWritten = 7530 + yaffs_WriteChunkDataToObject 7531 + (cache->object, 7532 + cache->chunkId, 7533 + cache->data, cache->nBytes, 7534 + 1); 6342 + 6343 + if(writeThrough) 6344 + { 6345 + chunkWritten = yaffs_WriteChunkDataToObject(cache->object, 6346 + cache->chunkId, 6347 + cache->data, 6348 + cache->nBytes,1); 7535 6349 + cache->dirty = 0; 7536 6350 + } 7537 6351 + 7538 + } else {7539 + chunkWritten = -1; /* fail the write */7540 6352 + } 7541 + } else { 7542 + /* An incomplete start or end chunk (or maybe both start and end chunk) 7543 + * Read into the local buffer then copy, then copy over and write back. 7544 + */ 7545 + 7546 + __u8 *localBuffer = 7547 + yaffs_GetTempBuffer(dev, __LINE__); 7548 + 7549 + yaffs_ReadChunkDataFromObject(in, chunk, 7550 + localBuffer); 7551 + 6353 + else 6354 + { 6355 + chunkWritten = -1; // fail the write 6356 + } 6357 + } 6358 + else 6359 + { 6360 + // An incomplete start or end chunk (or maybe both start and end chunk) 6361 + // Read into the local buffer then copy, then copy over and write back. 6362 + 6363 + __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__); 6364 + 6365 + yaffs_ReadChunkDataFromObject(in,chunk,localBuffer); 6366 + 7552 6367 +#ifdef CONFIG_YAFFS_WINCE 7553 6368 + yfsd_UnlockYAFFS(TRUE); 7554 6369 +#endif 7555 + 7556 + memcpy(&localBuffer[start], buffer,nToCopy);7557 + 6370 + 6371 + memcpy(&localBuffer[start],buffer,nToCopy); 6372 + 7558 6373 +#ifdef CONFIG_YAFFS_WINCE 7559 6374 + yfsd_LockYAFFS(TRUE); 7560 6375 +#endif 7561 + chunkWritten = 7562 + yaffs_WriteChunkDataToObject(in, chunk, 7563 + localBuffer, 7564 + nToWriteBack, 7565 + 0); 7566 + 7567 + yaffs_ReleaseTempBuffer(dev, localBuffer, 7568 + __LINE__); 7569 + 6376 + chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,localBuffer,nToWriteBack,0); 6377 + 6378 + yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__); 6379 + 6380 + //T(("Write with readback to chunk %d %d start %d copied %d wrote back %d\n",chunk,chunkWritten,start, nToCopy, nToWriteBack)); 7570 6381 + } 7571 + 7572 + } else { 7573 + 6382 + 6383 + } 6384 + else 6385 + { 6386 + 7574 6387 +#ifdef CONFIG_YAFFS_WINCE 7575 + /* Under WinCE can't do direct transfer. Need to use a local buffer. 7576 + * This is because we otherwise screw up WinCE's memory mapper 7577 + */ 7578 + __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); 6388 + // Under WinCE can't do direct transfer. Need to use a local buffer. 6389 + // This is because we otherwise screw up WinCE's memory mapper 6390 + __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__); 7579 6391 +#ifdef CONFIG_YAFFS_WINCE 7580 + yfsd_UnlockYAFFS(TRUE);7581 +#endif 7582 + memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);6392 + yfsd_UnlockYAFFS(TRUE); 6393 +#endif 6394 + memcpy(localBuffer,buffer,dev->nBytesPerChunk); 7583 6395 +#ifdef CONFIG_YAFFS_WINCE 7584 + yfsd_LockYAFFS(TRUE); 7585 +#endif 7586 + chunkWritten = 7587 + yaffs_WriteChunkDataToObject(in, chunk, localBuffer, 7588 + dev->nDataBytesPerChunk, 7589 + 0); 7590 + yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); 6396 + yfsd_LockYAFFS(TRUE); 6397 +#endif 6398 + chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,localBuffer,dev->nBytesPerChunk,0); 6399 + yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__); 7591 6400 +#else 7592 + /* A full chunk. Write directly from the supplied buffer. */ 7593 + chunkWritten = 7594 + yaffs_WriteChunkDataToObject(in, chunk, buffer, 7595 + dev->nDataBytesPerChunk, 7596 + 0); 7597 +#endif 7598 + /* Since we've overwritten the cached data, we better invalidate it. */ 7599 + yaffs_InvalidateChunkCache(in, chunk); 7600 + } 7601 + 7602 + if (chunkWritten >= 0) { 6401 + // A full chunk. Write directly from the supplied buffer. 6402 + chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,buffer,dev->nBytesPerChunk,0); 6403 +#endif 6404 + // Since we've overwritten the cached data, we better invalidate it. 6405 + yaffs_InvalidateChunkCache(in,chunk); 6406 + //T(("Write to chunk %d %d\n",chunk,chunkWritten)); 6407 + } 6408 + 6409 + if(chunkWritten >= 0) 6410 + { 7603 6411 + n -= nToCopy; 7604 6412 + offset += nToCopy; … … 7606 6414 + nDone += nToCopy; 7607 6415 + } 7608 + 7609 + } 7610 + 7611 + /* Update file object */ 7612 + 7613 + if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize) { 6416 + 6417 + } 6418 + 6419 + // Update file object 6420 + 6421 + if((startOfWrite + nDone) > in->variant.fileVariant.fileSize) 6422 + { 7614 6423 + in->variant.fileVariant.fileSize = (startOfWrite + nDone); 7615 6424 + } 7616 + 6425 + 7617 6426 + in->dirty = 1; 7618 + 6427 + 7619 6428 + return nDone; 7620 6429 +} 7621 6430 + 7622 + 7623 +/* ---------------------- File resizing stuff ------------------ */ 7624 + 7625 +static void yaffs_PruneResizedChunks(yaffs_Object * in, int newSize) 6431 +static void yaffs_PruneResizedChunks(yaffs_Object *in, int newSize) 7626 6432 +{ 7627 6433 + … … 7629 6435 + int oldFileSize = in->variant.fileVariant.fileSize; 7630 6436 + 7631 + int lastDel = 1 + (oldFileSize - 1) / dev->nDataBytesPerChunk; 7632 + 7633 + int startDel = 1 + (newSize + dev->nDataBytesPerChunk - 1) / 7634 + dev->nDataBytesPerChunk; 6437 + 6438 + int lastDel = 1 + (oldFileSize-1)/dev->nBytesPerChunk; 6439 + 6440 + int startDel = 1 + (newSize + dev->nBytesPerChunk - 1)/ 6441 + dev->nBytesPerChunk; 7635 6442 + int i; 7636 6443 + int chunkId; 7637 6444 + 7638 + /* Delete backwards so that we don't end up with holes if 7639 + * power is lost part-way through the operation. 7640 + */ 7641 + for (i = lastDel; i >= startDel; i--) { 7642 + /* NB this could be optimised somewhat, 7643 + * eg. could retrieve the tags and write them without 7644 + * using yaffs_DeleteChunk 7645 + */ 7646 + 7647 + chunkId = yaffs_FindAndDeleteChunkInFile(in, i, NULL); 7648 + if (chunkId > 0) { 7649 + if (chunkId < 7650 + (dev->internalStartBlock * dev->nChunksPerBlock) 7651 + || chunkId >= 7652 + ((dev->internalEndBlock + 7653 + 1) * dev->nChunksPerBlock)) { 7654 + T(YAFFS_TRACE_ALWAYS, 7655 + (TSTR("Found daft chunkId %d for %d" TENDSTR), 7656 + chunkId, i)); 7657 + } else { 6445 + // Delete backwards so that we don't end up with holes if 6446 + // power is lost part-way through the operation. 6447 + for(i = lastDel; i >= startDel; i--) 6448 + { 6449 + // NB this could be optimised somewhat, 6450 + // eg. could retrieve the tags and write them without 6451 + // using yaffs_DeleteChunk 6452 + 6453 + chunkId = yaffs_FindAndDeleteChunkInFile(in,i,NULL); 6454 + if(chunkId > 0) 6455 + { 6456 + if(chunkId < (dev->internalStartBlock * dev->nChunksPerBlock) || 6457 + chunkId >= ((dev->internalEndBlock+1) * dev->nChunksPerBlock)) 6458 + { 6459 + T(YAFFS_TRACE_ALWAYS,(TSTR("Found daft chunkId %d for %d"TENDSTR),chunkId,i)); 6460 + } 6461 + else 6462 + { 7658 6463 + in->nDataChunks--; 7659 + yaffs_DeleteChunk(dev, chunkId, 1,__LINE__);6464 + yaffs_DeleteChunk(dev,chunkId,1,__LINE__); 7660 6465 + } 7661 6466 + } 7662 6467 + } 7663 + 7664 +} 7665 + 7666 +int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)6468 + 6469 +} 6470 + 6471 +int yaffs_ResizeFile(yaffs_Object *in, int newSize) 7667 6472 +{ 7668 6473 + 7669 6474 + int oldFileSize = in->variant.fileVariant.fileSize; 7670 + int newSizeOfPartialChunk; 7671 + int newFullChunks; 7672 + 6475 + int sizeOfPartialChunk; 7673 6476 + yaffs_Device *dev = in->myDev; 7674 6477 + 7675 + yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk); 7676 + 7677 + yaffs_FlushFilesChunkCache(in); 6478 + sizeOfPartialChunk = newSize % dev->nBytesPerChunk; 6479 + 6480 + 6481 + yaffs_FlushFilesChunkCache(in); 7678 6482 + yaffs_InvalidateWholeChunkCache(in); 7679 6483 + 7680 6484 + yaffs_CheckGarbageCollection(dev); 7681 + 7682 + if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { 6485 + 6486 + if(in->variantType != YAFFS_OBJECT_TYPE_FILE) 6487 + { 7683 6488 + return yaffs_GetFileSize(in); 7684 6489 + } 7685 + 7686 + if (newSize == oldFileSize) { 6490 + 6491 + if(newSize < oldFileSize) 6492 + { 6493 + 6494 + yaffs_PruneResizedChunks(in,newSize); 6495 + 6496 + if(sizeOfPartialChunk != 0) 6497 + { 6498 + int lastChunk = 1+ newSize/dev->nBytesPerChunk; 6499 + __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__); 6500 + 6501 + // Got to read and rewrite the last chunk with its new size and zero pad 6502 + yaffs_ReadChunkDataFromObject(in,lastChunk,localBuffer); 6503 + 6504 + memset(localBuffer + sizeOfPartialChunk,0, dev->nBytesPerChunk - sizeOfPartialChunk); 6505 + 6506 + yaffs_WriteChunkDataToObject(in,lastChunk,localBuffer,sizeOfPartialChunk,1); 6507 + 6508 + yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__); 6509 + } 6510 + 6511 + in->variant.fileVariant.fileSize = newSize; 6512 + 6513 + yaffs_PruneFileStructure(dev,&in->variant.fileVariant); 6514 + 6515 + // Write a new object header to show we've shrunk the file 6516 + // Do this only if the file is not in the deleted directories. 6517 + if(in->parent->objectId != YAFFS_OBJECTID_UNLINKED && 6518 + in->parent->objectId != YAFFS_OBJECTID_DELETED 6519 + ) 6520 + { 6521 + yaffs_UpdateObjectHeader(in,NULL, 0, 1,0); 6522 + } 6523 + 6524 + 6525 + return newSize; 6526 + 6527 + } 6528 + else 6529 + { 7687 6530 + return oldFileSize; 7688 6531 + } 7689 + 7690 + if (newSize < oldFileSize) { 7691 + 7692 + yaffs_PruneResizedChunks(in, newSize); 7693 + 7694 + if (newSizeOfPartialChunk != 0) { 7695 + int lastChunk = 1 + newFullChunks; 7696 + 7697 + __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); 7698 + 7699 + /* Got to read and rewrite the last chunk with its new size and zero pad */ 7700 + yaffs_ReadChunkDataFromObject(in, lastChunk, 7701 + localBuffer); 7702 + 7703 + memset(localBuffer + newSizeOfPartialChunk, 0, 7704 + dev->nDataBytesPerChunk - newSizeOfPartialChunk); 7705 + 7706 + yaffs_WriteChunkDataToObject(in, lastChunk, localBuffer, 7707 + newSizeOfPartialChunk, 1); 7708 + 7709 + yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); 7710 + } 7711 + 7712 + in->variant.fileVariant.fileSize = newSize; 7713 + 7714 + yaffs_PruneFileStructure(dev, &in->variant.fileVariant); 7715 + } 7716 + /* Write a new object header. 7717 + * show we've shrunk the file, if need be 7718 + * Do this only if the file is not in the deleted directories. 7719 + */ 7720 + if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED && 7721 + in->parent->objectId != YAFFS_OBJECTID_DELETED) { 7722 + yaffs_UpdateObjectHeader(in, NULL, 0, 7723 + (newSize < oldFileSize) ? 1 : 0, 0); 7724 + } 7725 + 7726 + return newSize; 7727 +} 7728 + 7729 +loff_t yaffs_GetFileSize(yaffs_Object * obj) 6532 +} 6533 + 6534 + 6535 +loff_t yaffs_GetFileSize(yaffs_Object *obj) 7730 6536 +{ 7731 6537 + obj = yaffs_GetEquivalentObject(obj); 7732 + 7733 + switch (obj->variantType) { 7734 + case YAFFS_OBJECT_TYPE_FILE: 7735 + return obj->variant.fileVariant.fileSize; 7736 + case YAFFS_OBJECT_TYPE_SYMLINK: 7737 + return yaffs_strlen(obj->variant.symLinkVariant.alias); 7738 + default: 7739 + return 0; 7740 + } 7741 +} 7742 + 7743 + 7744 + 7745 +int yaffs_FlushFile(yaffs_Object * in, int updateTime) 6538 + 6539 + switch(obj->variantType) 6540 + { 6541 + case YAFFS_OBJECT_TYPE_FILE: 6542 + return obj->variant.fileVariant.fileSize; 6543 + case YAFFS_OBJECT_TYPE_SYMLINK: 6544 + return yaffs_strlen(obj->variant.symLinkVariant.alias); 6545 + default: 6546 + return 0; 6547 + } 6548 +} 6549 + 6550 + 6551 + 6552 +// yaffs_FlushFile() updates the file's 6553 +// objectId in NAND 6554 + 6555 +int yaffs_FlushFile(yaffs_Object *in, int updateTime) 7746 6556 +{ 7747 6557 + int retVal; 7748 + if (in->dirty) { 6558 + if(in->dirty) 6559 + { 6560 + //T(("flushing object header\n")); 6561 + 7749 6562 + yaffs_FlushFilesChunkCache(in); 7750 + if (updateTime) { 6563 + if(updateTime) 6564 + { 7751 6565 +#ifdef CONFIG_YAFFS_WINCE 7752 6566 + yfsd_WinFileTimeNow(in->win_mtime); … … 7758 6572 + } 7759 6573 + 7760 + retVal = 7761 + (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >=7762 + 0) ? YAFFS_OK : YAFFS_FAIL;7763 + } else{6574 + retVal = (yaffs_UpdateObjectHeader(in,NULL,0,0,0) >= 0)? YAFFS_OK : YAFFS_FAIL; 6575 + } 6576 + else 6577 + { 7764 6578 + retVal = YAFFS_OK; 7765 6579 + } 7766 + 6580 + 7767 6581 + return retVal; 7768 + 7769 +} 7770 + 7771 +static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) 7772 +{ 7773 + 7774 + /* First off, invalidate the file's data in the cache, without flushing. */ 6582 + 6583 +} 6584 + 6585 + 6586 +static int yaffs_DoGenericObjectDeletion(yaffs_Object *in) 6587 +{ 6588 + 6589 + // First off, invalidate the file's data in the cache, without flushing. 7775 6590 + yaffs_InvalidateWholeChunkCache(in); 7776 6591 + 7777 + if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) { 7778 + /* Move to the unlinked directory so we have a record that it was deleted. */ 7779 + yaffs_ChangeObjectName(in, in->myDev->deletedDir, NULL, 0, 0); 7780 + 7781 + } 7782 + 6592 + if(in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) 6593 + { 6594 + // Move to the unlinked directory so we have a record that it was deleted. 6595 + yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0,0); 6596 + 6597 + } 6598 + 6599 + 7783 6600 + yaffs_RemoveObjectFromDirectory(in); 7784 + yaffs_DeleteChunk(in->myDev, in->chunkId, 1,__LINE__);6601 + yaffs_DeleteChunk(in->myDev,in->chunkId,1,__LINE__); 7785 6602 + in->chunkId = -1; 6603 +#if 0 6604 +#ifdef __KERNEL__ 6605 + if(in->myInode) 6606 + { 6607 + in->myInode->u.generic_ip = NULL; 6608 + in->myInode = 0; 6609 + } 6610 +#endif 6611 +#endif 7786 6612 + 7787 6613 + yaffs_FreeObject(in); … … 7790 6616 +} 7791 6617 + 7792 +/* yaffs_DeleteFile deletes the whole file data 7793 + * and the inode associated with the file. 7794 + * It does not delete the links associated with the file. 7795 + */ 7796 +static int yaffs_UnlinkFile(yaffs_Object * in) 7797 +{ 7798 + 6618 +// yaffs_DeleteFile deletes the whole file data 6619 +// and the inode associated with the file. 6620 +// It does not delete the links associated with the file. 6621 +static int yaffs_UnlinkFile(yaffs_Object *in) 6622 +{ 6623 + 6624 +#ifdef CONFIG_YAFFS_DISABLE_BACKGROUND_DELETION 6625 + 6626 + // Delete the file data & tnodes 6627 + 6628 + yaffs_DeleteWorker(in, in->variant.fileVariant.top, in->variant.fileVariant.topLevel, 0,NULL); 6629 + 6630 + 6631 + yaffs_FreeTnode(in->myDev,in->variant.fileVariant.top); 6632 + 6633 + return yaffs_DoGenericObjectDeletion(in); 6634 +#else 7799 6635 + int retVal; 7800 + int immediateDeletion = 0; 7801 + 7802 + if (1) { 6636 + int immediateDeletion=0; 6637 + 6638 + if(1) 6639 + { 6640 + //in->unlinked = 1; 6641 + //in->myDev->nUnlinkedFiles++; 6642 + //in->renameAllowed = 0; 7803 6643 +#ifdef __KERNEL__ 7804 + if (!in->myInode) { 6644 + if(!in->myInode) 6645 + { 7805 6646 + immediateDeletion = 1; 7806 6647 + 7807 6648 + } 7808 6649 +#else 7809 + if (in->inUse <= 0) { 6650 + if(in->inUse <= 0) 6651 + { 7810 6652 + immediateDeletion = 1; 7811 6653 + 7812 6654 + } 7813 6655 +#endif 7814 + if (immediateDeletion) { 7815 + retVal = 7816 + yaffs_ChangeObjectName(in, in->myDev->deletedDir, 7817 + NULL, 0, 0); 7818 + T(YAFFS_TRACE_TRACING, 7819 + (TSTR("yaffs: immediate deletion of file %d" TENDSTR), 7820 + in->objectId)); 7821 + in->deleted = 1; 6656 + if(immediateDeletion) 6657 + { 6658 + retVal = yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0,0); 6659 + T(YAFFS_TRACE_TRACING,(TSTR("yaffs: immediate deletion of file %d" TENDSTR),in->objectId)); 6660 + in->deleted=1; 7822 6661 + in->myDev->nDeletedFiles++; 7823 + if (0 && in->myDev->isYaffs2) { 7824 + yaffs_ResizeFile(in, 0); 6662 + if( 0 && in->myDev->isYaffs2) 6663 + { 6664 + yaffs_ResizeFile(in,0); 7825 6665 + } 7826 6666 + yaffs_SoftDeleteFile(in); 7827 + } else {7828 + retVal =7829 + yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,7830 + NULL, 0,0);7831 + } 7832 + 6667 + } 6668 + else 6669 + { 6670 + retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL,0,0); 6671 + } 6672 + 7833 6673 + } 7834 6674 + return retVal; 7835 +} 7836 + 7837 +int yaffs_DeleteFile(yaffs_Object * in) 6675 + 6676 + 6677 +#endif 6678 +} 6679 + 6680 +int yaffs_DeleteFile(yaffs_Object *in) 7838 6681 +{ 7839 6682 + int retVal = YAFFS_OK; 7840 + 7841 + if (in->nDataChunks > 0) { 7842 + /* Use soft deletion if there is data in the file */ 7843 + if (!in->unlinked) { 6683 + 6684 + if(in->nDataChunks > 0) 6685 + { 6686 + // Use soft deletion 6687 + if(!in->unlinked) 6688 + { 7844 6689 + retVal = yaffs_UnlinkFile(in); 7845 6690 + } 7846 + if (retVal == YAFFS_OK && in->unlinked && !in->deleted) { 6691 + if(retVal == YAFFS_OK && 6692 + in->unlinked && 6693 + !in->deleted) 6694 + { 7847 6695 + in->deleted = 1; 7848 6696 + in->myDev->nDeletedFiles++; 7849 6697 + yaffs_SoftDeleteFile(in); 7850 6698 + } 7851 + return in->deleted ? YAFFS_OK : YAFFS_FAIL; 7852 + } else { 7853 + /* The file has no data chunks so we toss it immediately */ 7854 + yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top); 6699 + return in->deleted ? YAFFS_OK : YAFFS_FAIL; 6700 + } 6701 + else 6702 + { 6703 + // The file has no data chunks so we toss it immediately 6704 + yaffs_FreeTnode(in->myDev,in->variant.fileVariant.top); 7855 6705 + in->variant.fileVariant.top = NULL; 7856 + yaffs_DoGenericObjectDeletion(in); 7857 + 7858 + return YAFFS_OK; 7859 + } 7860 +} 7861 + 7862 +static int yaffs_DeleteDirectory(yaffs_Object * in) 7863 +{ 7864 + /* First check that the directory is empty. */ 7865 + if (list_empty(&in->variant.directoryVariant.children)) { 7866 + return yaffs_DoGenericObjectDeletion(in); 7867 + } 7868 + 6706 + yaffs_DoGenericObjectDeletion(in); 6707 + 6708 + return YAFFS_OK; 6709 + } 6710 +} 6711 + 6712 +static int yaffs_DeleteDirectory(yaffs_Object *in) 6713 +{ 6714 + //First check that the directory is empty. 6715 + if(list_empty(&in->variant.directoryVariant.children)) 6716 + { 6717 + return yaffs_DoGenericObjectDeletion(in); 6718 + } 6719 + 7869 6720 + return YAFFS_FAIL; 7870 + 7871 +} 7872 + 7873 +static int yaffs_DeleteSymLink(yaffs_Object * in)6721 + 6722 +} 6723 + 6724 +static int yaffs_DeleteSymLink(yaffs_Object *in) 7874 6725 +{ 7875 6726 + YFREE(in->variant.symLinkVariant.alias); 7876 6727 + 7877 + return yaffs_DoGenericObjectDeletion(in); 7878 +} 7879 + 7880 +static int yaffs_DeleteHardLink(yaffs_Object * in) 7881 +{ 7882 + /* remove this hardlink from the list assocaited with the equivalent 7883 + * object 7884 + */ 6728 + return yaffs_DoGenericObjectDeletion(in); 6729 +} 6730 + 6731 +static int yaffs_DeleteHardLink(yaffs_Object *in) 6732 +{ 6733 + // remove this hardlink from the list assocaited with the equivalent 6734 + // object 7885 6735 + list_del(&in->hardLinks); 7886 + return yaffs_DoGenericObjectDeletion(in); 7887 +} 7888 + 7889 +static void yaffs_DestroyObject(yaffs_Object * obj) 7890 +{ 7891 + switch (obj->variantType) { 7892 + case YAFFS_OBJECT_TYPE_FILE: 7893 + yaffs_DeleteFile(obj); 7894 + break; 7895 + case YAFFS_OBJECT_TYPE_DIRECTORY: 7896 + yaffs_DeleteDirectory(obj); 7897 + break; 7898 + case YAFFS_OBJECT_TYPE_SYMLINK: 7899 + yaffs_DeleteSymLink(obj); 7900 + break; 7901 + case YAFFS_OBJECT_TYPE_HARDLINK: 7902 + yaffs_DeleteHardLink(obj); 7903 + break; 7904 + case YAFFS_OBJECT_TYPE_SPECIAL: 7905 + yaffs_DoGenericObjectDeletion(obj); 7906 + break; 7907 + case YAFFS_OBJECT_TYPE_UNKNOWN: 7908 + break; /* should not happen. */ 7909 + } 7910 +} 7911 + 7912 +static int yaffs_UnlinkWorker(yaffs_Object * obj) 7913 +{ 7914 + 7915 + if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { 7916 + return yaffs_DeleteHardLink(obj); 7917 + } else if (!list_empty(&obj->hardLinks)) { 7918 + /* Curve ball: We're unlinking an object that has a hardlink. 7919 + * 7920 + * This problem arises because we are not strictly following 7921 + * The Linux link/inode model. 7922 + * 7923 + * We can't really delete the object. 7924 + * Instead, we do the following: 7925 + * - Select a hardlink. 7926 + * - Unhook it from the hard links 7927 + * - Unhook it from its parent directory (so that the rename can work) 7928 + * - Rename the object to the hardlink's name. 7929 + * - Delete the hardlink 7930 + */ 7931 + 6736 + return yaffs_DoGenericObjectDeletion(in); 6737 +} 6738 + 6739 + 6740 +static void yaffs_DestroyObject(yaffs_Object *obj) 6741 +{ 6742 + switch(obj->variantType) 6743 + { 6744 + case YAFFS_OBJECT_TYPE_FILE: yaffs_DeleteFile(obj); break; 6745 + case YAFFS_OBJECT_TYPE_DIRECTORY: yaffs_DeleteDirectory(obj); break; 6746 + case YAFFS_OBJECT_TYPE_SYMLINK: yaffs_DeleteSymLink(obj); break; 6747 + case YAFFS_OBJECT_TYPE_HARDLINK: yaffs_DeleteHardLink(obj); break; 6748 + case YAFFS_OBJECT_TYPE_SPECIAL: yaffs_DoGenericObjectDeletion(obj); break; 6749 + case YAFFS_OBJECT_TYPE_UNKNOWN: break; // should not happen. 6750 + } 6751 +} 6752 + 6753 + 6754 +static int yaffs_UnlinkWorker(yaffs_Object *obj) 6755 +{ 6756 + 6757 + 6758 + if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) 6759 + { 6760 + return yaffs_DeleteHardLink(obj); 6761 + } 6762 + else if(!list_empty(&obj->hardLinks)) 6763 + { 6764 + // Curve ball: We're unlinking an object that has a hardlink. 6765 + // 6766 + // This problem arises because we are not strictly following 6767 + // The Linux link/inode model. 6768 + // 6769 + // We can't really delete the object. 6770 + // Instead, we do the following: 6771 + // - Select a hardlink. 6772 + // - Unhook it from the hard links 6773 + // - Unhook it from its parent directory (so that the rename can work) 6774 + // - Rename the object to the hardlink's name. 6775 + // - Delete the hardlink 6776 + 6777 + 7932 6778 + yaffs_Object *hl; 7933 6779 + int retVal; 7934 + YCHAR name[YAFFS_MAX_NAME_LENGTH +1];7935 + 7936 + hl = list_entry(obj->hardLinks.next, yaffs_Object,hardLinks);7937 + 6780 + YCHAR name[YAFFS_MAX_NAME_LENGTH+1]; 6781 + 6782 + hl = list_entry(obj->hardLinks.next,yaffs_Object,hardLinks); 6783 + 7938 6784 + list_del_init(&hl->hardLinks); 7939 6785 + list_del_init(&hl->siblings); 7940 + 7941 + yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1); 7942 + 7943 + retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0); 7944 + 7945 + if (retVal == YAFFS_OK) { 6786 + 6787 + yaffs_GetObjectName(hl,name,YAFFS_MAX_NAME_LENGTH+1); 6788 + 6789 + retVal = yaffs_ChangeObjectName(obj, hl->parent, name,0,0); 6790 + 6791 + if(retVal == YAFFS_OK) 6792 + { 7946 6793 + retVal = yaffs_DoGenericObjectDeletion(hl); 7947 6794 + } 7948 6795 + return retVal; 7949 + 7950 + } else { 7951 + switch (obj->variantType) { 7952 + case YAFFS_OBJECT_TYPE_FILE: 7953 + return yaffs_UnlinkFile(obj); 7954 + break; 7955 + case YAFFS_OBJECT_TYPE_DIRECTORY: 7956 + return yaffs_DeleteDirectory(obj); 7957 + break; 7958 + case YAFFS_OBJECT_TYPE_SYMLINK: 7959 + return yaffs_DeleteSymLink(obj); 7960 + break; 7961 + case YAFFS_OBJECT_TYPE_SPECIAL: 7962 + return yaffs_DoGenericObjectDeletion(obj); 7963 + break; 7964 + case YAFFS_OBJECT_TYPE_HARDLINK: 7965 + case YAFFS_OBJECT_TYPE_UNKNOWN: 7966 + default: 7967 + return YAFFS_FAIL; 7968 + } 7969 + } 7970 +} 7971 + 7972 + 7973 +static int yaffs_UnlinkObject( yaffs_Object *obj) 7974 +{ 7975 + 7976 + if (obj && obj->unlinkAllowed) { 7977 + return yaffs_UnlinkWorker(obj); 7978 + } 7979 + 7980 + return YAFFS_FAIL; 7981 + 7982 +} 7983 +int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name) 6796 + 6797 + } 6798 + else 6799 + { 6800 + switch(obj->variantType) 6801 + { 6802 + case YAFFS_OBJECT_TYPE_FILE: 6803 + return yaffs_UnlinkFile(obj); 6804 + break; 6805 + case YAFFS_OBJECT_TYPE_DIRECTORY: 6806 + return yaffs_DeleteDirectory(obj); 6807 + break; 6808 + case YAFFS_OBJECT_TYPE_SYMLINK: 6809 + return yaffs_DeleteSymLink(obj); 6810 + break; 6811 + case YAFFS_OBJECT_TYPE_SPECIAL: 6812 + return yaffs_DoGenericObjectDeletion(obj); 6813 + break; 6814 + case YAFFS_OBJECT_TYPE_HARDLINK: 6815 + case YAFFS_OBJECT_TYPE_UNKNOWN: 6816 + default: 6817 + return YAFFS_FAIL; 6818 + } 6819 + } 6820 +} 6821 + 6822 +int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name) 7984 6823 +{ 7985 6824 + yaffs_Object *obj; 7986 + 7987 + obj = yaffs_FindObjectByName(dir, name); 7988 + return yaffs_UnlinkObject(obj); 7989 +} 7990 + 7991 +/*----------------------- Initialisation Scanning ---------------------- */ 7992 + 7993 +static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId, 7994 + int backwardScanning) 7995 +{ 7996 + yaffs_Object *obj; 7997 + 7998 + if (!backwardScanning) { 7999 + /* Handle YAFFS1 forward scanning case 8000 + * For YAFFS1 we always do the deletion 8001 + */ 8002 + 8003 + } else { 8004 + /* Handle YAFFS2 case (backward scanning) 8005 + * If the shadowed object exists then ignore. 8006 + */ 8007 + if (yaffs_FindObjectByNumber(dev, objId)) { 8008 + return; 8009 + } 8010 + } 8011 + 8012 + /* Let's create it (if it does not exist) assuming it is a file so that it can do shrinking etc. 8013 + * We put it in unlinked dir to be cleaned up after the scanning 8014 + */ 8015 + obj = 8016 + yaffs_FindOrCreateObjectByNumber(dev, objId, 8017 + YAFFS_OBJECT_TYPE_FILE); 8018 + yaffs_AddObjectToDirectory(dev->unlinkedDir, obj); 8019 + obj->variant.fileVariant.shrinkSize = 0; 8020 + obj->valid = 1; /* So that we don't read any other info for this file */ 8021 + 8022 +} 8023 + 8024 +typedef struct { 6825 + 6826 + obj = yaffs_FindObjectByName(dir,name); 6827 + 6828 + if(obj && obj->unlinkAllowed) 6829 + { 6830 + return yaffs_UnlinkWorker(obj); 6831 + } 6832 + 6833 + return YAFFS_FAIL; 6834 + 6835 +} 6836 + 6837 +//////////////// Initialisation Scanning ///////////////// 6838 + 6839 + 6840 +void yaffs_HandleShadowedObject(yaffs_Device *dev, int objId, int backwardScanning) 6841 +{ 6842 + //Todo 6843 +} 6844 + 6845 +#if 0 6846 +// For now we use the SmartMedia check. 6847 +// We look at the blockStatus byte in the first two chunks 6848 +// These must be 0xFF to pass as OK. 6849 +// todo: this function needs to be modifyable foir different NAND types 6850 +// and different chunk sizes. Suggest make this into a per-device configurable 6851 +// function. 6852 +static int yaffs_IsBlockBad(yaffs_Device *dev, int blk) 6853 +{ 6854 + yaffsExtendedTags *tags; 6855 + 6856 + yaffs_ReadChunkFromNAND(dev,blk * dev->nChunksPerBlock,NULL,&tags,1); 6857 +#if 1 6858 + if(yaffs_CountBits(spare.blockStatus) < 7) 6859 + { 6860 + return 1; 6861 + } 6862 +#else 6863 + if(spare.blockStatus != 0xFF) 6864 + { 6865 + return 1; 6866 + } 6867 +#endif 6868 + yaffs_ReadChunkFromNAND(dev,blk * dev->nChunksPerBlock + 1,NULL,&spare,1); 6869 + 6870 +#if 1 6871 + if(yaffs_CountBits(spare.blockStatus) < 7) 6872 + { 6873 + return 1; 6874 + } 6875 +#else 6876 + if(spare.blockStatus != 0xFF) 6877 + { 6878 + return 1; 6879 + } 6880 +#endif 6881 + 6882 + return 0; 6883 + 6884 +} 6885 + 6886 +#endif 6887 + 6888 + 6889 +typedef struct 6890 +{ 8025 6891 + int seq; 8026 6892 + int block; … … 8028 6894 + 8029 6895 + 8030 +static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList) 8031 +{ 8032 + yaffs_Object *hl; 8033 + yaffs_Object *in; 8034 + 8035 + while (hardList) { 8036 + hl = hardList; 8037 + hardList = (yaffs_Object *) (hardList->hardLinks.next); 8038 + 8039 + in = yaffs_FindObjectByNumber(dev, 8040 + hl->variant.hardLinkVariant. 8041 + equivalentObjectId); 8042 + 8043 + if (in) { 8044 + /* Add the hardlink pointers */ 8045 + hl->variant.hardLinkVariant.equivalentObject = in; 8046 + list_add(&hl->hardLinks, &in->hardLinks); 8047 + } else { 8048 + /* Todo Need to report/handle this better. 8049 + * Got a problem... hardlink to a non-existant object 8050 + */ 8051 + hl->variant.hardLinkVariant.equivalentObject = NULL; 8052 + INIT_LIST_HEAD(&hl->hardLinks); 8053 + 8054 + } 8055 + 8056 + } 8057 + 8058 +} 8059 + 8060 + 8061 + 8062 + 8063 + 8064 +static int ybicmp(const void *a, const void *b){ 8065 + register int aseq = ((yaffs_BlockIndex *)a)->seq; 8066 + register int bseq = ((yaffs_BlockIndex *)b)->seq; 8067 + register int ablock = ((yaffs_BlockIndex *)a)->block; 8068 + register int bblock = ((yaffs_BlockIndex *)b)->block; 8069 + if( aseq == bseq ) 8070 + return ablock - bblock; 8071 + else 8072 + return aseq - bseq; 8073 + 8074 +} 8075 + 8076 +static int yaffs_Scan(yaffs_Device * dev) 6896 + 6897 +static int yaffs_Scan(yaffs_Device *dev) 8077 6898 +{ 8078 6899 + yaffs_ExtendedTags tags; … … 8082 6903 + int endIterator; 8083 6904 + int nBlocksToScan = 0; 8084 + int result; 8085 + 6905 + 8086 6906 + int chunk; 8087 6907 + int c; … … 8091 6911 + yaffs_Object *hl; 8092 6912 + yaffs_BlockInfo *bi; 8093 + int sequenceNumber; 6913 + int sequenceNumber; 8094 6914 + yaffs_ObjectHeader *oh; 8095 6915 + yaffs_Object *in; 8096 6916 + yaffs_Object *parent; 8097 6917 + int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; 8098 + 6918 + 8099 6919 + __u8 *chunkData; 8100 6920 + 8101 6921 + yaffs_BlockIndex *blockIndex = NULL; 8102 6922 + 8103 + if (dev->isYaffs2) { 8104 + T(YAFFS_TRACE_SCAN, 8105 + (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR))); 8106 + return YAFFS_FAIL; 8107 + } 8108 + 8109 + //TODO Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format. 8110 + 8111 + T(YAFFS_TRACE_SCAN, 8112 + (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR), 8113 + dev->internalStartBlock, dev->internalEndBlock)); 8114 + 8115 + chunkData = yaffs_GetTempBuffer(dev, __LINE__); 8116 + 6923 + T(YAFFS_TRACE_SCAN,(TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR),dev->internalStartBlock,dev->internalEndBlock)); 6924 + 6925 + chunkData = yaffs_GetTempBuffer(dev,__LINE__); 6926 + 6927 + 8117 6928 + dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; 8118 + 8119 + if (dev->isYaffs2) { 8120 + blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); 8121 + } 8122 + 8123 + /* Scan all the blocks to determine their state */ 8124 + for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) { 8125 + bi = yaffs_GetBlockInfo(dev, blk); 8126 + yaffs_ClearChunkBits(dev, blk); 6929 + 6930 + if(dev->isYaffs2) 6931 + { 6932 + blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); 6933 + } 6934 + 6935 + 6936 + // Scan all the blocks to determine their state 6937 + for(blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) 6938 + { 6939 + bi = yaffs_GetBlockInfo(dev,blk); 6940 + yaffs_ClearChunkBits(dev,blk); 8127 6941 + bi->pagesInUse = 0; 8128 6942 + bi->softDeletions = 0; 8129 + 8130 + yaffs_QueryInitialBlockState(dev, blk, &state,&sequenceNumber);8131 + 6943 + 6944 + yaffs_QueryInitialBlockState(dev,blk,&state,&sequenceNumber); 6945 + 8132 6946 + bi->blockState = state; 8133 + bi->sequenceNumber = sequenceNumber; 8134 + 8135 + T(YAFFS_TRACE_SCAN_DEBUG, 8136 + (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, 8137 + state, sequenceNumber)); 8138 + 8139 + if (state == YAFFS_BLOCK_STATE_DEAD) { 8140 + T(YAFFS_TRACE_BAD_BLOCKS, 8141 + (TSTR("block %d is bad" TENDSTR), blk)); 8142 + } else if (state == YAFFS_BLOCK_STATE_EMPTY) { 8143 + T(YAFFS_TRACE_SCAN_DEBUG, 8144 + (TSTR("Block empty " TENDSTR))); 6947 + bi->sequenceNumber = sequenceNumber; 6948 + 6949 + T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block scanning block %d state %d seq %d" TENDSTR),blk,state,sequenceNumber)); 6950 + 6951 + if(state == YAFFS_BLOCK_STATE_DEAD) 6952 + { 6953 + T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("block %d is bad" TENDSTR),blk)); 6954 + } 6955 + else if(state == YAFFS_BLOCK_STATE_EMPTY) 6956 + { 6957 + T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block empty " TENDSTR))); 8145 6958 + dev->nErasedBlocks++; 8146 6959 + dev->nFreeChunks += dev->nChunksPerBlock; 8147 + } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { 8148 + 8149 + /* Determine the highest sequence number */ 8150 + if (dev->isYaffs2 && 6960 + } 6961 + else if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) 6962 + { 6963 + 6964 + // Determine the highest sequence number 6965 + if( dev->isYaffs2 && 8151 6966 + sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && 8152 + sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) { 8153 + 6967 + sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) 6968 + { 6969 + 8154 6970 + blockIndex[nBlocksToScan].seq = sequenceNumber; 8155 6971 + blockIndex[nBlocksToScan].block = blk; 8156 + 6972 + 8157 6973 + nBlocksToScan++; 8158 6974 + 8159 + if (sequenceNumber >= dev->sequenceNumber) { 8160 + dev->sequenceNumber = sequenceNumber; 6975 + if(sequenceNumber >= dev->sequenceNumber) 6976 + { 6977 + dev->sequenceNumber = sequenceNumber; 8161 6978 + } 8162 + } else if (dev->isYaffs2) {8163 + /* TODO: Nasty sequence number! */8164 + T(YAFFS_TRACE_SCAN,8165 + (TSTR8166 + ("Block scanning block %d has bad sequence number %d"8167 + TENDSTR), blk, sequenceNumber));8168 +8169 6979 + } 8170 + } 8171 + } 8172 + 8173 + /* Sort the blocks 8174 + * Dungy old bubble sort for now... 8175 + */ 8176 + if (dev->isYaffs2) { 6980 + else if(dev->isYaffs2) 6981 + { 6982 + // TODO: Nasty sequence number! 6983 + T(YAFFS_TRACE_SCAN,(TSTR("Block scanning block %d has bad sequence number %d" TENDSTR),blk,sequenceNumber)); 6984 + 6985 + } 6986 + } 6987 + } 6988 + 6989 + // Sort the blocks 6990 + // Dungy old bubble sort for now... 6991 + if(dev->isYaffs2) 6992 + { 8177 6993 + yaffs_BlockIndex temp; 8178 6994 + int i; 8179 6995 + int j; 8180 + 8181 + for (i = 0; i < nBlocksToScan; i++) 8182 + for (j = i + 1; j < nBlocksToScan; j++) 8183 + if (blockIndex[i].seq > blockIndex[j].seq) { 8184 + temp = blockIndex[j]; 8185 + blockIndex[j] = blockIndex[i]; 8186 + blockIndex[i] = temp; 8187 + } 8188 + } 8189 + 8190 + /* Now scan the blocks looking at the data. */ 8191 + if (dev->isYaffs2) { 6996 + 6997 + for(i = 0; i < nBlocksToScan; i++) 6998 + for(j = i+1; j < nBlocksToScan; j++) 6999 + if(blockIndex[i].seq > blockIndex[j].seq) 7000 + { 7001 + temp = blockIndex[j]; 7002 + blockIndex[j] = blockIndex[i]; 7003 + blockIndex[i] = temp; 7004 + } 7005 + } 7006 + 7007 + 7008 + // Now scan the blocks looking at the data. 7009 + if(dev->isYaffs2) 7010 + { 8192 7011 + startIterator = 0; 8193 + endIterator = nBlocksToScan - 1; 8194 + T(YAFFS_TRACE_SCAN_DEBUG, 8195 + (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan)); 8196 + } else { 7012 + endIterator = nBlocksToScan-1; 7013 + T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan)); 7014 + } 7015 + else 7016 + { 8197 7017 + startIterator = dev->internalStartBlock; 8198 7018 + endIterator = dev->internalEndBlock; 8199 7019 + } 8200 + 8201 + /* For each block.... */ 8202 + for (blockIterator = startIterator; blockIterator <= endIterator; 8203 + blockIterator++) { 8204 + 8205 + if (dev->isYaffs2) { 8206 + /* get the block to scan in the correct order */ 7020 + 7021 + // For each block.... 7022 + for(blockIterator = startIterator; blockIterator <= endIterator; blockIterator++) 7023 + { 7024 + 7025 + if(dev->isYaffs2) 7026 + { 7027 + // get the block to scan in the correct order 8207 7028 + blk = blockIndex[blockIterator].block; 8208 + } else { 7029 + } 7030 + else 7031 + { 8209 7032 + blk = blockIterator; 8210 7033 + } 8211 7034 + 8212 + bi = yaffs_GetBlockInfo(dev, blk); 7035 + 7036 + bi = yaffs_GetBlockInfo(dev,blk); 8213 7037 + state = bi->blockState; 8214 + 7038 + 8215 7039 + deleted = 0; 8216 + 8217 + /* For each chunk in each block that needs scanning....*/ 8218 + for (c = 0; c < dev->nChunksPerBlock && 8219 + state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) { 8220 + /* Read the tags and decide what to do */ 7040 + 7041 + // For each chunk in each block that needs scanning.... 7042 + for(c = 0; c < dev->nChunksPerBlock && 7043 + state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) 7044 + { 7045 + // Read the tags and decide what to do 8221 7046 + chunk = blk * dev->nChunksPerBlock + c; 8222 + 8223 + result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,8224 + &tags);8225 + 8226 + /* Let's have a good look at this chunk... */8227 + 8228 + if (!dev->isYaffs2 && tags.chunkDeleted) {8229 + /* YAFFS1 only...8230 + * A deleted chunk8231 + */7047 + 7048 + yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags); 7049 + 7050 + // Let's have a good look at this chunk... 7051 + 7052 + 7053 + if(!dev->isYaffs2 && tags.chunkDeleted) 7054 + { 7055 + // YAFFS1 only... 7056 + // A deleted chunk 8232 7057 + deleted++; 8233 + dev->nFreeChunks++; 8234 + /*T((" %d %d deleted\n",blk,c)); */ 8235 + } else if (!tags.chunkUsed) { 8236 + /* An unassigned chunk in the block 8237 + * This means that either the block is empty or 8238 + * this is the one being allocated from 8239 + */ 8240 + 8241 + if (c == 0) { 8242 + /* We're looking at the first chunk in the block so the block is unused */ 7058 + dev->nFreeChunks ++; 7059 + //T((" %d %d deleted\n",blk,c)); 7060 + } 7061 + else if(!tags.chunkUsed) 7062 + { 7063 + // An unassigned chunk in the block 7064 + // This means that either the block is empty or 7065 + // this is the one being allocated from 7066 + 7067 + if(c == 0) 7068 + { 7069 + // We're looking at the first chunk in the block so the block is unused 8243 7070 + state = YAFFS_BLOCK_STATE_EMPTY; 8244 7071 + dev->nErasedBlocks++; 8245 + } else { 8246 + /* this is the block being allocated from */ 8247 + T(YAFFS_TRACE_SCAN, 8248 + (TSTR 8249 + (" Allocating from %d %d" TENDSTR), 8250 + blk, c)); 7072 + } 7073 + else 7074 + { 7075 + // this is the block being allocated from 7076 + T(YAFFS_TRACE_SCAN,(TSTR(" Allocating from %d %d" TENDSTR),blk,c)); 8251 7077 + state = YAFFS_BLOCK_STATE_ALLOCATING; 8252 7078 + dev->allocationBlock = blk; 8253 7079 + dev->allocationPage = c; 8254 + dev->allocationBlockFinder = blk; 8255 + /* Set it to here to encourage the allocator to go forth from here. */ 8256 + 8257 + /* Yaffs2 sanity check: 8258 + * This should be the one with the highest sequence number 8259 + */ 8260 + if (dev->isYaffs2 8261 + && (dev->sequenceNumber != 8262 + bi->sequenceNumber)) { 7080 + dev->allocationBlockFinder = blk; // Set it to here to encourage the allocator to 7081 + // go forth from here. 7082 + //Yaffs2 sanity check: 7083 + // This should be the one with the highest sequence number 7084 + if(dev->isYaffs2 && (dev->sequenceNumber != bi->sequenceNumber)) 7085 + { 8263 7086 + T(YAFFS_TRACE_ALWAYS, 8264 + (TSTR 8265 + ("yaffs: Allocation block %d was not highest sequence id:" 8266 + " block seq = %d, dev seq = %d" 8267 + TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber)); 7087 + (TSTR("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d" TENDSTR), 7088 + blk,bi->sequenceNumber,dev->sequenceNumber)); 8268 7089 + } 8269 7090 + } 8270 7091 + 8271 7092 + dev->nFreeChunks += (dev->nChunksPerBlock - c); 8272 + } else if (tags.chunkId > 0) { 8273 + /* chunkId > 0 so it is a data chunk... */ 7093 + } 7094 + else if(tags.chunkId > 0) 7095 + { 7096 + // chunkId > 0 so it is a data chunk... 8274 7097 + unsigned int endpos; 8275 7098 + 8276 + yaffs_SetChunkBit(dev, blk,c);7099 + yaffs_SetChunkBit(dev,blk,c); 8277 7100 + bi->pagesInUse++; 8278 + 8279 + in = yaffs_FindOrCreateObjectByNumber(dev, 8280 + tags. 8281 + objectId, 8282 + YAFFS_OBJECT_TYPE_FILE); 8283 + /* PutChunkIntoFile checks for a clash (two data chunks with 8284 + * the same chunkId). 8285 + */ 8286 + yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, 8287 + 1); 8288 + endpos = 8289 + (tags.chunkId - 1) * dev->nDataBytesPerChunk + 8290 + tags.byteCount; 8291 + if (in->variantType == YAFFS_OBJECT_TYPE_FILE 8292 + && in->variant.fileVariant.scannedFileSize < 8293 + endpos) { 8294 + in->variant.fileVariant. 8295 + scannedFileSize = endpos; 8296 + if (!dev->useHeaderFileSize) { 8297 + in->variant.fileVariant. 8298 + fileSize = 8299 + in->variant.fileVariant. 8300 + scannedFileSize; 7101 + 7102 + in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE); 7103 + // PutChunkIntoFile checks for a clash (two data chunks with 7104 + // the same chunkId). 7105 + yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,1); 7106 + endpos = (tags.chunkId - 1)* dev->nBytesPerChunk + tags.byteCount; 7107 + if(in->variantType == YAFFS_OBJECT_TYPE_FILE && in->variant.fileVariant.scannedFileSize <endpos) 7108 + { 7109 + in->variant.fileVariant.scannedFileSize = endpos; 7110 + if(!dev->useHeaderFileSize) 7111 + { 7112 + in->variant.fileVariant.fileSize = in->variant.fileVariant.scannedFileSize; 8301 7113 + } 8302 7114 + 8303 7115 + } 8304 + /* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); */ 8305 + } else { 8306 + /* chunkId == 0, so it is an ObjectHeader. 8307 + * Thus, we read in the object header and make the object 8308 + */ 8309 + yaffs_SetChunkBit(dev, blk, c); 7116 + //T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); 7117 + } 7118 + else 7119 + { 7120 + // chunkId == 0, so it is an ObjectHeader. 7121 + // Thus, we read in the object header and make the object 7122 + yaffs_SetChunkBit(dev,blk,c); 8310 7123 + bi->pagesInUse++; 8311 + 8312 + result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, 8313 + chunkData, 8314 + NULL); 8315 + 8316 + oh = (yaffs_ObjectHeader *) chunkData; 8317 + 8318 + in = yaffs_FindObjectByNumber(dev, 8319 + tags.objectId); 8320 + if (in && in->variantType != oh->type) { 8321 + /* This should not happen, but somehow 8322 + * Wev'e ended up with an objectId that has been reused but not yet 8323 + * deleted, and worse still it has changed type. Delete the old object. 8324 + */ 8325 + 7124 + 7125 + yaffs_ReadChunkWithTagsFromNAND(dev,chunk,chunkData,NULL); 7126 + 7127 + oh = (yaffs_ObjectHeader *)chunkData; 7128 + 7129 + in = yaffs_FindObjectByNumber(dev,tags.objectId); 7130 + if(in && in->variantType != oh->type) 7131 + { 7132 + // This should not happen, but somehow 7133 + // Wev'e ended up with an objectId that has been reused but not yet 7134 + // deleted, and worse still it has changed type. Delete the old object. 7135 + 8326 7136 + yaffs_DestroyObject(in); 8327 + 7137 + 8328 7138 + in = 0; 8329 7139 + } 8330 + 8331 + in = yaffs_FindOrCreateObjectByNumber(dev, 8332 + tags. 8333 + objectId, 8334 + oh->type); 8335 + 8336 + if (oh->shadowsObject > 0) { 8337 + yaffs_HandleShadowedObject(dev, 8338 + oh-> 8339 + shadowsObject, 8340 + 0); 7140 + 7141 + in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type); 7142 + 7143 + if(oh->shadowsObject > 0) 7144 + { 7145 + yaffs_HandleShadowedObject(dev,oh->shadowsObject,0); 8341 7146 + } 8342 + 8343 + if (in->valid) { 8344 + /* We have already filled this one. We have a duplicate and need to resolve it. */ 8345 + 7147 + 7148 + if(in->valid) 7149 + { 7150 + // We have already filled this one. We have a duplicate and need to resolve it. 7151 + 8346 7152 + unsigned existingSerial = in->serial; 8347 7153 + unsigned newSerial = tags.serialNumber; 8348 + 8349 + if (dev->isYaffs2 || 8350 + ((existingSerial + 1) & 3) == 8351 + newSerial) { 8352 + /* Use new one - destroy the exisiting one */ 8353 + yaffs_DeleteChunk(dev, 8354 + in->chunkId, 8355 + 1, __LINE__); 7154 + 7155 + if( dev->isYaffs2 || 7156 + ((existingSerial+1) & 3) == newSerial) 7157 + { 7158 + // Use new one - destroy the exisiting one 7159 + yaffs_DeleteChunk(dev,in->chunkId,1,__LINE__); 8356 7160 + in->valid = 0; 8357 + } else { 8358 + /* Use existing - destroy this one. */ 8359 + yaffs_DeleteChunk(dev, chunk, 1, 8360 + __LINE__); 7161 + } 7162 + else 7163 + { 7164 + // Use existing - destroy this one. 7165 + yaffs_DeleteChunk(dev,chunk,1,__LINE__); 8361 7166 + } 8362 7167 + } 8363 + 8364 + if (!in->valid && 8365 + (tags.objectId == YAFFS_OBJECTID_ROOT || 8366 + tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) { 8367 + /* We only load some info, don't fiddle with directory structure */ 7168 + 7169 + if(!in->valid && 7170 + (tags.objectId == YAFFS_OBJECTID_ROOT || 7171 + tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) 7172 + { 7173 + // We only load some info, don't fiddle with directory structure 8368 7174 + in->valid = 1; 8369 7175 + in->variantType = oh->type; 8370 + 8371 + in->yst_mode = oh->yst_mode;7176 + 7177 + in->yst_mode = oh->yst_mode; 8372 7178 +#ifdef CONFIG_YAFFS_WINCE 8373 7179 + in->win_atime[0] = oh->win_atime[0]; … … 8378 7184 + in->win_mtime[1] = oh->win_mtime[1]; 8379 7185 +#else 8380 + in->yst_uid = oh->yst_uid;8381 + in->yst_gid = oh->yst_gid;7186 + in->yst_uid = oh->yst_uid; 7187 + in->yst_gid = oh->yst_gid; 8382 7188 + in->yst_atime = oh->yst_atime; 8383 7189 + in->yst_mtime = oh->yst_mtime; … … 8385 7191 + in->yst_rdev = oh->yst_rdev; 8386 7192 +#endif 8387 + in->chunkId = chunk; 8388 + 8389 + } else if (!in->valid) { 8390 + /* we need to load this info */ 8391 + 7193 + in->chunkId = chunk; 7194 + 7195 + } 7196 + else if(!in->valid) 7197 + { 7198 + // we need to load this info 7199 + 8392 7200 + in->valid = 1; 8393 7201 + in->variantType = oh->type; 8394 + 8395 + in->yst_mode = oh->yst_mode;7202 + 7203 + in->yst_mode = oh->yst_mode; 8396 7204 +#ifdef CONFIG_YAFFS_WINCE 8397 7205 + in->win_atime[0] = oh->win_atime[0]; … … 8402 7210 + in->win_mtime[1] = oh->win_mtime[1]; 8403 7211 +#else 8404 + in->yst_uid = oh->yst_uid;8405 + in->yst_gid = oh->yst_gid;7212 + in->yst_uid = oh->yst_uid; 7213 + in->yst_gid = oh->yst_gid; 8406 7214 + in->yst_atime = oh->yst_atime; 8407 7215 + in->yst_mtime = oh->yst_mtime; … … 8409 7217 + in->yst_rdev = oh->yst_rdev; 8410 7218 +#endif 8411 + in->chunkId = chunk;8412 + 8413 + yaffs_SetObjectName(in, oh->name);7219 + in->chunkId = chunk; 7220 + 7221 + yaffs_SetObjectName(in,oh->name); 8414 7222 + in->dirty = 0; 8415 + 8416 + /* directory stuff... 8417 + * hook up to parent 8418 + */ 8419 + 8420 + parent = 8421 + yaffs_FindOrCreateObjectByNumber 8422 + (dev, oh->parentObjectId, 8423 + YAFFS_OBJECT_TYPE_DIRECTORY); 8424 + if (parent->variantType == 8425 + YAFFS_OBJECT_TYPE_UNKNOWN) { 8426 + /* Set up as a directory */ 8427 + parent->variantType = 8428 + YAFFS_OBJECT_TYPE_DIRECTORY; 8429 + INIT_LIST_HEAD(&parent->variant. 8430 + directoryVariant. 8431 + children); 8432 + } else if (parent->variantType != 8433 + YAFFS_OBJECT_TYPE_DIRECTORY) 7223 + 7224 + // directory stuff... 7225 + // hook up to parent 7226 + 7227 + parent = yaffs_FindOrCreateObjectByNumber(dev,oh->parentObjectId,YAFFS_OBJECT_TYPE_DIRECTORY); 7228 + if(parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN) 8434 7229 + { 8435 + /* Hoosterman, another problem.... 8436 + * We're trying to use a non-directory as a directory 8437 + */ 8438 + 8439 + T(YAFFS_TRACE_ERROR, 8440 + (TSTR 8441 + ("yaffs tragedy: attempting to use non-directory as" 8442 + " a directory in scan. Put in lost+found." 8443 + TENDSTR))); 7230 + // Set up as a directory 7231 + parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY; 7232 + INIT_LIST_HEAD(&parent->variant.directoryVariant.children); 7233 + } 7234 + else if(parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) 7235 + { 7236 + // Hoosterman, another problem.... 7237 + // We're trying to use a non-directory as a directory 7238 + 7239 + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR))); 8444 7240 + parent = dev->lostNFoundDir; 8445 7241 + } 8446 + 8447 + yaffs_AddObjectToDirectory(parent, in); 8448 + 8449 + if (0 && (parent == dev->deletedDir || 8450 + parent == dev->unlinkedDir)) { 8451 + in->deleted = 1; /* If it is unlinked at start up then it wants deleting */ 7242 + 7243 + yaffs_AddObjectToDirectory(parent,in); 7244 + 7245 + if(0 && (parent == dev->deletedDir || 7246 + parent == dev->unlinkedDir)) 7247 + { 7248 + in->deleted = 1; // If it is unlinked at start up then it wants deleting 8452 7249 + dev->nDeletedFiles++; 8453 7250 + } 8454 + /* Note re hardlinks. 8455 + * Since we might scan a hardlink before its equivalent object is scanned 8456 + * we put them all in a list. 8457 + * After scanning is complete, we should have all the objects, so we run through this 8458 + * list and fix up all the chains. 8459 + */ 8460 + 8461 + switch (in->variantType) { 8462 + case YAFFS_OBJECT_TYPE_UNKNOWN: 8463 + /* Todo got a problem */ 8464 + break; 8465 + case YAFFS_OBJECT_TYPE_FILE: 8466 + if (dev->isYaffs2 8467 + && oh->isShrink) { 8468 + /* Prune back the shrunken chunks */ 8469 + yaffs_PruneResizedChunks 8470 + (in, oh->fileSize); 8471 + /* Mark the block as having a shrinkHeader */ 8472 + bi->hasShrinkHeader = 1; 8473 + } 8474 + 8475 + if (dev->useHeaderFileSize) 8476 + 8477 + in->variant.fileVariant. 8478 + fileSize = 8479 + oh->fileSize; 8480 + 8481 + break; 8482 + case YAFFS_OBJECT_TYPE_HARDLINK: 8483 + in->variant.hardLinkVariant. 8484 + equivalentObjectId = 8485 + oh->equivalentObjectId; 8486 + in->hardLinks.next = 8487 + (struct list_head *) 8488 + hardList; 8489 + hardList = in; 8490 + break; 8491 + case YAFFS_OBJECT_TYPE_DIRECTORY: 8492 + /* Do nothing */ 8493 + break; 8494 + case YAFFS_OBJECT_TYPE_SPECIAL: 8495 + /* Do nothing */ 8496 + break; 8497 + case YAFFS_OBJECT_TYPE_SYMLINK: 8498 + in->variant.symLinkVariant. 8499 + alias = 8500 + yaffs_CloneString(oh->alias); 8501 + break; 7251 + 7252 + // Note re hardlinks. 7253 + // Since we might scan a hardlink before its equivalent object is scanned 7254 + // we put them all in a list. 7255 + // After scanning is complete, we should have all the objects, so we run through this 7256 + // list and fix up all the chains. 7257 + 7258 + switch(in->variantType) 7259 + { 7260 + case YAFFS_OBJECT_TYPE_UNKNOWN: // Todo got a problem 7261 + break; 7262 + case YAFFS_OBJECT_TYPE_FILE: 7263 + if(dev->isYaffs2 && oh->isShrink) 7264 + { 7265 + // Prune back the shrunken chunks 7266 + yaffs_PruneResizedChunks(in,oh->fileSize); 7267 + // Mark the block as having a shrinkHeader 7268 + bi->hasShrinkHeader = 1; 7269 + } 7270 + 7271 + if(dev->useHeaderFileSize) 7272 + 7273 + in->variant.fileVariant.fileSize = oh->fileSize; 7274 + 7275 + break; 7276 + case YAFFS_OBJECT_TYPE_HARDLINK: 7277 + in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId; 7278 + in->hardLinks.next = (struct list_head *)hardList; 7279 + hardList = in; 7280 + break; 7281 + case YAFFS_OBJECT_TYPE_DIRECTORY: // Do nothing 7282 + break; 7283 + case YAFFS_OBJECT_TYPE_SPECIAL: // Do nothing 7284 + break; 7285 + case YAFFS_OBJECT_TYPE_SYMLINK: // Do nothing 7286 + in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias); 7287 + break; 8502 7288 + } 8503 7289 + 8504 + if (parent == dev->deletedDir) { 7290 + if(parent == dev->deletedDir) 7291 + { 8505 7292 + yaffs_DestroyObject(in); 8506 7293 + bi->hasShrinkHeader = 1; 8507 7294 + } 7295 + //T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType)); 8508 7296 + } 8509 7297 + } 8510 7298 + } 8511 + 8512 + if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { 8513 + /* If we got this far while scanning, then the block is fully allocated.*/ 8514 + state = YAFFS_BLOCK_STATE_FULL; 8515 + } 8516 + 7299 + 7300 + if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) 7301 + { 7302 + // If we got this far while scanning, then the block is fully allocated. 7303 + state = YAFFS_BLOCK_STATE_FULL; 7304 + } 7305 + 8517 7306 + bi->blockState = state; 8518 + 8519 + /* Now let's see if it was dirty */ 8520 + if (bi->pagesInUse == 0 && 8521 + !bi->hasShrinkHeader && 8522 + bi->blockState == YAFFS_BLOCK_STATE_FULL) { 8523 + yaffs_BlockBecameDirty(dev, blk); 8524 + } 8525 + 8526 + } 8527 + 8528 + if (blockIndex) { 7307 + 7308 + // Now let's see if it was dirty 7309 + if( bi->pagesInUse == 0 && 7310 + !bi->hasShrinkHeader && 7311 + bi->blockState == YAFFS_BLOCK_STATE_FULL) 7312 + { 7313 + yaffs_BlockBecameDirty(dev,blk); 7314 + } 7315 + 7316 + } 7317 + 7318 + if(blockIndex) 7319 + { 8529 7320 + YFREE(blockIndex); 8530 7321 + } 8531 7322 + 8532 + 8533 + /* Ok, we've done all the scanning. 8534 + * Fix up the hard link chains. 8535 + * We should now have scanned all the objects, now it's time to add these 8536 + * hardlinks. 8537 + */ 8538 + 8539 + yaffs_HardlinkFixup(dev,hardList); 8540 + 8541 + /* Handle the unlinked files. Since they were left in an unlinked state we should 8542 + * just delete them. 8543 + */ 8544 + { 8545 + struct list_head *i; 7323 + // Ok, we've done all the scanning. 7324 + 7325 + // Fix up the hard link chains. 7326 + // We should now have scanned all the objects, now it's time to add these 7327 + // hardlinks. 7328 + while(hardList) 7329 + { 7330 + hl = hardList; 7331 + hardList = (yaffs_Object *)(hardList->hardLinks.next); 7332 + 7333 + in = yaffs_FindObjectByNumber(dev,hl->variant.hardLinkVariant.equivalentObjectId); 7334 + 7335 + if(in) 7336 + { 7337 + // Add the hardlink pointers 7338 + hl->variant.hardLinkVariant.equivalentObject=in; 7339 + list_add(&hl->hardLinks,&in->hardLinks); 7340 + } 7341 + else 7342 + { 7343 + //Todo Need to report/handle this better. 7344 + // Got a problem... hardlink to a non-existant object 7345 + hl->variant.hardLinkVariant.equivalentObject=NULL; 7346 + INIT_LIST_HEAD(&hl->hardLinks); 7347 + 7348 + } 7349 + 7350 + } 7351 + 7352 + // Handle the unlinked files. Since they were left in an unlinked state we should 7353 + // just delete them. 7354 + { 7355 + struct list_head *i; 8546 7356 + struct list_head *n; 8547 + 7357 + 8548 7358 + yaffs_Object *l; 8549 + / * Soft delete all the unlinked files */8550 + list_for_each_safe(i, n,8551 + &dev->unlinkedDir->variant.directoryVariant.8552 + children) {8553 + if (i){8554 + l = list_entry(i, yaffs_Object, siblings);8555 + yaffs_DestroyObject(l); 7359 + // Soft delete all the unlinked files 7360 + list_for_each_safe(i,n,&dev->unlinkedDir->variant.directoryVariant.children) 7361 + { 7362 + if(i) 7363 + { 7364 + l = list_entry(i, yaffs_Object,siblings); 7365 + yaffs_DestroyObject(l); 8556 7366 + } 8557 + } 8558 + } 8559 + 8560 + yaffs_ReleaseTempBuffer(dev, chunkData,__LINE__);8561 + 8562 + T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));7367 + } 7368 + } 7369 + 7370 + yaffs_ReleaseTempBuffer(dev,chunkData,__LINE__); 7371 + 7372 + T(YAFFS_TRACE_SCAN,(TSTR("yaffs_Scan ends" TENDSTR))); 8563 7373 + 8564 7374 + return YAFFS_OK; 8565 7375 +} 8566 7376 + 8567 +static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) 8568 +{ 8569 + __u8 *chunkData; 8570 + yaffs_ObjectHeader *oh; 8571 + yaffs_Device *dev = in->myDev; 8572 + yaffs_ExtendedTags tags; 8573 + int result; 8574 + 8575 +#if 0 8576 + T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR), 8577 + in->objectId, 8578 + in->lazyLoaded ? "not yet" : "already")); 8579 +#endif 8580 + 8581 + if(in->lazyLoaded){ 8582 + in->lazyLoaded = 0; 8583 + chunkData = yaffs_GetTempBuffer(dev, __LINE__); 8584 + 8585 + result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags); 8586 + oh = (yaffs_ObjectHeader *) chunkData; 8587 + 8588 + in->yst_mode = oh->yst_mode; 8589 +#ifdef CONFIG_YAFFS_WINCE 8590 + in->win_atime[0] = oh->win_atime[0]; 8591 + in->win_ctime[0] = oh->win_ctime[0]; 8592 + in->win_mtime[0] = oh->win_mtime[0]; 8593 + in->win_atime[1] = oh->win_atime[1]; 8594 + in->win_ctime[1] = oh->win_ctime[1]; 8595 + in->win_mtime[1] = oh->win_mtime[1]; 8596 +#else 8597 + in->yst_uid = oh->yst_uid; 8598 + in->yst_gid = oh->yst_gid; 8599 + in->yst_atime = oh->yst_atime; 8600 + in->yst_mtime = oh->yst_mtime; 8601 + in->yst_ctime = oh->yst_ctime; 8602 + in->yst_rdev = oh->yst_rdev; 8603 + 8604 +#endif 8605 + yaffs_SetObjectName(in, oh->name); 8606 + 8607 + if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) 8608 + in->variant.symLinkVariant.alias = 8609 + yaffs_CloneString(oh->alias); 8610 + 8611 + yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__); 8612 + } 8613 +} 8614 + 8615 +static int yaffs_ScanBackwards(yaffs_Device * dev) 7377 + 7378 +static int yaffs_ScanBackwards(yaffs_Device *dev) 8616 7379 +{ 8617 7380 + yaffs_ExtendedTags tags; … … 8621 7384 + int endIterator; 8622 7385 + int nBlocksToScan = 0; 8623 + 7386 + 8624 7387 + int chunk; 8625 + int result;8626 7388 + int c; 8627 7389 + int deleted; 8628 7390 + yaffs_BlockState state; 8629 7391 + yaffs_Object *hardList = NULL; 7392 + yaffs_Object *hl; 8630 7393 + yaffs_BlockInfo *bi; 8631 + int sequenceNumber; 7394 + int sequenceNumber; 8632 7395 + yaffs_ObjectHeader *oh; 8633 7396 + yaffs_Object *in; 8634 7397 + yaffs_Object *parent; 8635 7398 + int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; 8636 + int itsUnlinked;7399 + 8637 7400 + __u8 *chunkData; 8638 +8639 + int fileSize;8640 + int isShrink;8641 + int foundChunksInBlock;8642 + int equivalentObjectId;8643 +8644 7401 + 8645 7402 + yaffs_BlockIndex *blockIndex = NULL; 8646 + int altBlockIndex = 0;8647 + 8648 + if (!dev->isYaffs2) {8649 + T(YAFFS_TRACE_SCAN,8650 + (TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR)));7403 + 7404 + 7405 + if(!dev->isYaffs2) 7406 + { 7407 + T(YAFFS_TRACE_SCAN,(TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR))); 8651 7408 + return YAFFS_FAIL; 8652 7409 + } 8653 + 8654 + T(YAFFS_TRACE_SCAN, 8655 + (TSTR 8656 + ("yaffs_ScanBackwards starts intstartblk %d intendblk %d..." 8657 + TENDSTR), dev->internalStartBlock, dev->internalEndBlock)); 8658 + 8659 + 7410 + 7411 + T(YAFFS_TRACE_SCAN,(TSTR("yaffs_ScanBackwards starts intstartblk %d intendblk %d..." TENDSTR),dev->internalStartBlock,dev->internalEndBlock)); 7412 + 7413 + chunkData = yaffs_GetTempBuffer(dev,__LINE__); 7414 + 7415 + 8660 7416 + dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; 8661 + 8662 + blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); 8663 + 8664 + if(!blockIndex) { 8665 + blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex)); 8666 + altBlockIndex = 1; 8667 + } 8668 + 8669 + if(!blockIndex) { 8670 + T(YAFFS_TRACE_SCAN, 8671 + (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR))); 8672 + return YAFFS_FAIL; 8673 + } 8674 + 8675 + chunkData = yaffs_GetTempBuffer(dev, __LINE__); 8676 + 8677 + /* Scan all the blocks to determine their state */ 8678 + for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) { 8679 + bi = yaffs_GetBlockInfo(dev, blk); 8680 + yaffs_ClearChunkBits(dev, blk); 7417 + 7418 + blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); 7419 + 7420 + 7421 + // Scan all the blocks to determine their state 7422 + for(blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) 7423 + { 7424 + bi = yaffs_GetBlockInfo(dev,blk); 7425 + yaffs_ClearChunkBits(dev,blk); 8681 7426 + bi->pagesInUse = 0; 8682 7427 + bi->softDeletions = 0; 8683 + 8684 + yaffs_QueryInitialBlockState(dev, blk, &state,&sequenceNumber);8685 + 7428 + 7429 + yaffs_QueryInitialBlockState(dev,blk,&state,&sequenceNumber); 7430 + 8686 7431 + bi->blockState = state; 8687 + bi->sequenceNumber = sequenceNumber; 8688 + 8689 + if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) 8690 + bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT; 8691 + 8692 + T(YAFFS_TRACE_SCAN_DEBUG, 8693 + (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, 8694 + state, sequenceNumber)); 8695 + 8696 + 8697 + if(state == YAFFS_BLOCK_STATE_CHECKPOINT){ 8698 + /* todo .. fix free space ? */ 8699 + 8700 + } else if (state == YAFFS_BLOCK_STATE_DEAD) { 8701 + T(YAFFS_TRACE_BAD_BLOCKS, 8702 + (TSTR("block %d is bad" TENDSTR), blk)); 8703 + } else if (state == YAFFS_BLOCK_STATE_EMPTY) { 8704 + T(YAFFS_TRACE_SCAN_DEBUG, 8705 + (TSTR("Block empty " TENDSTR))); 7432 + bi->sequenceNumber = sequenceNumber; 7433 + 7434 + T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block scanning block %d state %d seq %d" TENDSTR),blk,state,sequenceNumber)); 7435 + 7436 + if(state == YAFFS_BLOCK_STATE_DEAD) 7437 + { 7438 + T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("block %d is bad" TENDSTR),blk)); 7439 + } 7440 + else if(state == YAFFS_BLOCK_STATE_EMPTY) 7441 + { 7442 + T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block empty " TENDSTR))); 8706 7443 + dev->nErasedBlocks++; 8707 7444 + dev->nFreeChunks += dev->nChunksPerBlock; 8708 + } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { 8709 + 8710 + /* Determine the highest sequence number */ 8711 + if (dev->isYaffs2 && 7445 + } 7446 + else if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) 7447 + { 7448 + 7449 + // Determine the highest sequence number 7450 + if( dev->isYaffs2 && 8712 7451 + sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && 8713 + sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) { 8714 + 7452 + sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) 7453 + { 7454 + 8715 7455 + blockIndex[nBlocksToScan].seq = sequenceNumber; 8716 7456 + blockIndex[nBlocksToScan].block = blk; 8717 + 7457 + 8718 7458 + nBlocksToScan++; 8719 7459 + 8720 + if (sequenceNumber >= dev->sequenceNumber) { 8721 + dev->sequenceNumber = sequenceNumber; 7460 + if(sequenceNumber >= dev->sequenceNumber) 7461 + { 7462 + dev->sequenceNumber = sequenceNumber; 8722 7463 + } 8723 + } else if (dev->isYaffs2) {8724 + /* TODO: Nasty sequence number! */8725 + T(YAFFS_TRACE_SCAN,8726 + (TSTR8727 + ("Block scanning block %d has bad sequence number %d"8728 + TENDSTR), blk, sequenceNumber));8729 +8730 7464 + } 8731 + } 8732 + } 8733 + 8734 + T(YAFFS_TRACE_SCAN, 8735 + (TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan)); 8736 + 8737 + 8738 + 8739 + YYIELD(); 8740 + 8741 + /* Sort the blocks */ 8742 +#ifndef CONFIG_YAFFS_USE_OWN_SORT 8743 + { 8744 + /* Use qsort now. */ 8745 + qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp); 8746 + } 8747 +#else 8748 + { 8749 + /* Dungy old bubble sort... */ 8750 + 7465 + else if(dev->isYaffs2) 7466 + { 7467 + // TODO: Nasty sequence number! 7468 + T(YAFFS_TRACE_SCAN,(TSTR("Block scanning block %d has bad sequence number %d" TENDSTR),blk,sequenceNumber)); 7469 + 7470 + } 7471 + } 7472 + } 7473 + 7474 + // Sort the blocks 7475 + // Dungy old bubble sort for now... 7476 + { 8751 7477 + yaffs_BlockIndex temp; 8752 7478 + int i; 8753 7479 + int j; 8754 + 8755 + for (i = 0; i < nBlocksToScan; i++) 8756 + for (j = i + 1; j < nBlocksToScan; j++) 8757 + if (blockIndex[i].seq > blockIndex[j].seq) { 8758 + temp = blockIndex[j]; 8759 + blockIndex[j] = blockIndex[i]; 8760 + blockIndex[i] = temp; 8761 + } 8762 + } 8763 +#endif 8764 + 8765 + YYIELD(); 8766 + 8767 + T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR))); 8768 + 8769 + /* Now scan the blocks looking at the data. */ 7480 + 7481 + for(i = 0; i < nBlocksToScan; i++) 7482 + for(j = i+1; j < nBlocksToScan; j++) 7483 + if(blockIndex[i].seq > blockIndex[j].seq) 7484 + { 7485 + temp = blockIndex[j]; 7486 + blockIndex[j] = blockIndex[i]; 7487 + blockIndex[i] = temp; 7488 + } 7489 + } 7490 + 7491 + 7492 + // Now scan the blocks looking at the data. 8770 7493 + startIterator = 0; 8771 + endIterator = nBlocksToScan - 1; 8772 + T(YAFFS_TRACE_SCAN_DEBUG, 8773 + (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan)); 8774 + 8775 + /* For each block.... backwards */ 8776 + for (blockIterator = endIterator; blockIterator >= startIterator; 8777 + blockIterator--) { 8778 + /* Cooperative multitasking! This loop can run for so 8779 + long that watchdog timers expire. */ 8780 + YYIELD(); 8781 + 8782 + /* get the block to scan in the correct order */ 7494 + endIterator = nBlocksToScan-1; 7495 + T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan)); 7496 + 7497 + 7498 + // For each block.... backwards 7499 + for(blockIterator = endIterator; blockIterator >= startIterator; blockIterator--) 7500 + { 7501 + 7502 + // get the block to scan in the correct order 8783 7503 + blk = blockIndex[blockIterator].block; 8784 7504 + 8785 + bi = yaffs_GetBlockInfo(dev, blk); 7505 + 7506 + bi = yaffs_GetBlockInfo(dev,blk); 8786 7507 + state = bi->blockState; 8787 + 7508 + 8788 7509 + deleted = 0; 8789 + 8790 + /* For each chunk in each block that needs scanning.... */ 8791 + foundChunksInBlock = 0; 8792 + for (c = dev->nChunksPerBlock - 1; c >= 0 && 8793 + (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING || 8794 + state == YAFFS_BLOCK_STATE_ALLOCATING); c--) { 8795 + /* Scan backwards... 8796 + * Read the tags and decide what to do 8797 + */ 7510 + 7511 + if( 0 && // Disable since this is redundant. 7512 + state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) 7513 + { 7514 + // Let's look at the first chunk in the block 7515 + chunk = blk * dev->nChunksPerBlock; 7516 + 7517 + yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags); 7518 + 7519 + // Let's have a good look at this chunk... 7520 + 7521 + if(!tags.chunkUsed) 7522 + { 7523 + // An unassigned chunk in the block 7524 + // This means that either the block is empty or 7525 + // this is the one being allocated from 7526 + 7527 + // We're looking at the first chunk in the block so the block is unused 7528 + state = YAFFS_BLOCK_STATE_EMPTY; 7529 + dev->nErasedBlocks++; 7530 + dev->nFreeChunks += dev->nChunksPerBlock; 7531 + } 7532 + 7533 + } 7534 + 7535 + // For each chunk in each block that needs scanning.... 7536 + for(c = dev->nChunksPerBlock-1; c >= 0 && 7537 + (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING || 7538 + state == YAFFS_BLOCK_STATE_ALLOCATING); c--) 7539 + { 7540 + // Scan backwards... 7541 + // Read the tags and decide what to do 8798 7542 + chunk = blk * dev->nChunksPerBlock + c; 8799 + 8800 + result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL, 8801 + &tags); 8802 + 8803 + /* Let's have a good look at this chunk... */ 8804 + 8805 + if (!tags.chunkUsed) { 8806 + /* An unassigned chunk in the block. 8807 + * If there are used chunks after this one, then 8808 + * it is a chunk that was skipped due to failing the erased 8809 + * check. Just skip it so that it can be deleted. 8810 + * But, more typically, We get here when this is an unallocated 8811 + * chunk and his means that either the block is empty or 8812 + * this is the one being allocated from 8813 + */ 8814 + 8815 + if(foundChunksInBlock) 7543 + 7544 + yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags); 7545 + 7546 + // Let's have a good look at this chunk... 7547 + 7548 + if(!tags.chunkUsed) 7549 + { 7550 + // An unassigned chunk in the block 7551 + // This means that either the block is empty or 7552 + // this is the one being allocated from 7553 + 7554 + if(c == 0) 8816 7555 + { 8817 + /* This is a chunk that was skipped due to failing the erased check */ 8818 + 8819 + } else if (c == 0) { 8820 + /* We're looking at the first chunk in the block so the block is unused */ 7556 + // We're looking at the first chunk in the block so the block is unused 8821 7557 + state = YAFFS_BLOCK_STATE_EMPTY; 8822 7558 + dev->nErasedBlocks++; 8823 + } else { 8824 + if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING || 8825 + state == YAFFS_BLOCK_STATE_ALLOCATING) { 8826 + if(dev->sequenceNumber == bi->sequenceNumber) { 8827 + /* this is the block being allocated from */ 8828 + 8829 + T(YAFFS_TRACE_SCAN, 8830 + (TSTR 8831 + (" Allocating from %d %d" 8832 + TENDSTR), blk, c)); 8833 + 8834 + state = YAFFS_BLOCK_STATE_ALLOCATING; 8835 + dev->allocationBlock = blk; 8836 + dev->allocationPage = c; 8837 + dev->allocationBlockFinder = blk; 8838 + } 8839 + else { 8840 + /* This is a partially written block that is not 8841 + * the current allocation block. This block must have 8842 + * had a write failure, so set up for retirement. 8843 + */ 8844 + 8845 + bi->needsRetiring = 1; 8846 + bi->gcPrioritise = 1; 8847 + 8848 + T(YAFFS_TRACE_ALWAYS, 8849 + (TSTR("Partially written block %d being set for retirement" TENDSTR), 8850 + blk)); 8851 + } 8852 + 7559 + } 7560 + else 7561 + { 7562 + // this is the block being allocated from 7563 + if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) 7564 + { 7565 + T(YAFFS_TRACE_SCAN,(TSTR(" Allocating from %d %d" TENDSTR),blk,c)); 8853 7566 + } 8854 + 7567 + state = YAFFS_BLOCK_STATE_ALLOCATING; 7568 + dev->allocationBlock = blk; 7569 + dev->allocationPage = c; 7570 + dev->allocationBlockFinder = blk; // Set it to here to encourage the allocator to 7571 + // go forth from here. 7572 + //Yaffs2 sanity check: 7573 + // This should be the one with the highest sequence number 7574 + if(dev->isYaffs2 && (dev->sequenceNumber != bi->sequenceNumber)) 7575 + { 7576 + T(YAFFS_TRACE_ALWAYS, 7577 + (TSTR("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d" TENDSTR), 7578 + blk,bi->sequenceNumber,dev->sequenceNumber)); 7579 + } 8855 7580 + } 8856 7581 + 8857 + dev->nFreeChunks++; 7582 + dev->nFreeChunks ++; 7583 + } 7584 + else if(tags.chunkId > 0) 7585 + { 7586 + // chunkId > 0 so it is a data chunk... 7587 + unsigned int endpos; 8858 7588 + 8859 + } else if (tags.chunkId > 0) { 8860 + /* chunkId > 0 so it is a data chunk... */ 8861 + unsigned int endpos; 8862 + __u32 chunkBase = 8863 + (tags.chunkId - 1) * dev->nDataBytesPerChunk; 7589 + __u32 chunkBase = (tags.chunkId - 1)* dev->nBytesPerChunk; 7590 + 7591 + yaffs_SetChunkBit(dev,blk,c); 7592 + bi->pagesInUse++; 8864 7593 + 8865 + foundChunksInBlock = 1; 8866 + 8867 + 8868 + yaffs_SetChunkBit(dev, blk, c); 7594 + in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE); 7595 + if(in->variantType == YAFFS_OBJECT_TYPE_FILE && 7596 + chunkBase < in->variant.fileVariant.shrinkSize) 7597 + { 7598 + // This has not been invalidated by a resize 7599 + yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,-1); 7600 + 7601 + 7602 + // File size is calculated by looking at the data chunks if we have not 7603 + // seen an object header yet. Stop this practice once we find an object header. 7604 + endpos = (tags.chunkId - 1)* dev->nBytesPerChunk + tags.byteCount; 7605 + if(!in->valid && // have not got an object header yet 7606 + in->variant.fileVariant.scannedFileSize <endpos) 7607 + { 7608 + in->variant.fileVariant.scannedFileSize = endpos; 7609 + in->variant.fileVariant.fileSize = in->variant.fileVariant.scannedFileSize; 7610 + } 7611 + 7612 + } 7613 + else 7614 + { 7615 + // This chunk has been invalidated by a resize, so delete 7616 + yaffs_DeleteChunk(dev,chunk,1,__LINE__); 7617 + 7618 + 7619 + } 7620 + //T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); 7621 + } 7622 + else 7623 + { 7624 + // chunkId == 0, so it is an ObjectHeader. 7625 + // Thus, we read in the object header and make the object 7626 + yaffs_SetChunkBit(dev,blk,c); 8869 7627 + bi->pagesInUse++; 8870 + 8871 + in = yaffs_FindOrCreateObjectByNumber(dev, 8872 + tags. 8873 + objectId, 8874 + YAFFS_OBJECT_TYPE_FILE); 8875 + if (in->variantType == YAFFS_OBJECT_TYPE_FILE 8876 + && chunkBase < 8877 + in->variant.fileVariant.shrinkSize) { 8878 + /* This has not been invalidated by a resize */ 8879 + yaffs_PutChunkIntoFile(in, tags.chunkId, 8880 + chunk, -1); 8881 + 8882 + /* File size is calculated by looking at the data chunks if we have not 8883 + * seen an object header yet. Stop this practice once we find an object header. 8884 + */ 8885 + endpos = 8886 + (tags.chunkId - 8887 + 1) * dev->nDataBytesPerChunk + 8888 + tags.byteCount; 8889 + 8890 + if (!in->valid && /* have not got an object header yet */ 8891 + in->variant.fileVariant. 8892 + scannedFileSize < endpos) { 8893 + in->variant.fileVariant. 8894 + scannedFileSize = endpos; 8895 + in->variant.fileVariant. 8896 + fileSize = 8897 + in->variant.fileVariant. 8898 + scannedFileSize; 8899 + } 8900 + 8901 + } else { 8902 + /* This chunk has been invalidated by a resize, so delete */ 8903 + yaffs_DeleteChunk(dev, chunk, 1, __LINE__); 8904 + 8905 + } 8906 + } else { 8907 + /* chunkId == 0, so it is an ObjectHeader. 8908 + * Thus, we read in the object header and make the object 8909 + */ 8910 + foundChunksInBlock = 1; 8911 + 8912 + yaffs_SetChunkBit(dev, blk, c); 8913 + bi->pagesInUse++; 8914 + 7628 + 8915 7629 + oh = NULL; 8916 7630 + in = NULL; 8917 + 8918 + if (tags.extraHeaderInfoAvailable) { 8919 + in = yaffs_FindOrCreateObjectByNumber 8920 + (dev, tags.objectId, 8921 + tags.extraObjectType); 7631 + 7632 + if(tags.extraHeaderInfoAvailable) 7633 + { 7634 + in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,tags.extraObjectType); 8922 7635 + } 8923 7636 + 8924 + if (!in || 8925 +#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD 8926 + !in->valid || 8927 +#endif 8928 + tags.extraShadows || 8929 + (!in->valid && 8930 + (tags.objectId == YAFFS_OBJECTID_ROOT || 8931 + tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) 8932 + ) { 8933 + 8934 + /* If we don't have valid info then we need to read the chunk 8935 + * TODO In future we can probably defer reading the chunk and 8936 + * living with invalid data until needed. 8937 + */ 8938 + 8939 + result = yaffs_ReadChunkWithTagsFromNAND(dev, 8940 + chunk, 8941 + chunkData, 8942 + NULL); 8943 + 8944 + oh = (yaffs_ObjectHeader *) chunkData; 8945 + 8946 + if (!in) 8947 + in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type); 8948 + 7637 + 7638 + if(!in || !in->valid) 7639 + { 7640 + 7641 + // If we don't have valid info then we need to read the chunk 7642 + // TODO In future we can probably defer reading the chunk and 7643 + // living with invalid data until needed. 7644 + 7645 + yaffs_ReadChunkWithTagsFromNAND(dev,chunk,chunkData,NULL); 7646 + 7647 + oh = (yaffs_ObjectHeader *)chunkData; 7648 + 7649 + if(!in) 7650 + in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type); 7651 + 8949 7652 + } 8950 + 8951 + if (!in) { 8952 + /* TODO Hoosterman we have a problem! */ 8953 + T(YAFFS_TRACE_ERROR, 8954 + (TSTR 8955 + ("yaffs tragedy: Could not make object for object %d " 8956 + "at chunk %d during scan" 8957 + TENDSTR), tags.objectId, chunk)); 7653 + 7654 + if(!in) 7655 + { 7656 + // TODO Hoosterman we have a problem! 7657 + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: Could not make object for object %d at chunk %d during scan" TENDSTR),tags.objectId,chunk)); 8958 7658 + 8959 7659 + } 8960 + 8961 + if (in->valid) { 8962 + /* We have already filled this one. 8963 + * We have a duplicate that will be discarded, but 8964 + * we first have to suck out resize info if it is a file. 8965 + */ 8966 + 8967 + if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && 8968 + ((oh && 8969 + oh-> type == YAFFS_OBJECT_TYPE_FILE)|| 8970 + (tags.extraHeaderInfoAvailable && 8971 + tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE)) 8972 + ) { 8973 + __u32 thisSize = 8974 + (oh) ? oh->fileSize : tags. 8975 + extraFileLength; 8976 + __u32 parentObjectId = 8977 + (oh) ? oh-> 8978 + parentObjectId : tags. 8979 + extraParentObjectId; 8980 + unsigned isShrink = 8981 + (oh) ? oh->isShrink : tags. 8982 + extraIsShrinkHeader; 8983 + 8984 + /* If it is deleted (unlinked at start also means deleted) 8985 + * we treat the file size as being zeroed at this point. 8986 + */ 8987 + if (parentObjectId == 8988 + YAFFS_OBJECTID_DELETED 8989 + || parentObjectId == 8990 + YAFFS_OBJECTID_UNLINKED) { 7660 + 7661 + if(in->valid) 7662 + { 7663 + // We have already filled this one. We have a duplicate that will be discarded, but 7664 + // we first have to suck out resize info if it is a file. 7665 + 7666 + if( (in->variantType == YAFFS_OBJECT_TYPE_FILE) && 7667 + ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) || 7668 + (tags.extraHeaderInfoAvailable && tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE)) 7669 + ) 7670 + { 7671 + __u32 thisSize = (oh) ? oh->fileSize : tags.extraFileLength; 7672 + __u32 parentObjectId = (oh) ? oh->parentObjectId : tags.extraParentObjectId; 7673 + unsigned isShrink = (oh) ? oh->isShrink : tags.extraIsShrinkHeader; 7674 + 7675 + // If it is deleted (unlinked at start also means deleted) 7676 + // we treat the file size as being zeroed at this point. 7677 + if(parentObjectId == YAFFS_OBJECTID_DELETED || 7678 + parentObjectId == YAFFS_OBJECTID_UNLINKED) 7679 + { 8991 7680 + thisSize = 0; 8992 7681 + isShrink = 1; 8993 7682 + } 8994 + 8995 + if (isShrink && 8996 + in->variant.fileVariant. 8997 + shrinkSize > thisSize) { 8998 + in->variant.fileVariant. 8999 + shrinkSize = 9000 + thisSize; 7683 + 7684 + if(isShrink && 7685 + in->variant.fileVariant.shrinkSize > thisSize) 7686 + { 7687 + in->variant.fileVariant.shrinkSize = thisSize; 9001 7688 + } 9002 + 9003 + if (isShrink) { 7689 + 7690 + if(isShrink) 7691 + { 9004 7692 + bi->hasShrinkHeader = 1; 9005 7693 + } 9006 + 7694 + 9007 7695 + } 9008 + / * Use existing - destroy this one. */9009 + yaffs_DeleteChunk(dev, chunk, 1,__LINE__);9010 + 7696 + // Use existing - destroy this one. 7697 + yaffs_DeleteChunk(dev,chunk,1,__LINE__); 7698 + 9011 7699 + } 9012 + 9013 + if (!in->valid &&9014 + (tags.objectId == YAFFS_OBJECTID_ROOT ||9015 + tags.objectId ==9016 + YAFFS_OBJECTID_LOSTNFOUND)){9017 + / * We only load some info, don't fiddle with directory structure */7700 + 7701 + if(!in->valid && 7702 + (tags.objectId == YAFFS_OBJECTID_ROOT || 7703 + tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) 7704 + { 7705 + // We only load some info, don't fiddle with directory structure 9018 7706 + in->valid = 1; 7707 + in->variantType = oh->type; 7708 + 7709 + in->yst_mode = oh->yst_mode; 7710 +#ifdef CONFIG_YAFFS_WINCE 7711 + in->win_atime[0] = oh->win_atime[0]; 7712 + in->win_ctime[0] = oh->win_ctime[0]; 7713 + in->win_mtime[0] = oh->win_mtime[0]; 7714 + in->win_atime[1] = oh->win_atime[1]; 7715 + in->win_ctime[1] = oh->win_ctime[1]; 7716 + in->win_mtime[1] = oh->win_mtime[1]; 7717 +#else 7718 + in->yst_uid = oh->yst_uid; 7719 + in->yst_gid = oh->yst_gid; 7720 + in->yst_atime = oh->yst_atime; 7721 + in->yst_mtime = oh->yst_mtime; 7722 + in->yst_ctime = oh->yst_ctime; 7723 + in->yst_rdev = oh->yst_rdev; 7724 +#endif 7725 + in->chunkId = chunk; 7726 + 7727 + } 7728 + else if(!in->valid) 7729 + { 7730 + // we need to load this info 7731 + 7732 + in->valid = 1; 7733 + in->variantType = oh->type; 7734 + 7735 + in->yst_mode = oh->yst_mode; 7736 +#ifdef CONFIG_YAFFS_WINCE 7737 + in->win_atime[0] = oh->win_atime[0]; 7738 + in->win_ctime[0] = oh->win_ctime[0]; 7739 + in->win_mtime[0] = oh->win_mtime[0]; 7740 + in->win_atime[1] = oh->win_atime[1]; 7741 + in->win_ctime[1] = oh->win_ctime[1]; 7742 + in->win_mtime[1] = oh->win_mtime[1]; 7743 +#else 7744 + in->yst_uid = oh->yst_uid; 7745 + in->yst_gid = oh->yst_gid; 7746 + in->yst_atime = oh->yst_atime; 7747 + in->yst_mtime = oh->yst_mtime; 7748 + in->yst_ctime = oh->yst_ctime; 7749 + in->yst_rdev = oh->yst_rdev; 7750 +#endif 7751 + in->chunkId = chunk; 9019 7752 + 9020 + if(oh) { 9021 + in->variantType = oh->type; 9022 + 9023 + in->yst_mode = oh->yst_mode; 9024 +#ifdef CONFIG_YAFFS_WINCE 9025 + in->win_atime[0] = oh->win_atime[0]; 9026 + in->win_ctime[0] = oh->win_ctime[0]; 9027 + in->win_mtime[0] = oh->win_mtime[0]; 9028 + in->win_atime[1] = oh->win_atime[1]; 9029 + in->win_ctime[1] = oh->win_ctime[1]; 9030 + in->win_mtime[1] = oh->win_mtime[1]; 9031 +#else 9032 + in->yst_uid = oh->yst_uid; 9033 + in->yst_gid = oh->yst_gid; 9034 + in->yst_atime = oh->yst_atime; 9035 + in->yst_mtime = oh->yst_mtime; 9036 + in->yst_ctime = oh->yst_ctime; 9037 + in->yst_rdev = oh->yst_rdev; 9038 + 9039 +#endif 9040 + } else { 9041 + in->variantType = tags.extraObjectType; 9042 + in->lazyLoaded = 1; 7753 + if(oh->shadowsObject > 0) 7754 + { 7755 + yaffs_HandleShadowedObject(dev,oh->shadowsObject,0); 9043 7756 + } 9044 + 9045 + in->chunkId = chunk; 9046 + 9047 + } else if (!in->valid) { 9048 + /* we need to load this info */ 9049 + 9050 + in->valid = 1; 9051 + in->chunkId = chunk; 9052 + 9053 + if(oh) { 9054 + in->variantType = oh->type; 9055 + 9056 + in->yst_mode = oh->yst_mode; 9057 +#ifdef CONFIG_YAFFS_WINCE 9058 + in->win_atime[0] = oh->win_atime[0]; 9059 + in->win_ctime[0] = oh->win_ctime[0]; 9060 + in->win_mtime[0] = oh->win_mtime[0]; 9061 + in->win_atime[1] = oh->win_atime[1]; 9062 + in->win_ctime[1] = oh->win_ctime[1]; 9063 + in->win_mtime[1] = oh->win_mtime[1]; 9064 +#else 9065 + in->yst_uid = oh->yst_uid; 9066 + in->yst_gid = oh->yst_gid; 9067 + in->yst_atime = oh->yst_atime; 9068 + in->yst_mtime = oh->yst_mtime; 9069 + in->yst_ctime = oh->yst_ctime; 9070 + in->yst_rdev = oh->yst_rdev; 9071 +#endif 9072 + 9073 + if (oh->shadowsObject > 0) 9074 + yaffs_HandleShadowedObject(dev, 9075 + oh-> 9076 + shadowsObject, 9077 + 1); 9078 + 9079 + 9080 + yaffs_SetObjectName(in, oh->name); 9081 + parent = 9082 + yaffs_FindOrCreateObjectByNumber 9083 + (dev, oh->parentObjectId, 9084 + YAFFS_OBJECT_TYPE_DIRECTORY); 9085 + 9086 + fileSize = oh->fileSize; 9087 + isShrink = oh->isShrink; 9088 + equivalentObjectId = oh->equivalentObjectId; 9089 + 7757 + 7758 + 7759 + yaffs_SetObjectName(in,oh->name); 7760 + in->dirty = 0; 7761 + 7762 + // directory stuff... 7763 + // hook up to parent 7764 + 7765 + parent = yaffs_FindOrCreateObjectByNumber(dev,oh->parentObjectId,YAFFS_OBJECT_TYPE_DIRECTORY); 7766 + if(parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN) 7767 + { 7768 + // Set up as a directory 7769 + parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY; 7770 + INIT_LIST_HEAD(&parent->variant.directoryVariant.children); 9090 7771 + } 9091 + else { 9092 + in->variantType = tags.extraObjectType; 9093 + parent = 9094 + yaffs_FindOrCreateObjectByNumber 9095 + (dev, tags.extraParentObjectId, 9096 + YAFFS_OBJECT_TYPE_DIRECTORY); 9097 + fileSize = tags.extraFileLength; 9098 + isShrink = tags.extraIsShrinkHeader; 9099 + equivalentObjectId = tags.extraEquivalentObjectId; 9100 + in->lazyLoaded = 1; 9101 + 9102 + } 9103 + in->dirty = 0; 9104 + 9105 + /* directory stuff... 9106 + * hook up to parent 9107 + */ 9108 + 9109 + if (parent->variantType == 9110 + YAFFS_OBJECT_TYPE_UNKNOWN) { 9111 + /* Set up as a directory */ 9112 + parent->variantType = 9113 + YAFFS_OBJECT_TYPE_DIRECTORY; 9114 + INIT_LIST_HEAD(&parent->variant. 9115 + directoryVariant. 9116 + children); 9117 + } else if (parent->variantType != 9118 + YAFFS_OBJECT_TYPE_DIRECTORY) 7772 + else if(parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) 9119 7773 + { 9120 + /* Hoosterman, another problem.... 9121 + * We're trying to use a non-directory as a directory 9122 + */ 9123 + 9124 + T(YAFFS_TRACE_ERROR, 9125 + (TSTR 9126 + ("yaffs tragedy: attempting to use non-directory as" 9127 + " a directory in scan. Put in lost+found." 9128 + TENDSTR))); 7774 + // Hoosterman, another problem.... 7775 + // We're trying to use a non-directory as a directory 7776 + 7777 + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR))); 9129 7778 + parent = dev->lostNFoundDir; 9130 7779 + } 9131 + 9132 + yaffs_AddObjectToDirectory(parent, in); 9133 + 9134 + itsUnlinked = (parent == dev->deletedDir) || 9135 + (parent == dev->unlinkedDir); 9136 + 9137 + if (isShrink) { 9138 + /* Mark the block as having a shrinkHeader */ 7780 + 7781 + yaffs_AddObjectToDirectory(parent,in); 7782 + 7783 + if((parent == dev->deletedDir || 7784 + parent == dev->unlinkedDir)) 7785 + { 7786 + in->deleted = 1; // If it is unlinked at start up then it wants deleting 7787 + } 7788 + 7789 + if( oh->isShrink) 7790 + { 7791 + // Mark the block as having a shrinkHeader 9139 7792 + bi->hasShrinkHeader = 1; 9140 7793 + } 9141 + 9142 + /* Note re hardlinks. 9143 + * Since we might scan a hardlink before its equivalent object is scanned 9144 + * we put them all in a list. 9145 + * After scanning is complete, we should have all the objects, so we run 9146 + * through this list and fix up all the chains. 9147 + */ 9148 + 9149 + switch (in->variantType) { 9150 + case YAFFS_OBJECT_TYPE_UNKNOWN: 9151 + /* Todo got a problem */ 9152 + break; 9153 + case YAFFS_OBJECT_TYPE_FILE: 9154 + 9155 + if (in->variant.fileVariant. 9156 + scannedFileSize < fileSize) { 9157 + /* This covers the case where the file size is greater 9158 + * than where the data is 9159 + * This will happen if the file is resized to be larger 9160 + * than its current data extents. 9161 + */ 9162 + in->variant.fileVariant.fileSize = fileSize; 9163 + in->variant.fileVariant.scannedFileSize = 9164 + in->variant.fileVariant.fileSize; 9165 + } 9166 + 9167 + if (isShrink && 9168 + in->variant.fileVariant.shrinkSize > fileSize) { 9169 + in->variant.fileVariant.shrinkSize = fileSize; 9170 + } 9171 + 9172 + break; 9173 + case YAFFS_OBJECT_TYPE_HARDLINK: 9174 + if(!itsUnlinked) { 9175 + in->variant.hardLinkVariant.equivalentObjectId = 9176 + equivalentObjectId; 9177 + in->hardLinks.next = 9178 + (struct list_head *) hardList; 9179 + hardList = in; 9180 + } 9181 + break; 9182 + case YAFFS_OBJECT_TYPE_DIRECTORY: 9183 + /* Do nothing */ 9184 + break; 9185 + case YAFFS_OBJECT_TYPE_SPECIAL: 9186 + /* Do nothing */ 9187 + break; 9188 + case YAFFS_OBJECT_TYPE_SYMLINK: 9189 + if(oh) 9190 + in->variant.symLinkVariant.alias = 9191 + yaffs_CloneString(oh-> 9192 + alias); 9193 + break; 7794 + 7795 + 7796 + // Note re hardlinks. 7797 + // Since we might scan a hardlink before its equivalent object is scanned 7798 + // we put them all in a list. 7799 + // After scanning is complete, we should have all the objects, so we run through this 7800 + // list and fix up all the chains. 7801 + 7802 + switch(in->variantType) 7803 + { 7804 + case YAFFS_OBJECT_TYPE_UNKNOWN: // Todo got a problem 7805 + break; 7806 + case YAFFS_OBJECT_TYPE_FILE: 7807 + 7808 + 7809 + if(in->variant.fileVariant.scannedFileSize < oh->fileSize) 7810 + { 7811 + in->variant.fileVariant.fileSize = oh->fileSize; 7812 + in->variant.fileVariant.scannedFileSize = in->variant.fileVariant.fileSize; 7813 + } 7814 + 7815 + if(oh->isShrink && 7816 + in->variant.fileVariant.shrinkSize > oh->fileSize) 7817 + { 7818 + in->variant.fileVariant.shrinkSize = oh->fileSize; 7819 + } 7820 + 7821 + break; 7822 + case YAFFS_OBJECT_TYPE_HARDLINK: 7823 + in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId; 7824 + in->hardLinks.next = (struct list_head *)hardList; 7825 + hardList = in; 7826 + break; 7827 + case YAFFS_OBJECT_TYPE_DIRECTORY: // Do nothing 7828 + break; 7829 + case YAFFS_OBJECT_TYPE_SPECIAL: // Do nothing 7830 + break; 7831 + case YAFFS_OBJECT_TYPE_SYMLINK: // Do nothing 7832 + in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias); 7833 + break; 9194 7834 + } 9195 7835 + 7836 +#if 0 7837 + if(parent == dev->deletedDir) 7838 + { 7839 + yaffs_DestroyObject(in); 7840 + bi->hasShrinkHeader = 1; 7841 + } 7842 +#endif 7843 + //T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType)); 9196 7844 + } 9197 7845 + } 9198 7846 + } 9199 + 9200 + if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { 9201 + /* If we got this far while scanning, then the block is fully allocated. */ 9202 + state = YAFFS_BLOCK_STATE_FULL; 9203 + } 9204 + 7847 + 7848 + if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) 7849 + { 7850 + // If we got this far while scanning, then the block is fully allocated. 7851 + state = YAFFS_BLOCK_STATE_FULL; 7852 + } 7853 + 9205 7854 + bi->blockState = state; 9206 + 9207 + / * Now let's see if it was dirty */9208 + if (bi->pagesInUse == 0 &&9209 + !bi->hasShrinkHeader &&9210 + bi->blockState == YAFFS_BLOCK_STATE_FULL) {9211 + yaffs_BlockBecameDirty(dev, blk);9212 + }9213 + 9214 + }9215 + 9216 + if (altBlockIndex)9217 + YFREE_ALT(blockIndex);9218 + else7855 + 7856 + // Now let's see if it was dirty 7857 + if( bi->pagesInUse == 0 && 7858 + !bi->hasShrinkHeader && 7859 + bi->blockState == YAFFS_BLOCK_STATE_FULL) 7860 + { 7861 + yaffs_BlockBecameDirty(dev,blk); 7862 + } 7863 + 7864 + } 7865 + 7866 + if(blockIndex) 7867 + { 9219 7868 + YFREE(blockIndex); 9220 + 9221 + /* Ok, we've done all the scanning. 9222 + * Fix up the hard link chains. 9223 + * We should now have scanned all the objects, now it's time to add these 9224 + * hardlinks. 9225 + */ 9226 + yaffs_HardlinkFixup(dev,hardList); 9227 + 9228 + 9229 + /* 9230 + * Sort out state of unlinked and deleted objects. 9231 + */ 9232 + { 9233 + struct list_head *i; 7869 + } 7870 + 7871 + // Ok, we've done all the scanning. 7872 + 7873 + // Fix up the hard link chains. 7874 + // We should now have scanned all the objects, now it's time to add these 7875 + // hardlinks. 7876 + while(hardList) 7877 + { 7878 + hl = hardList; 7879 + hardList = (yaffs_Object *)(hardList->hardLinks.next); 7880 + 7881 + in = yaffs_FindObjectByNumber(dev,hl->variant.hardLinkVariant.equivalentObjectId); 7882 + 7883 + if(in) 7884 + { 7885 + // Add the hardlink pointers 7886 + hl->variant.hardLinkVariant.equivalentObject=in; 7887 + list_add(&hl->hardLinks,&in->hardLinks); 7888 + } 7889 + else 7890 + { 7891 + //Todo Need to report/handle this better. 7892 + // Got a problem... hardlink to a non-existant object 7893 + hl->variant.hardLinkVariant.equivalentObject=NULL; 7894 + INIT_LIST_HEAD(&hl->hardLinks); 7895 + 7896 + } 7897 + 7898 + } 7899 + 7900 + { 7901 + struct list_head *i; 9234 7902 + struct list_head *n; 9235 + 7903 + 9236 7904 + yaffs_Object *l; 9237 + 9238 + / * Soft delete all the unlinked files */9239 + list_for_each_safe(i, n,9240 + &dev->unlinkedDir->variant.directoryVariant.9241 + children) {9242 + if (i){9243 + l = list_entry(i, yaffs_Object, siblings);9244 + yaffs_DestroyObject(l); 7905 + 7906 + // Soft delete all the unlinked files 7907 + list_for_each_safe(i,n,&dev->unlinkedDir->variant.directoryVariant.children) 7908 + { 7909 + if(i) 7910 + { 7911 + l = list_entry(i, yaffs_Object,siblings); 7912 + yaffs_DestroyObject(l); 9245 7913 + } 9246 + } 9247 + 9248 + / * Soft delete all the deletedDir files */9249 + list_for_each_safe(i, n,9250 + &dev->deletedDir->variant.directoryVariant.9251 + children) {9252 + if (i){9253 + l = list_entry(i, yaffs_Object, siblings);9254 + yaffs_DestroyObject(l); 9255 + 7914 + } 7915 + 7916 + // Soft delete all the deletedDir files 7917 + list_for_each_safe(i,n,&dev->deletedDir->variant.directoryVariant.children) 7918 + { 7919 + if(i) 7920 + { 7921 + l = list_entry(i, yaffs_Object,siblings); 7922 + yaffs_DestroyObject(l); 7923 + 9256 7924 + } 9257 + } 9258 + } 9259 + 9260 + yaffs_ReleaseTempBuffer(dev, chunkData,__LINE__);9261 + 9262 + T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));7925 + } 7926 + } 7927 + 7928 + yaffs_ReleaseTempBuffer(dev,chunkData,__LINE__); 7929 + 7930 + T(YAFFS_TRACE_SCAN,(TSTR("yaffs_ScanBackwards ends" TENDSTR))); 9263 7931 + 9264 7932 + return YAFFS_OK; 9265 7933 +} 9266 7934 + 9267 +/*------------------------------ Directory Functions ----------------------------- */ 9268 + 9269 +static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) 9270 +{ 9271 + yaffs_Device *dev = obj->myDev; 9272 + 9273 + if(dev && dev->removeObjectCallback) 9274 + dev->removeObjectCallback(obj); 9275 + 9276 + list_del_init(&obj->siblings); 9277 + obj->parent = NULL; 9278 +} 9279 + 9280 + 9281 +static void yaffs_AddObjectToDirectory(yaffs_Object * directory, 9282 + yaffs_Object * obj) 9283 +{ 9284 + 9285 + if (!directory) { 9286 + T(YAFFS_TRACE_ALWAYS, 9287 + (TSTR 9288 + ("tragedy: Trying to add an object to a null pointer directory" 9289 + TENDSTR))); 7935 + 7936 + 7937 +////////////////////////// Directory Functions ///////////////////////// 7938 + 7939 + 7940 +static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj) 7941 +{ 7942 + 7943 + if(!directory) 7944 + { 7945 + T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: Trying to add an object to a null pointer directory" TENDSTR))); 9290 7946 + YBUG(); 9291 7947 + } 9292 + if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { 9293 + T(YAFFS_TRACE_ALWAYS, 9294 + (TSTR 9295 + ("tragedy: Trying to add an object to a non-directory" 9296 + TENDSTR))); 7948 + if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) 7949 + { 7950 + T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: Trying to add an object to a non-directory" TENDSTR))); 9297 7951 + YBUG(); 9298 7952 + } 9299 7953 + 9300 + if (obj->siblings.prev == NULL) { 9301 + /* Not initialised */ 7954 + if(obj->siblings.prev == NULL) 7955 + { 7956 + // Not initialised 9302 7957 + INIT_LIST_HEAD(&obj->siblings); 9303 + 9304 + } else if (!list_empty(&obj->siblings)) { 9305 + /* If it is holed up somewhere else, un hook it */ 9306 + yaffs_RemoveObjectFromDirectory(obj); 9307 + } 9308 + /* Now add it */ 9309 + list_add(&obj->siblings, &directory->variant.directoryVariant.children); 7958 + 7959 + } 7960 + else if(!list_empty(&obj->siblings)) 7961 + { 7962 + // If it is holed up somewhere else, un hook it 7963 + list_del_init(&obj->siblings); 7964 + } 7965 + // Now add it 7966 + list_add(&obj->siblings,&directory->variant.directoryVariant.children); 9310 7967 + obj->parent = directory; 9311 + 9312 + if (directory == obj->myDev->unlinkedDir9313 + || directory == obj->myDev->deletedDir){7968 + 7969 + if(directory == obj->myDev->unlinkedDir || directory == obj->myDev->deletedDir) 7970 + { 9314 7971 + obj->unlinked = 1; 9315 7972 + obj->myDev->nUnlinkedFiles++; … … 9318 7975 +} 9319 7976 + 9320 +yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, 9321 + const YCHAR * name) 7977 +static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj) 7978 +{ 7979 + list_del_init(&obj->siblings); 7980 + obj->parent = NULL; 7981 +} 7982 + 7983 +yaffs_Object *yaffs_FindObjectByName(yaffs_Object *directory,const YCHAR *name) 9322 7984 +{ 9323 7985 + int sum; 9324 + 7986 + 9325 7987 + struct list_head *i; 9326 + YCHAR buffer[YAFFS_MAX_NAME_LENGTH +1];9327 + 7988 + YCHAR buffer[YAFFS_MAX_NAME_LENGTH+1]; 7989 + 9328 7990 + yaffs_Object *l; 9329 + 9330 + if (!name) { 7991 + 7992 + if(!name) 7993 + { 9331 7994 + return NULL; 9332 7995 + } 9333 7996 + 9334 + if (!directory) { 9335 + T(YAFFS_TRACE_ALWAYS, 9336 + (TSTR 9337 + ("tragedy: yaffs_FindObjectByName: null pointer directory" 9338 + TENDSTR))); 7997 + if(!directory) 7998 + { 7999 + T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: null pointer directory"TENDSTR))); 9339 8000 + YBUG(); 9340 8001 + } 9341 + if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { 9342 + T(YAFFS_TRACE_ALWAYS, 9343 + (TSTR 9344 + ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR))); 8002 + if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) 8003 + { 8004 + T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: non-directory"TENDSTR))); 9345 8005 + YBUG(); 9346 8006 + } 9347 8007 + 9348 8008 + sum = yaffs_CalcNameSum(name); 9349 + 9350 + list_for_each(i, &directory->variant.directoryVariant.children) { 9351 + if (i) { 9352 + l = list_entry(i, yaffs_Object, siblings); 9353 + 9354 + yaffs_CheckObjectDetailsLoaded(l); 9355 + 9356 + /* Special case for lost-n-found */ 9357 + if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) { 9358 + if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) { 8009 + 8010 + list_for_each(i,&directory->variant.directoryVariant.children) 8011 + { 8012 + if(i) 8013 + { 8014 + l = list_entry(i, yaffs_Object,siblings); 8015 + 8016 + // Special case for lost-n-found 8017 + if(l->objectId == YAFFS_OBJECTID_LOSTNFOUND) 8018 + { 8019 + if(yaffs_strcmp(name,YAFFS_LOSTNFOUND_NAME) == 0) 8020 + { 9359 8021 + return l; 9360 8022 + } 9361 + } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) 8023 + } 8024 + else if(yaffs_SumCompare(l->sum, sum)|| 8025 + l->chunkId <= 0) //LostnFound cunk called Objxxx 9362 8026 + { 9363 + /* LostnFound cunk called Objxxx 9364 + * Do a real check 9365 + */ 9366 + yaffs_GetObjectName(l, buffer, 9367 + YAFFS_MAX_NAME_LENGTH); 9368 + if (yaffs_strcmp(name, buffer) == 0) { 8027 + // Do a real check 8028 + yaffs_GetObjectName(l,buffer,YAFFS_MAX_NAME_LENGTH); 8029 + if(yaffs_strcmp(name,buffer) == 0) 8030 + { 9369 8031 + return l; 9370 8032 + } 9371 + 9372 + } 9373 + } 9374 + } 9375 + 8033 + 8034 + } 8035 + } 8036 + } 8037 + 9376 8038 + return NULL; 9377 8039 +} 9378 8040 + 9379 8041 + 9380 +#if 0 9381 +int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, 9382 + int (*fn) (yaffs_Object *)) 9383 +{ 9384 + struct list_head *i; 8042 +int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *)) 8043 +{ 8044 + struct list_head *i; 9385 8045 + yaffs_Object *l; 9386 + 9387 + if (!theDir) { 9388 + T(YAFFS_TRACE_ALWAYS, 9389 + (TSTR 9390 + ("tragedy: yaffs_FindObjectByName: null pointer directory" 9391 + TENDSTR))); 8046 + 8047 + 8048 + if(!theDir) 8049 + { 8050 + T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: null pointer directory"TENDSTR))); 9392 8051 + YBUG(); 9393 8052 + } 9394 + if (theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { 9395 + T(YAFFS_TRACE_ALWAYS, 9396 + (TSTR 9397 + ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR))); 8053 + if(theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) 8054 + { 8055 + T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: non-directory"TENDSTR))); 9398 8056 + YBUG(); 9399 8057 + } 9400 + 9401 + list_for_each(i, &theDir->variant.directoryVariant.children) { 9402 + if (i) { 9403 + l = list_entry(i, yaffs_Object, siblings); 9404 + if (l && !fn(l)) { 8058 + 8059 + list_for_each(i,&theDir->variant.directoryVariant.children) 8060 + { 8061 + if(i) 8062 + { 8063 + l = list_entry(i, yaffs_Object,siblings); 8064 + if(l && !fn(l)) 8065 + { 9405 8066 + return YAFFS_FAIL; 9406 8067 + } 9407 8068 + } 9408 8069 + } 9409 + 8070 + 9410 8071 + return YAFFS_OK; 9411 8072 + 9412 8073 +} 9413 + #endif9414 + 9415 +/ *GetEquivalentObject dereferences any hard links to get to the9416 + *actual object.9417 + */9418 + 9419 + yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj)9420 + {9421 + if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK){9422 + / * We want the object id of the equivalent object, not this one */8074 + 8075 + 8076 +// GetEquivalentObject dereferences any hard links to get to the 8077 +// actual object. 8078 + 8079 +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj) 8080 +{ 8081 + if(obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) 8082 + { 8083 + // We want the object id of the equivalent object, not this one 9423 8084 + obj = obj->variant.hardLinkVariant.equivalentObject; 9424 8085 + } … … 9427 8088 +} 9428 8089 + 9429 +int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) 9430 +{ 9431 + memset(name, 0, buffSize * sizeof(YCHAR)); 9432 + 9433 + yaffs_CheckObjectDetailsLoaded(obj); 9434 + 9435 + if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) { 9436 + yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1); 9437 + } else if (obj->chunkId <= 0) { 8090 +int yaffs_GetObjectName(yaffs_Object *obj,YCHAR *name,int buffSize) 8091 +{ 8092 + memset(name,0,buffSize * sizeof(YCHAR)); 8093 + 8094 + if(obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) 8095 + { 8096 + yaffs_strncpy(name,YAFFS_LOSTNFOUND_NAME,buffSize - 1); 8097 + } 8098 + else if(obj->chunkId <= 0) 8099 + { 9438 8100 + YCHAR locName[20]; 9439 + /* make up a name */ 9440 + yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX, 9441 + obj->objectId); 9442 + yaffs_strncpy(name, locName, buffSize - 1); 8101 + // make up a name 8102 + yaffs_sprintf(locName,_Y("%s%d"),YAFFS_LOSTNFOUND_PREFIX,obj->objectId); 8103 + yaffs_strncpy(name,locName,buffSize - 1); 9443 8104 + 9444 8105 + } 9445 8106 +#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM 9446 + else if (obj->shortName[0]) {9447 + yaffs_strcpy(name, obj->shortName);9448 + }9449 + #endif9450 + else {9451 + int result;9452 + __u8 *buffer = yaffs_GetTempBuffer(obj->myDev, __LINE__);9453 + 9454 + yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *) buffer;9455 + 9456 + memset(buffer, 0, obj->myDev->nDataBytesPerChunk);9457 + 9458 + if (obj->chunkId >= 0) {9459 + result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,9460 + obj->chunkId, buffer,9461 + NULL);9462 + } 9463 + yaffs_strncpy(name, oh->name,buffSize - 1);9464 + 9465 + yaffs_ReleaseTempBuffer(obj->myDev, buffer,__LINE__);9466 + } 9467 + 8107 + else if(obj->shortName[0]) 8108 + { 8109 + yaffs_strcpy(name,obj->shortName); 8110 + } 8111 +#endif 8112 + else 8113 + { 8114 + __u8 *buffer = yaffs_GetTempBuffer(obj->myDev,__LINE__); 8115 + 8116 + yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)buffer; 8117 + 8118 + memset(buffer,0,obj->myDev->nBytesPerChunk); 8119 + 8120 + if(obj->chunkId >= 0) 8121 + { 8122 + yaffs_ReadChunkWithTagsFromNAND(obj->myDev,obj->chunkId,buffer,NULL); 8123 + } 8124 + yaffs_strncpy(name,oh->name,buffSize - 1); 8125 + 8126 + yaffs_ReleaseTempBuffer(obj->myDev,buffer,__LINE__); 8127 + } 8128 + 9468 8129 + return yaffs_strlen(name); 9469 8130 +} 9470 8131 + 9471 +int yaffs_GetObjectFileLength(yaffs_Object * obj)9472 +{ 9473 + 9474 + / * Dereference any hard linking */8132 +int yaffs_GetObjectFileLength(yaffs_Object *obj) 8133 +{ 8134 + 8135 + // Dereference any hard linking 9475 8136 + obj = yaffs_GetEquivalentObject(obj); 9476 + 9477 + if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) { 8137 + 8138 + if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) 8139 + { 9478 8140 + return obj->variant.fileVariant.fileSize; 9479 8141 + } 9480 + if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { 8142 + if(obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) 8143 + { 9481 8144 + return yaffs_strlen(obj->variant.symLinkVariant.alias); 9482 + } else { 9483 + /* Only a directory should drop through to here */ 9484 + return obj->myDev->nDataBytesPerChunk; 9485 + } 9486 +} 9487 + 9488 +int yaffs_GetObjectLinkCount(yaffs_Object * obj) 9489 +{ 9490 + int count = 0; 8145 + } 8146 + else 8147 + { 8148 + // Only a directory should drop through to here 8149 + return obj->myDev->nBytesPerChunk; 8150 + } 8151 +} 8152 + 8153 +int yaffs_GetObjectLinkCount(yaffs_Object *obj) 8154 +{ 8155 + int count = 0; 9491 8156 + struct list_head *i; 9492 + 9493 + if (!obj->unlinked) { 9494 + count++; /* the object itself */ 9495 + } 9496 + list_for_each(i, &obj->hardLinks) { 9497 + count++; /* add the hard links; */ 8157 + 8158 + if(!obj->unlinked) 8159 + { 8160 + count++; // the object itself 8161 + } 8162 + list_for_each(i,&obj->hardLinks) 8163 + { 8164 + count++; // add the hard links; 9498 8165 + } 9499 8166 + return count; 9500 + 9501 +} 9502 + 9503 +int yaffs_GetObjectInode(yaffs_Object * obj) 8167 + 8168 +} 8169 + 8170 + 8171 +int yaffs_GetObjectInode(yaffs_Object *obj) 9504 8172 +{ 9505 8173 + obj = yaffs_GetEquivalentObject(obj); 9506 + 8174 + 9507 8175 + return obj->objectId; 9508 8176 +} 9509 8177 + 9510 +unsigned yaffs_GetObjectType(yaffs_Object * obj)8178 +unsigned yaffs_GetObjectType(yaffs_Object *obj) 9511 8179 +{ 9512 8180 + obj = yaffs_GetEquivalentObject(obj); 9513 + 9514 + switch (obj->variantType) { 9515 + case YAFFS_OBJECT_TYPE_FILE: 9516 + return DT_REG; 9517 + break; 9518 + case YAFFS_OBJECT_TYPE_DIRECTORY: 9519 + return DT_DIR; 9520 + break; 9521 + case YAFFS_OBJECT_TYPE_SYMLINK: 9522 + return DT_LNK; 9523 + break; 9524 + case YAFFS_OBJECT_TYPE_HARDLINK: 9525 + return DT_REG; 9526 + break; 9527 + case YAFFS_OBJECT_TYPE_SPECIAL: 9528 + if (S_ISFIFO(obj->yst_mode)) 9529 + return DT_FIFO; 9530 + if (S_ISCHR(obj->yst_mode)) 9531 + return DT_CHR; 9532 + if (S_ISBLK(obj->yst_mode)) 9533 + return DT_BLK; 9534 + if (S_ISSOCK(obj->yst_mode)) 9535 + return DT_SOCK; 9536 + default: 9537 + return DT_REG; 9538 + break; 9539 + } 9540 +} 9541 + 9542 +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj) 8181 + 8182 + switch(obj->variantType) 8183 + { 8184 + case YAFFS_OBJECT_TYPE_FILE: return DT_REG; break; 8185 + case YAFFS_OBJECT_TYPE_DIRECTORY: return DT_DIR; break; 8186 + case YAFFS_OBJECT_TYPE_SYMLINK: return DT_LNK; break; 8187 + case YAFFS_OBJECT_TYPE_HARDLINK: return DT_REG; break; 8188 + case YAFFS_OBJECT_TYPE_SPECIAL: 8189 + if(S_ISFIFO(obj->yst_mode)) return DT_FIFO; 8190 + if(S_ISCHR(obj->yst_mode)) return DT_CHR; 8191 + if(S_ISBLK(obj->yst_mode)) return DT_BLK; 8192 + if(S_ISSOCK(obj->yst_mode)) return DT_SOCK; 8193 + default: return DT_REG; break; 8194 + } 8195 +} 8196 + 8197 +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj) 9543 8198 +{ 9544 8199 + obj = yaffs_GetEquivalentObject(obj); 9545 + if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { 8200 + if(obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) 8201 + { 9546 8202 + return yaffs_CloneString(obj->variant.symLinkVariant.alias); 9547 + } else { 8203 + } 8204 + else 8205 + { 9548 8206 + return yaffs_CloneString(_Y("")); 9549 8207 + } … … 9552 8210 +#ifndef CONFIG_YAFFS_WINCE 9553 8211 + 9554 +int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr)8212 +int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) 9555 8213 +{ 9556 8214 + unsigned int valid = attr->ia_valid; 9557 + 9558 + if (valid & ATTR_MODE) 9559 + obj->yst_mode = attr->ia_mode; 9560 + if (valid & ATTR_UID) 9561 + obj->yst_uid = attr->ia_uid; 9562 + if (valid & ATTR_GID) 9563 + obj->yst_gid = attr->ia_gid; 9564 + 9565 + if (valid & ATTR_ATIME) 9566 + obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); 9567 + if (valid & ATTR_CTIME) 9568 + obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); 9569 + if (valid & ATTR_MTIME) 9570 + obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); 9571 + 9572 + if (valid & ATTR_SIZE) 9573 + yaffs_ResizeFile(obj, attr->ia_size); 9574 + 9575 + yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0); 9576 + 8215 + 8216 + if(valid & ATTR_MODE) obj->yst_mode = attr->ia_mode; 8217 + if(valid & ATTR_UID) obj->yst_uid = attr->ia_uid; 8218 + if(valid & ATTR_GID) obj->yst_gid = attr->ia_gid; 8219 + 8220 + if(valid & ATTR_ATIME) obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); 8221 + if(valid & ATTR_CTIME) obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); 8222 + if(valid & ATTR_MTIME) obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); 8223 + 8224 + if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size); 8225 + 8226 + yaffs_UpdateObjectHeader(obj,NULL,1,0,0); 8227 + 9577 8228 + return YAFFS_OK; 9578 + 9579 +} 9580 +int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr)8229 + 8230 +} 8231 +int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr) 9581 8232 +{ 9582 8233 + unsigned int valid = 0; 9583 + 9584 + attr->ia_mode = obj->yst_mode; 9585 + valid |= ATTR_MODE; 9586 + attr->ia_uid = obj->yst_uid; 9587 + valid |= ATTR_UID; 9588 + attr->ia_gid = obj->yst_gid; 9589 + valid |= ATTR_GID; 9590 + 9591 + Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime; 9592 + valid |= ATTR_ATIME; 9593 + Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; 9594 + valid |= ATTR_CTIME; 9595 + Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; 9596 + valid |= ATTR_MTIME; 9597 + 9598 + attr->ia_size = yaffs_GetFileSize(obj); 9599 + valid |= ATTR_SIZE; 9600 + 8234 + 8235 + attr->ia_mode = obj->yst_mode; valid |= ATTR_MODE; 8236 + attr->ia_uid = obj->yst_uid; valid |= ATTR_UID; 8237 + attr->ia_gid = obj->yst_gid; valid |= ATTR_GID; 8238 + 8239 + Y_TIME_CONVERT(attr->ia_atime)= obj->yst_atime; valid |= ATTR_ATIME; 8240 + Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; valid |= ATTR_CTIME; 8241 + Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; valid |= ATTR_MTIME; 8242 + 8243 + attr->ia_size = yaffs_GetFileSize(obj); valid |= ATTR_SIZE; 8244 + 9601 8245 + attr->ia_valid = valid; 9602 + 8246 + 9603 8247 + return YAFFS_OK; 9604 + 9605 +} 9606 + 9607 +#endif 8248 + 8249 +} 8250 + 8251 +#endif 8252 + 8253 +int yaffs_DumpObject(yaffs_Object *obj) 8254 +{ 8255 +// __u8 buffer[YAFFS_BYTES_PER_CHUNK]; 8256 + YCHAR name[257]; 8257 +// yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)buffer; 8258 + 8259 +// memset(buffer,0,YAFFS_BYTES_PER_CHUNK); 8260 + 8261 +// if(obj->chunkId >= 0) 8262 +// { 8263 +// yaffs_ReadChunkFromNAND(obj->myDev,obj->chunkId,buffer,NULL); 8264 +// } 8265 + 8266 + yaffs_GetObjectName(obj,name,256); 8267 + 8268 + T(YAFFS_TRACE_ALWAYS,(TSTR("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d chunk %d type %d size %d\n" TENDSTR), 8269 + obj->objectId,yaffs_GetObjectInode(obj), name, obj->dirty, obj->valid, obj->serial, 8270 + obj->sum, obj->chunkId, yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj))); 9608 8271 + 9609 8272 +#if 0 9610 +int yaffs_DumpObject(yaffs_Object * obj) 9611 +{ 9612 + YCHAR name[257]; 9613 + 9614 + yaffs_GetObjectName(obj, name, 256); 9615 + 9616 + T(YAFFS_TRACE_ALWAYS, 9617 + (TSTR 9618 + ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d" 9619 + " chunk %d type %d size %d\n" 9620 + TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name, 9621 + obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId, 9622 + yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj))); 9623 + 8273 + YPRINTF(("Object %d \"%s\"\n dirty %d valid %d serial %d sum %d chunk %d\n", 8274 + obj->objectId, oh->name, obj->dirty, obj->valid, obj->serial, 8275 + obj->sum, obj->chunkId)); 8276 + switch(obj->variantType) 8277 + { 8278 + case YAFFS_OBJECT_TYPE_FILE: 8279 + YPRINTF((" FILE length %d\n",obj->variant.fileVariant.fileSize)); 8280 + break; 8281 + case YAFFS_OBJECT_TYPE_DIRECTORY: 8282 + YPRINTF((" DIRECTORY\n")); 8283 + break; 8284 + case YAFFS_OBJECT_TYPE_HARDLINK: //todo 8285 + case YAFFS_OBJECT_TYPE_SYMLINK: 8286 + case YAFFS_OBJECT_TYPE_UNKNOWN: 8287 + default: 8288 + } 8289 +#endif 8290 + 9624 8291 + return YAFFS_OK; 9625 8292 +} 9626 +#endif 9627 + 9628 +/*---------------------------- Initialisation code -------------------------------------- */ 9629 + 9630 +static int yaffs_CheckDevFunctions(const yaffs_Device * dev) 9631 +{ 9632 + 9633 + /* Common functions, gotta have */ 9634 + if (!dev->eraseBlockInNAND || !dev->initialiseNAND) 9635 + return 0; 8293 + 8294 + 8295 +///////////////////////// Initialisation code /////////////////////////// 8296 + 8297 + 8298 +static int yaffs_CheckDevFunctions(const yaffs_Device *dev) 8299 +{ 8300 + 8301 + // Common functions, gotta have 8302 + if(!dev->eraseBlockInNAND || 8303 + !dev->initialiseNAND) return 0; 9636 8304 + 9637 8305 +#ifdef CONFIG_YAFFS_YAFFS2 9638 8306 + 9639 + /* Can use the "with tags" style interface for yaffs1 or yaffs2 */ 9640 + if (dev->writeChunkWithTagsToNAND && 9641 + dev->readChunkWithTagsFromNAND && 9642 + !dev->writeChunkToNAND && 9643 + !dev->readChunkFromNAND && 9644 + dev->markNANDBlockBad && dev->queryNANDBlock) 9645 + return 1; 9646 +#endif 9647 + 9648 + /* Can use the "spare" style interface for yaffs1 */ 9649 + if (!dev->isYaffs2 && 9650 + !dev->writeChunkWithTagsToNAND && 9651 + !dev->readChunkWithTagsFromNAND && 9652 + dev->writeChunkToNAND && 9653 + dev->readChunkFromNAND && 9654 + !dev->markNANDBlockBad && !dev->queryNANDBlock) 9655 + return 1; 9656 + 9657 + return 0; /* bad */ 9658 +} 9659 + 9660 + 9661 +static void yaffs_CreateInitialDirectories(yaffs_Device *dev) 9662 +{ 9663 + /* Initialise the unlinked, deleted, root and lost and found directories */ 9664 + 9665 + dev->lostNFoundDir = dev->rootDir = NULL; 9666 + dev->unlinkedDir = dev->deletedDir = NULL; 9667 + 9668 + dev->unlinkedDir = 9669 + yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR); 9670 + dev->deletedDir = 9671 + yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR); 9672 + 9673 + dev->rootDir = 9674 + yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_ROOT, 9675 + YAFFS_ROOT_MODE | S_IFDIR); 9676 + dev->lostNFoundDir = 9677 + yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND, 9678 + YAFFS_LOSTNFOUND_MODE | S_IFDIR); 9679 + yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir); 9680 +} 9681 + 9682 +int yaffs_GutsInitialise(yaffs_Device * dev) 8307 + // Can use the "with tags" style interface for yaffs1 or yaffs2 8308 + if(dev->writeChunkWithTagsToNAND && 8309 + dev->readChunkWithTagsFromNAND && 8310 + !dev->writeChunkToNAND && 8311 + !dev->readChunkFromNAND && 8312 + dev->markNANDBlockBad && 8313 + dev->queryNANDBlock) return 1; 8314 +#endif 8315 + 8316 + // Can use the "spare" style interface for yaffs1 8317 + if(!dev->isYaffs2 && 8318 + !dev->writeChunkWithTagsToNAND && 8319 + !dev->readChunkWithTagsFromNAND && 8320 + dev->writeChunkToNAND && 8321 + dev->readChunkFromNAND && 8322 + !dev->markNANDBlockBad && 8323 + !dev->queryNANDBlock) return 1; 8324 + 8325 + return 0; // bad 8326 +} 8327 + 8328 + 8329 +int yaffs_GutsInitialise(yaffs_Device *dev) 9683 8330 +{ 9684 8331 + unsigned x; 9685 8332 + int bits; 9686 + 9687 + T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); 9688 + 9689 + /* Check stuff that must be set */ 9690 + 9691 + if (!dev) { 9692 + T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Need a device" TENDSTR))); 8333 + int extraBits; 8334 + int nBlocks; 8335 + 8336 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); 8337 + // Check stuff that must be set 8338 + 8339 + if(!dev) 8340 + { 8341 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Need a device" TENDSTR))); 9693 8342 + return YAFFS_FAIL; 9694 8343 + } 9695 + 8344 + 9696 8345 + dev->internalStartBlock = dev->startBlock; 9697 + dev->internalEndBlock = dev->endBlock;8346 + dev->internalEndBlock = dev->endBlock; 9698 8347 + dev->blockOffset = 0; 9699 8348 + dev->chunkOffset = 0; 9700 8349 + dev->nFreeChunks = 0; 9701 + 9702 + if (dev->startBlock == 0) { 8350 + 8351 + if(dev->startBlock == 0) 8352 + { 9703 8353 + dev->internalStartBlock = dev->startBlock + 1; 9704 + dev->internalEndBlock = dev->endBlock + 1;8354 + dev->internalEndBlock = dev->endBlock + 1; 9705 8355 + dev->blockOffset = 1; 9706 8356 + dev->chunkOffset = dev->nChunksPerBlock; 9707 8357 + } 9708 8358 + 9709 + /* Check geometry parameters. */ 9710 + 9711 + if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) || 9712 + (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) || 9713 + dev->nChunksPerBlock < 2 || 9714 + dev->nReservedBlocks < 2 || 9715 + dev->internalStartBlock <= 0 || 9716 + dev->internalEndBlock <= 0 || 9717 + dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2) // otherwise it is too small 9718 + ) { 9719 + T(YAFFS_TRACE_ALWAYS, 9720 + (TSTR 9721 + ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s " 9722 + TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : "")); 8359 + // Check geometry parameters. 8360 + 8361 + if( (dev->isYaffs2 && dev->nBytesPerChunk <1024) || 8362 + (!dev->isYaffs2 && dev->nBytesPerChunk !=512) || 8363 + dev->nChunksPerBlock < 2 || 8364 + dev->nReservedBlocks < 2 || 8365 + dev->internalStartBlock <= 0 || 8366 + dev->internalEndBlock <= 0 || 8367 + dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2) // otherwise it is too small 8368 + ) 8369 + { 8370 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s " TENDSTR), 8371 + dev->nBytesPerChunk, dev->isYaffs2 ? "2" : "")); 9723 8372 + return YAFFS_FAIL; 9724 8373 + } 9725 8374 + 9726 + if (yaffs_InitialiseNAND(dev) != YAFFS_OK) {9727 + T(YAFFS_TRACE_ALWAYS,9728 + (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));8375 + if(yaffs_InitialiseNAND(dev) != YAFFS_OK) 8376 + { 8377 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: InitialiseNAND failed" TENDSTR))); 9729 8378 + return YAFFS_FAIL; 9730 8379 + } 9731 8380 + 9732 + / * Got the right mix of functions? */9733 + if (!yaffs_CheckDevFunctions(dev)) {9734 + /* Function missing */9735 + T(YAFFS_TRACE_ALWAYS,9736 + (TSTR9737 + ("yaffs: device function(s) missing or wrong\n" TENDSTR)));8381 + // Got the right mix of functions? 8382 + // 8383 + if(!yaffs_CheckDevFunctions(dev)) 8384 + { 8385 + //Function missing 8386 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: device function(s) missing or wrong\n" TENDSTR))); 9738 8387 + 9739 8388 + return YAFFS_FAIL; 9740 8389 + } 9741 8390 + 9742 + / * This is really a compilation check. */9743 + if (!yaffs_CheckStructures()) {9744 + T(YAFFS_TRACE_ALWAYS,9745 + (TSTR("yaffs_CheckStructures failed\n" TENDSTR)));8391 + // This is really a compilation check. 8392 + if(!yaffs_CheckStructures()) 8393 + { 8394 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs_CheckStructures failed\n" TENDSTR))); 9746 8395 + return YAFFS_FAIL; 9747 8396 + } 9748 8397 + 9749 + if (dev->isMounted) {9750 + T(YAFFS_TRACE_ALWAYS,9751 + (TSTR("yaffs: device already mounted\n" TENDSTR)));8398 + if(dev->isMounted) 8399 + { 8400 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: device already mounted\n" TENDSTR))); 9752 8401 + return YAFFS_FAIL; 9753 8402 + } 9754 8403 + 9755 + /* Finished with most checks. One or two more checks happen later on too. */ 8404 + // 8405 + // 8406 + // Finished with most checks. One or two more checks happen later on too. 8407 + // 9756 8408 + 9757 8409 + dev->isMounted = 1; 9758 8410 + 9759 8411 + 9760 + 9761 + /* OK now calculate a few things for the device */ 9762 + 9763 + /* 9764 + * Calculate all the chunk size manipulation numbers: 9765 + */ 9766 + /* Start off assuming it is a power of 2 */ 9767 + dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk); 9768 + dev->chunkMask = (1<<dev->chunkShift) - 1; 9769 + 9770 + if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){ 9771 + /* Yes it is a power of 2, disable crumbs */ 9772 + dev->crumbMask = 0; 9773 + dev->crumbShift = 0; 9774 + dev->crumbsPerChunk = 0; 9775 + } else { 9776 + /* Not a power of 2, use crumbs instead */ 9777 + dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart)); 9778 + dev->crumbMask = (1<<dev->crumbShift)-1; 9779 + dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift); 9780 + dev->chunkShift = 0; 9781 + dev->chunkMask = 0; 9782 + } 9783 + 9784 + 9785 + /* 9786 + * Calculate chunkGroupBits. 9787 + * We need to find the next power of 2 > than internalEndBlock 9788 + */ 9789 + 9790 + x = dev->nChunksPerBlock * (dev->internalEndBlock + 1); 9791 + 9792 + bits = ShiftsGE(x); 9793 + 9794 + /* Set up tnode width if wide tnodes are enabled. */ 9795 + if(!dev->wideTnodesDisabled){ 9796 + /* bits must be even so that we end up with 32-bit words */ 9797 + if(bits & 1) 9798 + bits++; 9799 + if(bits < 16) 9800 + dev->tnodeWidth = 16; 9801 + else 9802 + dev->tnodeWidth = bits; 8412 + nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; 8413 + 8414 + 8415 + 8416 + // OK now calculate a few things for the device 8417 + // Calculate chunkGroupBits. 8418 + // We need to find the next power of 2 > than internalEndBlock 8419 + 8420 + x = dev->nChunksPerBlock * (dev->internalEndBlock+1); 8421 + 8422 + for(bits = extraBits = 0; x > 1; bits++) 8423 + { 8424 + if(x & 1) extraBits++; 8425 + x >>= 1; 8426 + } 8427 + 8428 + if(extraBits > 0) bits++; 8429 + 8430 + 8431 + // Level0 Tnodes are 16 bits, so if the bitwidth of the 8432 + // chunk range we're using is greater than 16 we need 8433 + // to figure out chunk shift and chunkGroupSize 8434 + if(bits <= 16) 8435 + { 8436 + dev->chunkGroupBits = 0; 9803 8437 + } 9804 8438 + else 9805 + dev->tnodeWidth = 16; 9806 + 9807 + dev->tnodeMask = (1<<dev->tnodeWidth)-1; 9808 + 9809 + /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled), 9810 + * so if the bitwidth of the 9811 + * chunk range we're using is greater than 16 we need 9812 + * to figure out chunk shift and chunkGroupSize 9813 + */ 9814 + 9815 + if (bits <= dev->tnodeWidth) 9816 + dev->chunkGroupBits = 0; 9817 + else 9818 + dev->chunkGroupBits = bits - dev->tnodeWidth; 9819 + 9820 + 8439 + { 8440 + dev->chunkGroupBits = bits - 16; 8441 + } 8442 + 9821 8443 + dev->chunkGroupSize = 1 << dev->chunkGroupBits; 9822 8444 + 9823 + if (dev->nChunksPerBlock < dev->chunkGroupSize) { 9824 + /* We have a problem because the soft delete won't work if 9825 + * the chunk group size > chunks per block. 9826 + * This can be remedied by using larger "virtual blocks". 9827 + */ 9828 + T(YAFFS_TRACE_ALWAYS, 9829 + (TSTR("yaffs: chunk group too large\n" TENDSTR))); 9830 + 8445 + if(dev->nChunksPerBlock < dev->chunkGroupSize) 8446 + { 8447 + // We have a problem because the soft delete won't work if 8448 + // the chunk group size > chunks per block. 8449 + // This can be remedied by using larger "virtual blocks". 8450 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: chunk group too large\n" TENDSTR))); 8451 + 9831 8452 + return YAFFS_FAIL; 9832 8453 + } 9833 8454 + 9834 + /* OK, we've finished verifying the device, lets continue with initialisation */ 9835 + 9836 + /* More device initialisation */ 8455 + 8456 + // OK, we've finished verifying the device, lets continue with initialisation 8457 + 8458 + // More device initialisation 9837 8459 + dev->garbageCollections = 0; 9838 8460 + dev->passiveGarbageCollections = 0; … … 9841 8463 + dev->doingBufferedBlockRewrite = 0; 9842 8464 + dev->nDeletedFiles = 0; 9843 + dev->nBackgroundDeletions =0;8465 + dev->nBackgroundDeletions=0; 9844 8466 + dev->nUnlinkedFiles = 0; 9845 + dev->eccFixed =0;9846 + dev->eccUnfixed =0;9847 + dev->tagsEccFixed =0;9848 + dev->tagsEccUnfixed =0;8467 + dev->eccFixed=0; 8468 + dev->eccUnfixed=0; 8469 + dev->tagsEccFixed=0; 8470 + dev->tagsEccUnfixed=0; 9849 8471 + dev->nErasureFailures = 0; 9850 8472 + dev->nErasedBlocks = 0; 9851 8473 + dev->isDoingGC = 0; 9852 + dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */9853 + 9854 + / * Initialise temporary buffers and caches. */8474 + 8475 + //dev->localBuffer = YMALLOC(dev->nBytesPerChunk); 8476 + // Initialise temporary buffers 9855 8477 + { 9856 8478 + int i; 9857 + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { 9858 + dev->tempBuffer[i].line = 0; /* not in use */ 9859 + dev->tempBuffer[i].buffer = 9860 + YMALLOC_DMA(dev->nDataBytesPerChunk); 9861 + } 9862 + } 9863 + 9864 + if (dev->nShortOpCaches > 0) { 8479 + for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) 8480 + { 8481 + dev->tempBuffer[i].line = 0; // not in use 8482 + dev->tempBuffer[i].buffer = YMALLOC(dev->nBytesPerChunk); 8483 + } 8484 + } 8485 + 8486 + 8487 + 8488 + yaffs_InitialiseBlocks(dev,nBlocks); 8489 + 8490 + yaffs_InitialiseTnodes(dev); 8491 + 8492 + yaffs_InitialiseObjects(dev); 8493 + 8494 + dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); 8495 + 8496 + if(dev->nShortOpCaches > 0) 8497 + { 9865 8498 + int i; 9866 + 9867 + if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) { 8499 + 8500 + if(dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) 8501 + { 9868 8502 + dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES; 9869 8503 + } 9870 + 9871 + dev->srCache = 9872 + YMALLOC(dev->nShortOpCaches * sizeof(yaffs_ChunkCache));9873 + 9874 + for (i = 0; i < dev->nShortOpCaches; i++){8504 + 8505 + dev->srCache = YMALLOC( dev->nShortOpCaches * sizeof(yaffs_ChunkCache)); 8506 + 8507 + for(i=0; i < dev->nShortOpCaches; i++) 8508 + { 9875 8509 + dev->srCache[i].object = NULL; 9876 8510 + dev->srCache[i].lastUse = 0; 9877 8511 + dev->srCache[i].dirty = 0; 9878 + dev->srCache[i].data = YMALLOC _DMA(dev->nDataBytesPerChunk);8512 + dev->srCache[i].data = YMALLOC(dev->nBytesPerChunk); 9879 8513 + } 9880 8514 + dev->srLastUse = 0; … … 9883 8517 + dev->cacheHits = 0; 9884 8518 + 9885 + dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); 9886 + 9887 + if (dev->isYaffs2) { 8519 + 8520 + // Initialise the unlinked, root and lost and found directories 8521 + dev->lostNFoundDir = dev->rootDir = dev->unlinkedDir = dev->deletedDir = NULL; 8522 + 8523 + dev->unlinkedDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_UNLINKED, S_IFDIR); 8524 + dev->deletedDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_DELETED, S_IFDIR); 8525 + 8526 + dev->rootDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_ROOT,YAFFS_ROOT_MODE | S_IFDIR); 8527 + dev->lostNFoundDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_LOSTNFOUND,YAFFS_LOSTNFOUND_MODE | S_IFDIR); 8528 + yaffs_AddObjectToDirectory(dev->rootDir,dev->lostNFoundDir); 8529 + 8530 + if(dev->isYaffs2) 8531 + { 9888 8532 + dev->useHeaderFileSize = 1; 9889 8533 + } 9890 + 9891 + yaffs_InitialiseBlocks(dev); 9892 + yaffs_InitialiseTnodes(dev); 9893 + yaffs_InitialiseObjects(dev); 9894 + 9895 + yaffs_CreateInitialDirectories(dev); 9896 + 9897 + 9898 + /* Now scan the flash. */ 9899 + if (dev->isYaffs2) { 9900 + if(yaffs_CheckpointRestore(dev)) { 9901 + T(YAFFS_TRACE_ALWAYS, 9902 + (TSTR("yaffs: restored from checkpoint" TENDSTR))); 9903 + } else { 9904 + 9905 + /* Clean up the mess caused by an aborted checkpoint load 9906 + * and scan backwards. 9907 + */ 9908 + yaffs_DeinitialiseBlocks(dev); 9909 + yaffs_DeinitialiseTnodes(dev); 9910 + yaffs_DeinitialiseObjects(dev); 9911 + yaffs_InitialiseBlocks(dev); 9912 + yaffs_InitialiseTnodes(dev); 9913 + yaffs_InitialiseObjects(dev); 9914 + yaffs_CreateInitialDirectories(dev); 9915 + 9916 + yaffs_ScanBackwards(dev); 9917 + } 9918 + }else 8534 + 8535 + // Now scan the flash. 8536 + 8537 + if(dev->isYaffs2) 8538 + yaffs_ScanBackwards(dev); 8539 + else 9919 8540 + yaffs_Scan(dev); 9920 + 9921 + / * Zero out stats */8541 + 8542 + // Zero out stats 9922 8543 + dev->nPageReads = 0; 9923 + dev->nPageWrites =0;8544 + dev->nPageWrites = 0; 9924 8545 + dev->nBlockErasures = 0; 9925 8546 + dev->nGCCopies = 0; … … 9927 8548 + 9928 8549 + dev->nRetiredBlocks = 0; 9929 + 8550 + 9930 8551 + yaffs_VerifyFreeChunks(dev); 9931 8552 + 9932 + T(YAFFS_TRACE_TRACING, 9933 + (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); 8553 + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); 9934 8554 + return YAFFS_OK; 9935 + 9936 +} 9937 + 9938 +void yaffs_Deinitialise(yaffs_Device * dev) 9939 +{ 9940 + if (dev->isMounted) { 8555 + 8556 +} 8557 + 8558 +void yaffs_Deinitialise(yaffs_Device *dev) 8559 +{ 8560 + if(dev->isMounted) 8561 + { 9941 8562 + int i; 9942 + 8563 + 9943 8564 + yaffs_DeinitialiseBlocks(dev); 9944 8565 + yaffs_DeinitialiseTnodes(dev); 9945 8566 + yaffs_DeinitialiseObjects(dev); 9946 + if (dev->nShortOpCaches > 0) { 9947 + 9948 + for (i = 0; i < dev->nShortOpCaches; i++) { 8567 + if(dev->nShortOpCaches > 0) 8568 + { 8569 + 8570 + for(i=0; i < dev->nShortOpCaches; i++) 8571 + { 9949 8572 + YFREE(dev->srCache[i].data); 9950 8573 + } … … 9955 8578 + YFREE(dev->gcCleanupList); 9956 8579 + 9957 + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { 8580 + for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) 8581 + { 9958 8582 + YFREE(dev->tempBuffer[i].buffer); 9959 8583 + } 9960 + 8584 + 9961 8585 + dev->isMounted = 0; 9962 8586 + } 9963 + 9964 +} 9965 + 9966 +static int yaffs_CountFreeChunks(yaffs_Device * dev) 8587 + 8588 +} 8589 + 8590 +#if 0 8591 + 8592 +int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) 8593 +{ 8594 + int nFree = dev->nFreeChunks - (dev->nChunksPerBlock * YAFFS_RESERVED_BLOCKS); 8595 + 8596 + struct list_head *i; 8597 + yaffs_Object *l; 8598 + 8599 + 8600 + // To the free chunks add the chunks that are in the deleted unlinked files. 8601 + list_for_each(i,&dev->deletedDir->variant.directoryVariant.children) 8602 + { 8603 + l = list_entry(i, yaffs_Object,siblings); 8604 + if(l->deleted) 8605 + { 8606 + nFree++; 8607 + nFree += l->nDataChunks; 8608 + } 8609 + } 8610 + 8611 + 8612 + // printf("___________ nFreeChunks is %d nFree is %d\n",dev->nFreeChunks,nFree); 8613 + 8614 + if(nFree < 0) nFree = 0; 8615 + 8616 + return nFree; 8617 + 8618 +} 8619 + 8620 +#endif 8621 + 8622 +static int yaffs_CountFreeChunks(yaffs_Device *dev) 9967 8623 +{ 9968 8624 + int nFree; 9969 8625 + int b; 9970 8626 + 9971 + yaffs_BlockInfo *blk; 9972 + 9973 + for (nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock; 9974 + b++) { 9975 + blk = yaffs_GetBlockInfo(dev, b); 9976 + 9977 + switch (blk->blockState) { 9978 + case YAFFS_BLOCK_STATE_EMPTY: 9979 + case YAFFS_BLOCK_STATE_ALLOCATING: 9980 + case YAFFS_BLOCK_STATE_COLLECTING: 9981 + case YAFFS_BLOCK_STATE_FULL: 9982 + nFree += 9983 + (dev->nChunksPerBlock - blk->pagesInUse + 9984 + blk->softDeletions); 9985 + break; 9986 + default: 9987 + break; 9988 + } 9989 + 9990 + } 9991 + 8627 + yaffs_BlockInfo *blk; 8628 + 8629 + 8630 + for(nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock; b++) 8631 + { 8632 + blk = yaffs_GetBlockInfo(dev,b); 8633 + 8634 + switch(blk->blockState) 8635 + { 8636 + case YAFFS_BLOCK_STATE_EMPTY: 8637 + case YAFFS_BLOCK_STATE_ALLOCATING: 8638 + case YAFFS_BLOCK_STATE_COLLECTING: 8639 + case YAFFS_BLOCK_STATE_FULL: nFree += (dev->nChunksPerBlock - blk->pagesInUse + blk->softDeletions); break; 8640 + default: break; 8641 + } 8642 + 8643 + } 8644 + 9992 8645 + return nFree; 9993 +} 9994 + 9995 +int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev) 9996 +{ 9997 + /* This is what we report to the outside world */ 8646 +} 8647 + 8648 + 8649 + 8650 +int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) 8651 +{ 8652 + // This is what we report to the outside world 9998 8653 + 9999 8654 + int nFree; 10000 8655 + int nDirtyCacheChunks; 10001 + int blocksForCheckpoint; 10002 + 10003 +#if 1 8656 + 8657 +#if 1 10004 8658 + nFree = dev->nFreeChunks; 10005 8659 +#else 10006 8660 + nFree = yaffs_CountFreeChunks(dev); 10007 8661 +#endif 10008 + 10009 + nFree += dev->nDeletedFiles; 10010 + 10011 + /* Now count the number of dirty chunks in the cache and subtract those */ 10012 + 8662 + 8663 + // Now count the number of dirty chunks in the cache and subtract those 8664 + 10013 8665 + { 10014 8666 + int i; 10015 + for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) {10016 + if (dev->srCache[i].dirty)10017 + nDirtyCacheChunks++;10018 + } 10019 + } 10020 + 8667 + for( nDirtyCacheChunks = 0,i = 0; i < dev->nShortOpCaches; i++) 8668 + { 8669 + if(dev->srCache[i].dirty) nDirtyCacheChunks++; 8670 + } 8671 + } 8672 + 10021 8673 + nFree -= nDirtyCacheChunks; 10022 + 8674 + 10023 8675 + nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock); 10024 8676 + 10025 + /* Now we figure out how much to reserve for the checkpoint and report that... */ 10026 + blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; 10027 + if(blocksForCheckpoint < 0) 10028 + blocksForCheckpoint = 0; 10029 + 10030 + nFree -= (blocksForCheckpoint * dev->nChunksPerBlock); 10031 + 10032 + if (nFree < 0) 10033 + nFree = 0; 10034 + 10035 + return nFree; 10036 + 10037 +} 10038 + 10039 +static int yaffs_freeVerificationFailures; 10040 + 10041 +static void yaffs_VerifyFreeChunks(yaffs_Device * dev) 8677 + if(nFree < 0) nFree = 0; 8678 + 8679 + return nFree; 8680 + 8681 +} 8682 + 8683 +static int yaffs_freeVerificationFailures; 8684 + 8685 +static void yaffs_VerifyFreeChunks(yaffs_Device *dev) 10042 8686 +{ 10043 8687 + int counted = yaffs_CountFreeChunks(dev); 10044 + 8688 + 10045 8689 + int difference = dev->nFreeChunks - counted; 10046 + 10047 + if (difference) { 10048 + T(YAFFS_TRACE_ALWAYS, 10049 + (TSTR("Freechunks verification failure %d %d %d" TENDSTR), 10050 + dev->nFreeChunks, counted, difference)); 10051 + yaffs_freeVerificationFailures++; 10052 + } 10053 +} 10054 + 10055 +/*---------------------------------------- YAFFS test code ----------------------*/ 8690 + 8691 + if(difference) 8692 + { 8693 + T(YAFFS_TRACE_ALWAYS,(TSTR("Freechunks verification failure %d %d %d" TENDSTR),dev->nFreeChunks,counted,difference)); 8694 + yaffs_freeVerificationFailures++; 8695 + } 8696 +} 8697 + 8698 +/////////////////// YAFFS test code ////////////////////////////////// 10056 8699 + 10057 8700 +#define yaffs_CheckStruct(structure,syze, name) \ 10058 8701 + if(sizeof(structure) != syze) \ 10059 8702 + { \ 10060 + T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\ 10061 + name,syze,sizeof(structure))); \ 8703 + T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),name,syze,sizeof(structure))); \ 10062 8704 + return YAFFS_FAIL; \ 10063 + } 10064 + 8705 + } 8706 + 8707 + 10065 8708 +static int yaffs_CheckStructures(void) 10066 8709 +{ 10067 +/ * yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */10068 +/ * yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */10069 +/ * yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */8710 +// yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") 8711 +// yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") 8712 +// yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") 10070 8713 +#ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG 10071 + yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode") 10072 +#endif 10073 + yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader") 10074 + 10075 + return YAFFS_OK; 10076 +} 10077 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_guts.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.h 10078 --- linux-2.6.18.2/fs/yaffs2/yaffs_guts.h 1970-01-01 01:00:00.000000000 +0100 10079 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.h 2006-11-25 00:15:32.000000000 +0100 10080 @@ -0,0 +1,893 @@ 8714 + yaffs_CheckStruct(yaffs_Tnode,2* YAFFS_NTNODES_LEVEL0,"yaffs_Tnode") 8715 +#endif 8716 + yaffs_CheckStruct(yaffs_ObjectHeader,512,"yaffs_ObjectHeader") 8717 + 8718 + 8719 + return YAFFS_OK; 8720 +} 8721 + 8722 +#if 0 8723 +void yaffs_GutsTest(yaffs_Device *dev) 8724 +{ 8725 + 8726 + if(yaffs_CheckStructures() != YAFFS_OK) 8727 + { 8728 + T(YAFFS_TRACE_ALWAYS,(TSTR("One or more structures malformed-- aborting\n" TENDSTR))); 8729 + return; 8730 + } 8731 + 8732 + yaffs_TnodeTest(dev); 8733 + yaffs_ObjectTest(dev); 8734 +} 8735 +#endif 8736 + 8737 + 8738 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h 8739 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h 1970-01-01 01:00:00.000000000 +0100 8740 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h 2006-12-10 04:23:35.000000000 +0100 8741 @@ -0,0 +1,760 @@ 10081 8742 +/* 10082 8743 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 10095 8756 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. 10096 8757 + * 10097 + * $Id: yaffs_guts.h,v 1. 25 2006/10/13 08:52:49charles Exp $8758 + * $Id: yaffs_guts.h,v 1.11 2005/07/31 06:52:40 charles Exp $ 10098 8759 + */ 10099 8760 + … … 10107 8768 +#define YAFFS_FAIL 0 10108 8769 + 10109 +/* Give us a Y=0x59, 10110 + * Give us an A=0x41, 10111 + * Give us an FF=0xFF 10112 + * Give us an S=0x53 10113 + * And what have we got... 10114 + */ 10115 +#define YAFFS_MAGIC 0x5941FF53 8770 +// Give us a Y=0x59, 8771 +// Give us an A=0x41, 8772 +// Give us an FF=0xFF 8773 +// Give us an S=0x53 8774 +// And what have we got... 8775 +#define YAFFS_MAGIC 0x5941FF53 10116 8776 + 10117 8777 +#define YAFFS_NTNODES_LEVEL0 16 … … 10135 8795 +#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32 10136 8796 + 10137 +#define YAFFS_MAX_CHUNK_ID 0x000FFFFF8797 +#define YAFFS_MAX_CHUNK_ID 0x000FFFFF 10138 8798 + 10139 8799 +#define YAFFS_UNUSED_OBJECT_ID 0x0003FFFF … … 10146 8806 + 10147 8807 + 10148 +#define YAFFS_OBJECT_SPACE 0x40000 10149 + 10150 +#define YAFFS_NCHECKPOINT_OBJECTS 5000 10151 + 10152 +#define YAFFS_CHECKPOINT_VERSION 2 8808 +#define YAFFS_OBJECT_SPACE 0x40000 10153 8809 + 10154 8810 +#ifdef CONFIG_YAFFS_UNICODE … … 10162 8818 +#define YAFFS_SHORT_NAME_LENGTH 15 10163 8819 + 10164 + /* Some special object ids for pseudo objects */10165 +#define YAFFS_OBJECTID_ROOT 18820 + 8821 +#define YAFFS_OBJECTID_ROOT 1 10166 8822 +#define YAFFS_OBJECTID_LOSTNFOUND 2 10167 8823 +#define YAFFS_OBJECTID_UNLINKED 3 10168 8824 +#define YAFFS_OBJECTID_DELETED 4 10169 8825 + 10170 +/* Sseudo object ids for checkpointing */10171 +#define YAFFS_OBJECTID_SB_HEADER 0x1010172 +#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x2010173 +#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x2110174 +10175 +/* */10176 +10177 8826 +#define YAFFS_MAX_SHORT_OP_CACHES 20 10178 8827 + 10179 8828 +#define YAFFS_N_TEMP_BUFFERS 4 10180 8829 + 10181 +/ *Sequence numbers are used in YAFFS2 to determine block allocation order.10182 + *The range is limited slightly to help distinguish bad numbers from good.10183 + *This also allows us to perhaps in the future use special numbers for10184 + *special purposes.10185 + *EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,10186 + *and is a larger number than the lifetime of a 2GB device.10187 + */8830 +// Sequence numbers are used in YAFFS2 to determine block allocation order. 8831 +// The range is limited slightly to help distinguish bad numbers from good. 8832 +// This also allows us to perhaps in the future use special numbers for 8833 +// special purposes. 8834 +// EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, 8835 +// and is a larger number than the lifetime of a 2GB device. 8836 + 10188 8837 +#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000 10189 8838 +#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xEFFFFF00 10190 8839 + 10191 +/* ChunkCache is used for short read/write operations.*/ 10192 +typedef struct { 8840 + 8841 +// ChunkCache is used for short read/write operations. 8842 +typedef struct 8843 +{ 10193 8844 + struct yaffs_ObjectStruct *object; 10194 8845 + int chunkId; 10195 8846 + int lastUse; 10196 + int dirty; 10197 + int nBytes; /* Only valid if the cache is dirty */10198 + int locked; /* Can't push out or flush while locked. */8847 + int dirty; 8848 + int nBytes; // Only valid if the cache is dirty 8849 + int locked; // Can't push out or flush while locked.. 10199 8850 +#ifdef CONFIG_YAFFS_YAFFS2 10200 8851 + __u8 *data; … … 10205 8856 + 10206 8857 + 10207 +10208 +/* Tags structures in RAM10209 + * NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise10210 + * the structure size will get blown out.10211 + */10212 +10213 8858 +#ifndef CONFIG_YAFFS_NO_YAFFS1 10214 +typedef struct { 8859 +// Tags structures in RAM 8860 +// NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise 8861 +// the structure size will get blown out. 8862 + 8863 +typedef struct 8864 +{ 10215 8865 + unsigned chunkId:20; 10216 + unsigned serialNumber:2;10217 + unsigned byteCount:10;10218 + unsigned objectId:18;10219 + unsigned ecc:12;10220 + unsigned unusedStuff:2;8866 + unsigned serialNumber:2; 8867 + unsigned byteCount:10; 8868 + unsigned objectId:18; 8869 + unsigned ecc:12; 8870 + unsigned unusedStuff:2; 10221 8871 + 10222 8872 +} yaffs_Tags; 10223 8873 + 10224 +typedef union { 10225 + yaffs_Tags asTags; 10226 + __u8 asBytes[8]; 8874 +typedef union 8875 +{ 8876 + yaffs_Tags asTags; 8877 + __u8 asBytes[8]; 10227 8878 +} yaffs_TagsUnion; 10228 8879 + 10229 8880 +#endif 10230 8881 + 10231 +/* Stuff used for extended tags in YAFFS2 */ 10232 + 10233 +typedef enum { 8882 +typedef enum 8883 +{ 10234 8884 + YAFFS_ECC_RESULT_UNKNOWN, 10235 8885 + YAFFS_ECC_RESULT_NO_ERROR, … … 10238 8888 +} yaffs_ECCResult; 10239 8889 + 10240 +typedef enum { 8890 +typedef enum 8891 +{ 10241 8892 + YAFFS_OBJECT_TYPE_UNKNOWN, 10242 8893 + YAFFS_OBJECT_TYPE_FILE, … … 10247 8898 +} yaffs_ObjectType; 10248 8899 + 10249 +typedef struct { 8900 + 8901 +typedef struct 8902 +{ 10250 8903 + 10251 8904 + unsigned validMarker0; 10252 + unsigned chunkUsed; /* Status of the chunk: used or unused */ 10253 + unsigned objectId; /* If 0 then this is not part of an object (unused) */ 10254 + unsigned chunkId; /* If 0 then this is a header, else a data chunk */ 10255 + unsigned byteCount; /* Only valid for data chunks */ 10256 + 10257 + /* The following stuff only has meaning when we read */ 10258 + yaffs_ECCResult eccResult; 10259 + unsigned blockBad; 10260 + 10261 + /* YAFFS 1 stuff */ 10262 + unsigned chunkDeleted; /* The chunk is marked deleted */ 10263 + unsigned serialNumber; /* Yaffs1 2-bit serial number */ 10264 + 10265 + /* YAFFS2 stuff */ 10266 + unsigned sequenceNumber; /* The sequence number of this block */ 10267 + 10268 + /* Extra info if this is an object header (YAFFS2 only) */ 10269 + 10270 + unsigned extraHeaderInfoAvailable; /* There is extra info available if this is not zero */ 10271 + unsigned extraParentObjectId; /* The parent object */ 10272 + unsigned extraIsShrinkHeader; /* Is it a shrink header? */ 10273 + unsigned extraShadows; /* Does this shadow another object? */ 10274 + 10275 + yaffs_ObjectType extraObjectType; /* What object type? */ 10276 + 10277 + unsigned extraFileLength; /* Length if it is a file */ 10278 + unsigned extraEquivalentObjectId; /* Equivalent object Id if it is a hard link */ 10279 + 10280 + unsigned validMarker1; 10281 + 8905 + unsigned chunkUsed; // Status of the chunk: used or unused 8906 + unsigned objectId; // If 0 then this is not part of an object (unused) 8907 + unsigned chunkId; // If 0 then this is a header, else a data chunk 8908 + unsigned byteCount; // Only valid for data chunks 8909 + 8910 + 8911 + // The following stuff only has meaning when we read 8912 + yaffs_ECCResult eccResult; // Only valid when we read. 8913 + unsigned blockBad; // Only valid on reading 8914 + 8915 + // YAFFS 1 stuff 8916 + unsigned chunkDeleted; // The chunk is marked deleted 8917 + unsigned serialNumber; // Yaffs1 2-bit serial number 8918 + 8919 + // YAFFS2 stuff 8920 + unsigned sequenceNumber; // The sequence number of this block 8921 + 8922 + // Extra info if this is an object header (YAFFS2 only) 8923 + 8924 + unsigned extraHeaderInfoAvailable; // There is extra info available if this is not zero 8925 + unsigned extraParentObjectId; // The parent object 8926 + unsigned extraIsShrinkHeader; // Is it a shrink header? 8927 + unsigned extraShadows; // Does this shadow another object? 8928 + 8929 + yaffs_ObjectType extraObjectType; // What object type? 8930 + 8931 + unsigned extraFileLength; // Length if it is a file 8932 + unsigned extraEquivalentObjectId; // Equivalent object Id if it is a hard link 8933 + 8934 + unsigned validMarker1; 8935 + 10282 8936 +} yaffs_ExtendedTags; 10283 8937 + 10284 +/* Spare structure for YAFFS1 */ 10285 +typedef struct { 10286 + __u8 tagByte0; 10287 + __u8 tagByte1; 10288 + __u8 tagByte2; 10289 + __u8 tagByte3; 10290 + __u8 pageStatus; /* set to 0 to delete the chunk */ 10291 + __u8 blockStatus; 10292 + __u8 tagByte4; 10293 + __u8 tagByte5; 10294 + __u8 ecc1[3]; 10295 + __u8 tagByte6; 10296 + __u8 tagByte7; 10297 + __u8 ecc2[3]; 8938 +#ifndef CONFIG_YAFFS_NO_YAFFS1 8939 +// Spare structure 8940 +typedef struct 8941 +{ 8942 + __u8 tagByte0; 8943 + __u8 tagByte1; 8944 + __u8 tagByte2; 8945 + __u8 tagByte3; 8946 + __u8 pageStatus; // set to 0 to delete the chunk 8947 + __u8 blockStatus; 8948 + __u8 tagByte4; 8949 + __u8 tagByte5; 8950 + __u8 ecc1[3]; 8951 + __u8 tagByte6; 8952 + __u8 tagByte7; 8953 + __u8 ecc2[3]; 10298 8954 +} yaffs_Spare; 10299 8955 + 10300 +/ *Special structure for passing through to mtd */8956 +//Special structure for passing through to mtd 10301 8957 +struct yaffs_NANDSpare { 10302 + yaffs_Spare spare;10303 + int eccres1;10304 + int eccres2;8958 + yaffs_Spare spare; 8959 + int eccres1; 8960 + int eccres2; 10305 8961 +}; 10306 + 10307 +/* Block data in RAM */ 8962 +#endif 8963 + 8964 + 8965 +// Block data in RAM 10308 8966 + 10309 8967 +typedef enum { 10310 + YAFFS_BLOCK_STATE_UNKNOWN = 0,8968 + YAFFS_BLOCK_STATE_UNKNOWN = 0, 10311 8969 + 10312 8970 + YAFFS_BLOCK_STATE_SCANNING, 10313 + YAFFS_BLOCK_STATE_NEEDS_SCANNING, 10314 + /* The block might have something on it (ie it is allocating or full, perhaps empty) 10315 + * but it needs to be scanned to determine its true state. 10316 + * This state is only valid during yaffs_Scan. 10317 + * NB We tolerate empty because the pre-scanner might be incapable of deciding 10318 + * However, if this state is returned on a YAFFS2 device, then we expect a sequence number 10319 + */ 10320 + 10321 + YAFFS_BLOCK_STATE_EMPTY, 10322 + /* This block is empty */ 10323 + 10324 + YAFFS_BLOCK_STATE_ALLOCATING, 10325 + /* This block is partially allocated. 10326 + * At least one page holds valid data. 10327 + * This is the one currently being used for page 10328 + * allocation. Should never be more than one of these 10329 + */ 10330 + 10331 + YAFFS_BLOCK_STATE_FULL, 10332 + /* All the pages in this block have been allocated. 10333 + */ 10334 + 10335 + YAFFS_BLOCK_STATE_DIRTY, 10336 + /* All pages have been allocated and deleted. 10337 + * Erase me, reuse me. 10338 + */ 10339 + 10340 + YAFFS_BLOCK_STATE_CHECKPOINT, 10341 + /* This block is assigned to holding checkpoint data. 10342 + */ 10343 + 10344 + YAFFS_BLOCK_STATE_COLLECTING, 10345 + /* This block is being garbage collected */ 10346 + 10347 + YAFFS_BLOCK_STATE_DEAD 10348 + /* This block has failed and is not in use */ 8971 + YAFFS_BLOCK_STATE_NEEDS_SCANNING,// The block might have something on it (ie it is allocating or full, perhaps empty) 8972 + // but it needs to be scanned to determine its true state. 8973 + // This state is only valid during yaffs_Scan. 8974 + // NB We tolerate empty because the pre-scanner might be incapable of deciding 8975 + // However, if this state is returned on a YAFFS2 device, then we expect a sequence number 8976 + 8977 + YAFFS_BLOCK_STATE_EMPTY, // This block is empty 8978 + 8979 + YAFFS_BLOCK_STATE_ALLOCATING, // This block is partially allocated. 8980 + // This is the one currently being used for page 8981 + // allocation. Should never be more than one of these 8982 + 8983 + 8984 + YAFFS_BLOCK_STATE_FULL, // All the pages in this block have been allocated. 8985 + // At least one page holds valid data. 8986 + 8987 + YAFFS_BLOCK_STATE_DIRTY, // All pages have been allocated and deleted. 8988 + // Erase me, reuse me. 8989 + 8990 + YAFFS_BLOCK_STATE_COLLECTING, // This block is being garbage collected 8991 + 8992 + YAFFS_BLOCK_STATE_DEAD // This block has failed and is not in use 8993 + 10349 8994 +} yaffs_BlockState; 10350 8995 + 10351 +typedef struct { 10352 + 10353 + int softDeletions:10; /* number of soft deleted pages */ 10354 + int pagesInUse:10; /* number of pages in use */ 10355 + yaffs_BlockState blockState:4; /* One of the above block states */ 10356 + __u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */ 10357 + /* and retire the block. */ 10358 + __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */ 10359 + __u32 gcPrioritise: 1; /* An ECC check or bank check has failed on this block. 10360 + It should be prioritised for GC */ 10361 + __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */ 10362 + 8996 + 8997 + 8998 + 8999 +typedef struct 9000 +{ 9001 + 9002 + int softDeletions:12; // number of soft deleted pages 9003 + int pagesInUse:12; // number of pages in use 9004 + yaffs_BlockState blockState:4; // One of the above block states 9005 + __u32 needsRetiring:1; // Data has failed on this block, need to get valid data off 9006 + // and retire the block. 10363 9007 +#ifdef CONFIG_YAFFS_YAFFS2 10364 + __u32 hasShrinkHeader:1; /* This block has at least one shrink object header */10365 + __u32 sequenceNumber; /* block sequence number for yaffs2 */9008 + __u32 hasShrinkHeader:1;// This block has at least one object header that does a shrink 9009 + __u32 sequenceNumber; // block sequence number for yaffs2 10366 9010 +#endif 10367 9011 + 10368 9012 +} yaffs_BlockInfo; 10369 9013 + 10370 +/* -------------------------- Object structure -------------------------------*/ 10371 +/* This is the object structure as stored on NAND */ 10372 + 10373 +typedef struct { 9014 + 9015 +//////////////////// Object structure /////////////////////////// 9016 +// This is the object structure as stored on NAND 9017 + 9018 +typedef struct 9019 +{ 10374 9020 + yaffs_ObjectType type; 10375 9021 + 10376 + / * Apply to everything */10377 + int parentObjectId;10378 + __u16 sum__NoLongerUsed; / * checksum of name. No longer used */10379 + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];10380 + 10381 + / * Thes following apply to directories, files, symlinks - not hard links */10382 + __u32 yst_mode; /* protection */9022 + // Apply to everything 9023 + int parentObjectId; 9024 + __u16 sum__NoLongerUsed; // checksum of name. Calc this off the name to prevent inconsistencies 9025 + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; 9026 + 9027 + // Thes following apply to directories, files, symlinks - not hard links 9028 + __u32 yst_mode; // protection 10383 9029 + 10384 9030 +#ifdef CONFIG_YAFFS_WINCE 10385 9031 + __u32 notForWinCE[5]; 10386 9032 +#else 10387 + __u32 yst_uid; 10388 + __u32 yst_gid; 10389 + __u32 yst_atime; 10390 + __u32 yst_mtime; 10391 + __u32 yst_ctime; 10392 +#endif 10393 + 10394 + / * File size applies to files only */10395 + int fileSize; 10396 + 10397 + / * Equivalent object id applies to hard links only. */10398 + int equivalentObjectId;10399 + 10400 + / * Alias is for symlinks only. */9033 + __u32 yst_uid; // user ID of owner 9034 + __u32 yst_gid; // group ID of owner 9035 + __u32 yst_atime; // time of last access 9036 + __u32 yst_mtime; // time of last modification 9037 + __u32 yst_ctime; // time of last change 9038 +#endif 9039 + 9040 + // File size applies to files only 9041 + int fileSize; 9042 + 9043 + // Equivalent object id applies to hard links only. 9044 + int equivalentObjectId; 9045 + 9046 + // Alias is for symlinks only. 10401 9047 + YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1]; 10402 + 10403 + __u32 yst_rdev; /* device stuff for block and char devices (major/min) */10404 + 9048 + 9049 + __u32 yst_rdev; // device stuff for block and char devices (maj/min) 9050 + 10405 9051 +#ifdef CONFIG_YAFFS_WINCE 10406 9052 + __u32 win_ctime[2]; … … 10412 9058 +#endif 10413 9059 + 10414 + int shadowsObject; /* This object header shadows the specified object if > 0 */10415 + 10416 + / * isShrink applies to object headers written when we shrink the file (ie resize) */9060 + int shadowsObject; // This object header shadows the specified object if not > 0 9061 + 9062 + // isShrink applies to object headers written when we shrink the file (ie resize) 10417 9063 + __u32 isShrink; 10418 + 9064 + 10419 9065 +} yaffs_ObjectHeader; 10420 9066 + 10421 +/*--------------------------- Tnode -------------------------- */ 10422 + 10423 +union yaffs_Tnode_union { 9067 + 9068 + 9069 +//////////////////// Tnode /////////////////////////// 9070 + 9071 +union yaffs_Tnode_union 9072 +{ 10424 9073 +#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG 10425 + union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL +1];9074 + union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL+1]; 10426 9075 +#else 10427 9076 + union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL]; 10428 9077 +#endif 10429 + /* __u16 level0[YAFFS_NTNODES_LEVEL0]; */10430 + 9078 + __u16 level0[YAFFS_NTNODES_LEVEL0]; 9079 + 10431 9080 +}; 10432 9081 + 10433 9082 +typedef union yaffs_Tnode_union yaffs_Tnode; 10434 9083 + 10435 +struct yaffs_TnodeList_struct { 9084 +struct yaffs_TnodeList_struct 9085 +{ 10436 9086 + struct yaffs_TnodeList_struct *next; 10437 9087 + yaffs_Tnode *tnodes; … … 10440 9090 +typedef struct yaffs_TnodeList_struct yaffs_TnodeList; 10441 9091 + 10442 +/*------------------------ Object -----------------------------*/ 10443 +/* An object can be one of: 10444 + * - a directory (no data, has children links 10445 + * - a regular file (data.... not prunes :->). 10446 + * - a symlink [symbolic link] (the alias). 10447 + * - a hard link 10448 + */ 10449 + 10450 +typedef struct { 9092 + 9093 + 9094 +/////////////////// Object //////////////////////////////// 9095 +// An object can be one of: 9096 +// - a directory (no data, has children links 9097 +// - a regular file (data.... not prunes :->). 9098 +// - a symlink [symbolic link] (the alias). 9099 +// - a hard link 9100 + 9101 + 9102 +typedef struct 9103 +{ 10451 9104 + __u32 fileSize; 10452 9105 + __u32 scannedFileSize; 10453 9106 + __u32 shrinkSize; 10454 + int topLevel;9107 + int topLevel; 10455 9108 + yaffs_Tnode *top; 10456 9109 +} yaffs_FileStructure; 10457 9110 + 10458 +typedef struct { 10459 + struct list_head children; /* list of child links */ 9111 +typedef struct 9112 +{ 9113 + struct list_head children; // list of child links 10460 9114 +} yaffs_DirectoryStructure; 10461 9115 + 10462 +typedef struct { 9116 +typedef struct 9117 +{ 10463 9118 + YCHAR *alias; 10464 9119 +} yaffs_SymLinkStructure; 10465 9120 + 10466 +typedef struct { 9121 +typedef struct 9122 +{ 10467 9123 + struct yaffs_ObjectStruct *equivalentObject; 10468 + __u32 equivalentObjectId;9124 + __u32 equivalentObjectId; 10469 9125 +} yaffs_HardLinkStructure; 10470 9126 + 10471 +typedef union { 9127 +typedef union 9128 +{ 10472 9129 + yaffs_FileStructure fileVariant; 10473 9130 + yaffs_DirectoryStructure directoryVariant; … … 10476 9133 +} yaffs_ObjectVariant; 10477 9134 + 10478 +struct yaffs_ObjectStruct { 10479 + __u8 deleted:1; /* This should only apply to unlinked files. */ 10480 + __u8 softDeleted:1; /* it has also been soft deleted */ 10481 + __u8 unlinked:1; /* An unlinked file. The file should be in the unlinked directory.*/ 10482 + __u8 fake:1; /* A fake object has no presence on NAND. */ 10483 + __u8 renameAllowed:1; /* Some objects are not allowed to be renamed. */ 9135 + 9136 +struct yaffs_ObjectStruct 9137 +{ 9138 + __u8 deleted: 1; // This should only apply to unlinked files. 9139 + __u8 softDeleted: 1; // it has also been soft deleted 9140 + __u8 unlinked: 1; // An unlinked file. The file should be in the unlinked pseudo directory. 9141 + __u8 fake:1; // A fake object has no presence on NAND. 9142 + __u8 renameAllowed:1; // Some objects are not allowed to be renamed. 10484 9143 + __u8 unlinkAllowed:1; 10485 + __u8 dirty:1; /* the object needs to be written to flash */ 10486 + __u8 valid:1; /* When the file system is being loaded up, this 10487 + * object might be created before the data 10488 + * is available (ie. file data records appear before the header). 10489 + */ 10490 + __u8 lazyLoaded:1; /* This object has been lazy loaded and is missing some detail */ 10491 + 10492 + __u8 deferedFree:1; /* For Linux kernel. Object is removed from NAND, but is 10493 + * still in the inode cache. Free of object is defered. 10494 + * until the inode is released. 10495 + */ 10496 + 10497 + __u8 serial; /* serial number of chunk in NAND. Cached here */ 10498 + __u16 sum; /* sum of the name to speed searching */ 10499 + 10500 + struct yaffs_DeviceStruct *myDev; /* The device I'm on */ 10501 + 10502 + struct list_head hashLink; /* list of objects in this hash bucket */ 10503 + 10504 + struct list_head hardLinks; /* all the equivalent hard linked objects */ 10505 + 10506 + /* directory structure stuff */ 10507 + /* also used for linking up the free list */ 10508 + struct yaffs_ObjectStruct *parent; 10509 + struct list_head siblings; 10510 + 10511 + /* Where's my object header in NAND? */ 10512 + int chunkId; 10513 + 10514 + int nDataChunks; /* Number of data chunks attached to the file. */ 10515 + 10516 + __u32 objectId; /* the object id value */ 10517 + 10518 + __u32 yst_mode; 9144 + __u8 dirty:1; // the object needs to be written to flash 9145 + __u8 valid:1; // When the file system is being loaded up, this 9146 + // object might be created before the data 9147 + // is available (ie. file data records appear before the header). 9148 + __u8 serial; // serial number of chunk in NAND. Store here so we don't have to 9149 + 9150 + __u8 deferedFree: 1; // For Linux kernel. Object is removed from NAND, but still in the inode cache. 9151 + // Free of object is defered. 9152 + 9153 + __u8 lazyLoaded; // Vital info has been loaded from tags. Not all info available. 9154 + // 9155 + 9156 + // read back the old one to update. 9157 + __u16 sum; // sum of the name to speed searching 9158 + 9159 + struct yaffs_DeviceStruct *myDev; // The device I'm on 9160 + 9161 + 9162 + struct list_head hashLink; // list of objects in this hash bucket 9163 + 9164 + 9165 + struct list_head hardLinks; // all the equivalent hard linked objects 9166 + // live on this list 9167 + // directory structure stuff 9168 + struct yaffs_ObjectStruct *parent; //my parent directory 9169 + struct list_head siblings; // siblings in a directory 9170 + // also used for linking up the free list 9171 + 9172 + // Where's my object header in NAND? 9173 + int chunkId; // where it lives 9174 + 9175 + int nDataChunks; // Number of data chunks attached to the file. 9176 + 9177 + __u32 objectId; // the object id value 9178 + 9179 + 9180 + __u32 yst_mode; // protection 10519 9181 + 10520 9182 +#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM 10521 + YCHAR shortName[YAFFS_SHORT_NAME_LENGTH +1];9183 + YCHAR shortName[YAFFS_SHORT_NAME_LENGTH+1]; 10522 9184 +#endif 10523 9185 + … … 10531 9193 + __u32 win_atime[2]; 10532 9194 +#else 10533 + __u32 yst_uid; 10534 + __u32 yst_gid; 10535 + __u32 yst_atime; 10536 + __u32 yst_mtime; 10537 + __u32 yst_ctime; 10538 +#endif 10539 + 10540 + __u32 yst_rdev; 9195 + __u32 yst_uid; // user ID of owner 9196 + __u32 yst_gid; // group ID of owner 9197 + __u32 yst_atime; // time of last access 9198 + __u32 yst_mtime; // time of last modification 9199 + __u32 yst_ctime; // time of last change 9200 +#endif 9201 + 9202 + __u32 yst_rdev; // device stuff for block and char devices 9203 + 9204 + 10541 9205 + 10542 9206 +#ifdef __KERNEL__ … … 10545 9209 +#endif 10546 9210 + 9211 + 9212 + 10547 9213 + yaffs_ObjectType variantType; 10548 + 9214 + 10549 9215 + yaffs_ObjectVariant variant; 10550 + 9216 + 10551 9217 +}; 10552 9218 + 9219 + 9220 + 10553 9221 +typedef struct yaffs_ObjectStruct yaffs_Object; 10554 9222 + 10555 +struct yaffs_ObjectList_struct { 9223 + 9224 +struct yaffs_ObjectList_struct 9225 +{ 10556 9226 + yaffs_Object *objects; 10557 9227 + struct yaffs_ObjectList_struct *next; … … 10560 9230 +typedef struct yaffs_ObjectList_struct yaffs_ObjectList; 10561 9231 + 10562 +typedef struct { 9232 +typedef struct 9233 +{ 10563 9234 + struct list_head list; 10564 9235 + int count; 10565 9236 +} yaffs_ObjectBucket; 10566 9237 + 10567 + 10568 +/* yaffs_CheckpointObject holds the definition of an object as dumped 10569 + * by checkpointing. 10570 + */ 10571 + 10572 +typedef struct { 10573 + int structType; 10574 + __u32 objectId; 10575 + __u32 parentId; 10576 + int chunkId; 10577 + 10578 + yaffs_ObjectType variantType:3; 10579 + __u8 deleted:1; 10580 + __u8 softDeleted:1; 10581 + __u8 unlinked:1; 10582 + __u8 fake:1; 10583 + __u8 renameAllowed:1; 10584 + __u8 unlinkAllowed:1; 10585 + __u8 serial; 10586 + 10587 + int nDataChunks; 10588 + __u32 fileSizeOrEquivalentObjectId; 10589 + 10590 +}yaffs_CheckpointObject; 10591 + 10592 +/*--------------------- Temporary buffers ---------------- 10593 + * 10594 + * These are chunk-sized working buffers. Each device has a few 10595 + */ 9238 +///////////////////// Temporary buffers //////////////////// 9239 +// 9240 +// These are chunk-sized working buffers. Each device has a few 10596 9241 + 10597 9242 +typedef struct { 10598 9243 + __u8 *buffer; 10599 + int line; /* track from whence this buffer was allocated */9244 + int line; // track from whence this buffer was allocated 10600 9245 + int maxLine; 10601 9246 +} yaffs_TempBuffer; 10602 9247 + 10603 +/*----------------- Device ---------------------------------*/ 10604 + 10605 +struct yaffs_DeviceStruct { 9248 +//////////////////// Device //////////////////////////////// 9249 + 9250 +struct yaffs_DeviceStruct 9251 +{ 10606 9252 + struct list_head devList; 10607 9253 + const char *name; 10608 9254 + 10609 + /* Entry parameters set up way early. Yaffs sets up the rest.*/ 10610 + int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */ 10611 + int nChunksPerBlock; /* does not need to be a power of 2 */ 10612 + int nBytesPerSpare; /* spare area size */ 10613 + int startBlock; /* Start block we're allowed to use */ 10614 + int endBlock; /* End block we're allowed to use */ 10615 + int nReservedBlocks; /* We want this tuneable so that we can reduce */ 10616 + /* reserved blocks on NOR and RAM. */ 10617 + 10618 + /* Stuff used by the partitioned checkpointing mechanism */ 10619 + int checkpointStartBlock; 10620 + int checkpointEndBlock; 10621 + 10622 + /* Stuff used by the shared space checkpointing mechanism */ 10623 + /* If this value is zero, then this mechanism is disabled */ 10624 + 10625 + int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ 10626 + 10627 + 10628 + 10629 + 10630 + int nShortOpCaches; /* If <= 0, then short op caching is disabled, else 10631 + * the number of short op caches (don't use too many) 10632 + */ 10633 + 10634 + int useHeaderFileSize; /* Flag to determine if we should use file sizes from the header */ 10635 + 10636 + int useNANDECC; /* Flag to decide whether or not to use NANDECC */ 10637 + 10638 + void *genericDevice; /* Pointer to device context 10639 + * On an mtd this holds the mtd pointer. 10640 + */ 10641 + void *superBlock; 10642 + 10643 + /* NAND access functions (Must be set before calling YAFFS)*/ 10644 + 10645 + int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev, 10646 + int chunkInNAND, const __u8 * data, 10647 + const yaffs_Spare * spare); 10648 + int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev, 10649 + int chunkInNAND, __u8 * data, 10650 + yaffs_Spare * spare); 10651 + int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, 10652 + int blockInNAND); 10653 + int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); 9255 + // Entry parameters set up way early. Yaffs sets up the rest. 9256 + int nDataBytesPerChunk; 9257 + int nBytesPerChunk; // Should be a power of 2 >= 512 9258 + int nChunksPerBlock; // does not need to be a power of 2 9259 + int nBytesPerSpare; // spare area size 9260 + int startBlock; // Start block we're allowed to use 9261 + int endBlock; // End block we're allowed to use 9262 + int nReservedBlocks; // We want this tuneable so that we can reduce 9263 + // reserved blocks on NOR and RAM. 9264 + 9265 + int nShortOpCaches; // If <= 0, then short op caching is disabled, else 9266 + // the number of short op caches (don't use too many). 9267 + 9268 + int useHeaderFileSize; // Flag to determine if we should use file sizes from the header 9269 + 9270 + int useNANDECC; // Flag to decide whether or not to use NANDECC 9271 + 9272 + 9273 + void *genericDevice; // Pointer to device context 9274 + // On an mtd this holds the mtd pointer. 9275 + 9276 + // NAND access functions (Must be set before calling YAFFS) 9277 + 9278 + 9279 + int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, const yaffs_Spare *spare); 9280 + int (*readChunkFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare); 9281 + int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND); 9282 + int (*initialiseNAND)(struct yaffs_DeviceStruct *dev); 10654 9283 + 10655 9284 +#ifdef CONFIG_YAFFS_YAFFS2 10656 + int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, 10657 + int chunkInNAND, const __u8 * data, 10658 + const yaffs_ExtendedTags * tags); 10659 + int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev, 10660 + int chunkInNAND, __u8 * data, 10661 + yaffs_ExtendedTags * tags); 10662 + int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo); 10663 + int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo, 10664 + yaffs_BlockState * state, int *sequenceNumber); 9285 + int (*writeChunkWithTagsToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *tags); 9286 + int (*readChunkWithTagsFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags); 9287 + int (*markNANDBlockBad)(struct yaffs_DeviceStruct *dev, int blockNo); 9288 + int (*queryNANDBlock)(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber); 10665 9289 +#endif 10666 9290 + 10667 9291 + int isYaffs2; 10668 + 10669 + /* The removeObjectCallback function must be supplied by OS flavours that 10670 + * need it. The Linux kernel does not use this, but yaffs direct does use 10671 + * it to implement the faster readdir 10672 + */ 10673 + void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj); 10674 + 10675 + /* Callback to mark the superblock dirsty */ 10676 + void (*markSuperBlockDirty)(void * superblock); 10677 + 10678 + int wideTnodesDisabled; /* Set to disable wide tnodes */ 10679 + 10680 + 10681 + /* End of stuff that must be set before initialisation. */ 10682 + 10683 + /* Runtime parameters. Set up by YAFFS. */ 10684 + 10685 + __u16 chunkGroupBits; /* 0 for devices <= 32MB. else log2(nchunks) - 16 */ 10686 + __u16 chunkGroupSize; /* == 2^^chunkGroupBits */ 10687 + 10688 + /* Stuff to support wide tnodes */ 10689 + __u32 tnodeWidth; 10690 + __u32 tnodeMask; 10691 + 10692 + /* Stuff to support various file offses to chunk/offset translations */ 10693 + /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */ 10694 + __u32 crumbMask; 10695 + __u32 crumbShift; 10696 + __u32 crumbsPerChunk; 10697 + 10698 + /* Straight shifting for nDataBytesPerChunk being a power of 2 */ 10699 + __u32 chunkShift; 10700 + __u32 chunkMask; 10701 + 10702 + 9292 + 9293 + // End of stuff that must be set before initialisation. 9294 + 9295 + // Runtime parameters. Set up by YAFFS. 9296 + 9297 + __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16 9298 + __u16 chunkGroupSize; // == 2^^chunkGroupBits 9299 + 10703 9300 +#ifdef __KERNEL__ 10704 9301 + 10705 + struct semaphore sem; /* Semaphore for waiting on erasure.*/ 10706 + struct semaphore grossLock; /* Gross locking semaphore */ 10707 + __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer 10708 + * at compile time so we have to allocate it. 10709 + */ 10710 + void (*putSuperFunc) (struct super_block * sb); 9302 + struct semaphore sem;// Semaphore for waiting on erasure. 9303 + struct semaphore grossLock; // Gross locking semaphore 9304 + __u8 * spareBuffer; // For mtdif2 use. Don't know the size of the buffer at compile time so we have to allocate it. 9305 + void (*putSuperFunc)(struct super_block *sb); 10711 9306 +#endif 10712 9307 + 10713 9308 + int isMounted; 10714 9309 + 10715 + int isCheckpointed; 10716 + 10717 + 10718 + /* Stuff to support block offsetting to support start block zero */ 9310 + // Stuff to support block offsetting to support start block zero 10719 9311 + int internalStartBlock; 10720 9312 + int internalEndBlock; … … 10722 9314 + int chunkOffset; 10723 9315 + 10724 + 10725 + /* Runtime checkpointing stuff */ 10726 + int checkpointPageSequence; /* running sequence number of checkpoint pages */ 10727 + int checkpointByteCount; 10728 + int checkpointByteOffset; 10729 + __u8 *checkpointBuffer; 10730 + int checkpointOpenForWrite; 10731 + int blocksInCheckpoint; 10732 + int checkpointCurrentChunk; 10733 + int checkpointCurrentBlock; 10734 + int checkpointNextBlock; 10735 + int *checkpointBlockList; 10736 + int checkpointMaxBlocks; 10737 + 10738 + /* Block Info */ 9316 + // Block Info 10739 9317 + yaffs_BlockInfo *blockInfo; 10740 + __u8 *chunkBits; /* bitmap of chunks in use */ 10741 + unsigned blockInfoAlt:1; /* was allocated using alternative strategy */ 10742 + unsigned chunkBitsAlt:1; /* was allocated using alternative strategy */ 10743 + int chunkBitmapStride; /* Number of bytes of chunkBits per block. 10744 + * Must be consistent with nChunksPerBlock. 10745 + */ 10746 + 10747 + int nErasedBlocks; 10748 + int allocationBlock; /* Current block being allocated off */ 9318 + __u8 *chunkBits; // bitmap of chunks in use 9319 + int chunkBitmapStride; // Number of bytes of chunkBits per block. 9320 + // Must be consistent with nChunksPerBlock. 9321 + 9322 + 9323 + int nErasedBlocks; 9324 + int allocationBlock; // Current block being allocated off 10749 9325 + __u32 allocationPage; 10750 + int allocationBlockFinder; /* Used to search for next allocation block */10751 + 10752 + / * Runtime state */10753 + int nTnodesCreated;9326 + int allocationBlockFinder; // Used to search for next allocation block 9327 + 9328 + // Runtime state 9329 + int nTnodesCreated; 10754 9330 + yaffs_Tnode *freeTnodes; 10755 + int nFreeTnodes;9331 + int nFreeTnodes; 10756 9332 + yaffs_TnodeList *allocatedTnodeList; 10757 9333 + 10758 + int isDoingGC;10759 + 10760 + int nObjectsCreated;9334 + int isDoingGC; 9335 + 9336 + int nObjectsCreated; 10761 9337 + yaffs_Object *freeObjects; 10762 + int nFreeObjects;9338 + int nFreeObjects; 10763 9339 + 10764 9340 + yaffs_ObjectList *allocatedObjectList; … … 10766 9342 + yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS]; 10767 9343 + 10768 + int nFreeChunks;10769 + 10770 + int currentDirtyChecker; /* Used to find current dirtiest block */10771 + 10772 + __u32 *gcCleanupList; /* objects to delete at the end of a GC. */10773 + 10774 + / * Statistcs */9344 + int nFreeChunks; 9345 + 9346 + int currentDirtyChecker; // Used to find current dirtiest block 9347 + 9348 + __u32 *gcCleanupList; // objects to delete at the end of a GC. 9349 + 9350 + // Operations since mount 10775 9351 + int nPageWrites; 10776 9352 + int nPageReads; … … 10789 9365 + int nUnmarkedDeletions; 10790 9366 + 10791 + int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */10792 +10793 + /* Special directories */10794 9367 + yaffs_Object *rootDir; 10795 9368 + yaffs_Object *lostNFoundDir; 10796 + 10797 + /* Buffer areas for storing data to recover from write failures TODO 10798 + * __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK]; 10799 + * yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK]; 10800 + */ 10801 + 10802 + int bufferedBlock; /* Which block is buffered here? */ 9369 + 9370 + // Buffer areas for storing data to recover from write failures 9371 +// __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK]; 9372 +// yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK]; 9373 + int bufferedBlock; // Which block is buffered here? 10803 9374 + int doingBufferedBlockRewrite; 10804 9375 + … … 10808 9379 + int cacheHits; 10809 9380 + 10810 + /* Stuff for background deletion and unlinked files.*/ 10811 + yaffs_Object *unlinkedDir; /* Directory where unlinked and deleted files live. */ 10812 + yaffs_Object *deletedDir; /* Directory where deleted objects are sent to disappear. */ 10813 + yaffs_Object *unlinkedDeletion; /* Current file being background deleted.*/ 10814 + int nDeletedFiles; /* Count of files awaiting deletion;*/ 10815 + int nUnlinkedFiles; /* Count of unlinked files. */ 10816 + int nBackgroundDeletions; /* Count of background deletions. */ 10817 + 10818 + 9381 + // Stuff for background deletion and unlinked files. 9382 + yaffs_Object *unlinkedDir; // Directory where unlinked and deleted files live. 9383 + yaffs_Object *deletedDir; // Directory where deleted objects are sent to disappear. 9384 + yaffs_Object *unlinkedDeletion; // Current file being background deleted. 9385 + int nDeletedFiles; // Count of files awaiting deletion; 9386 + int nUnlinkedFiles; // Count of unlinked files. 9387 + int nBackgroundDeletions; // Count of background deletions. 9388 + 9389 + //__u8 *localBuffer; 9390 + 10819 9391 + yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS]; 10820 9392 + int maxTemp; 10821 9393 + int unmanagedTempAllocations; 10822 9394 + int unmanagedTempDeallocations; 10823 + 10824 + / * yaffs2 runtime stuff */10825 + unsigned sequenceNumber; /* Sequence number of currently allocating block */9395 + 9396 + // yaffs2 runtime stuff 9397 + unsigned sequenceNumber; //Sequence number of currently allocating block 10826 9398 + unsigned oldestDirtySequence; 10827 + 9399 + 10828 9400 +}; 10829 9401 + 10830 9402 +typedef struct yaffs_DeviceStruct yaffs_Device; 10831 9403 + 10832 +/* The static layout of bllock usage etc is stored in the super block header */ 10833 +typedef struct { 10834 + int StructType; 10835 + int version; 10836 + int checkpointStartBlock; 10837 + int checkpointEndBlock; 10838 + int startBlock; 10839 + int endBlock; 10840 + int rfu[100]; 10841 +} yaffs_SuperBlockHeader; 10842 + 10843 +/* The CheckpointDevice structure holds the device information that changes at runtime and 10844 + * must be preserved over unmount/mount cycles. 10845 + */ 10846 +typedef struct { 10847 + int structType; 10848 + int nErasedBlocks; 10849 + int allocationBlock; /* Current block being allocated off */ 10850 + __u32 allocationPage; 10851 + int nFreeChunks; 10852 + 10853 + int nDeletedFiles; /* Count of files awaiting deletion;*/ 10854 + int nUnlinkedFiles; /* Count of unlinked files. */ 10855 + int nBackgroundDeletions; /* Count of background deletions. */ 10856 + 10857 + /* yaffs2 runtime stuff */ 10858 + unsigned sequenceNumber; /* Sequence number of currently allocating block */ 10859 + unsigned oldestDirtySequence; 10860 + 10861 +} yaffs_CheckpointDevice; 10862 + 10863 + 10864 +typedef struct { 10865 + int structType; 10866 + __u32 magic; 10867 + __u32 version; 10868 + __u32 head; 10869 +} yaffs_CheckpointValidity; 10870 + 10871 +/* Function to manipulate block info */ 10872 +static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) 10873 +{ 10874 + if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { 10875 + T(YAFFS_TRACE_ERROR, 10876 + (TSTR 10877 + ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), 10878 + blk)); 9404 + 9405 +// Function to manipulate block info 9406 +static Y_INLINE yaffs_BlockInfo* yaffs_GetBlockInfo(yaffs_Device *dev, int blk) 9407 +{ 9408 + if(blk < dev->internalStartBlock || blk > dev->internalEndBlock) 9409 + { 9410 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),blk)); 10879 9411 + YBUG(); 10880 9412 + } … … 10882 9414 +} 10883 9415 + 10884 +/*----------------------- YAFFS Functions -----------------------*/ 10885 + 10886 +int yaffs_GutsInitialise(yaffs_Device * dev); 10887 +void yaffs_Deinitialise(yaffs_Device * dev); 10888 + 10889 +int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev); 10890 + 10891 +int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, 10892 + yaffs_Object * newDir, const YCHAR * newName); 10893 + 10894 +int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name); 10895 +int yaffs_DeleteFile(yaffs_Object * obj); 10896 + 10897 +int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize); 10898 +int yaffs_GetObjectFileLength(yaffs_Object * obj); 10899 +int yaffs_GetObjectInode(yaffs_Object * obj); 10900 +unsigned yaffs_GetObjectType(yaffs_Object * obj); 10901 +int yaffs_GetObjectLinkCount(yaffs_Object * obj); 10902 + 10903 +int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr); 10904 +int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr); 10905 + 10906 +/* File operations */ 10907 +int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset, 10908 + int nBytes); 10909 +int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset, 10910 + int nBytes, int writeThrough); 10911 +int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize); 10912 + 10913 +yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, 10914 + __u32 mode, __u32 uid, __u32 gid); 10915 +int yaffs_FlushFile(yaffs_Object * obj, int updateTime); 10916 + 10917 +/* Flushing and checkpointing */ 10918 +void yaffs_FlushEntireDeviceCache(yaffs_Device *dev); 10919 + 10920 +int yaffs_CheckpointSave(yaffs_Device *dev); 10921 +int yaffs_CheckpointRestore(yaffs_Device *dev); 10922 + 10923 +/* Directory operations */ 10924 +yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, 10925 + __u32 mode, __u32 uid, __u32 gid); 10926 +yaffs_Object *yaffs_FindObjectByName(yaffs_Object * theDir, const YCHAR * name); 10927 +int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, 10928 + int (*fn) (yaffs_Object *)); 10929 + 10930 +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number); 10931 + 10932 +/* Link operations */ 10933 +yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name, 10934 + yaffs_Object * equivalentObject); 10935 + 10936 +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj); 10937 + 10938 +/* Symlink operations */ 10939 +yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, 10940 + __u32 mode, __u32 uid, __u32 gid, 10941 + const YCHAR * alias); 10942 +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj); 10943 + 10944 +/* Special inodes (fifos, sockets and devices) */ 10945 +yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name, 10946 + __u32 mode, __u32 uid, __u32 gid, __u32 rdev); 10947 + 10948 +/* Special directories */ 10949 +yaffs_Object *yaffs_Root(yaffs_Device * dev); 10950 +yaffs_Object *yaffs_LostNFound(yaffs_Device * dev); 9416 + 9417 +//////////// YAFFS Functions ////////////////// 9418 + 9419 +int yaffs_GutsInitialise(yaffs_Device *dev); 9420 +void yaffs_Deinitialise(yaffs_Device *dev); 9421 + 9422 +int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev); 9423 + 9424 + 9425 +// Rename 9426 +int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object *newDir, const YCHAR *newName); 9427 + 9428 +// generic Object functions 9429 +int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name); 9430 +int yaffs_DeleteFile(yaffs_Object *obj); 9431 + 9432 +// Object access functions. 9433 +int yaffs_GetObjectName(yaffs_Object *obj,YCHAR *name,int buffSize); 9434 +int yaffs_GetObjectFileLength(yaffs_Object *obj); 9435 +int yaffs_GetObjectInode(yaffs_Object *obj); 9436 +unsigned yaffs_GetObjectType(yaffs_Object *obj); 9437 +int yaffs_GetObjectLinkCount(yaffs_Object *obj); 9438 + 9439 +// Change inode attributes 9440 +int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr); 9441 +int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr); 9442 + 9443 +// File operations 9444 +int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, __u32 offset, int nBytes); 9445 +int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, __u32 offset, int nBytes, int writeThrough); 9446 +int yaffs_ResizeFile(yaffs_Object *obj, int newSize); 9447 + 9448 +yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid); 9449 +int yaffs_FlushFile(yaffs_Object *obj,int updateTime); 9450 + 9451 + 9452 +// Directory operations 9453 +yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid); 9454 +yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir,const YCHAR *name); 9455 +int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *)); 9456 + 9457 +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number); 9458 + 9459 +// Link operations 9460 +yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, yaffs_Object *equivalentObject); 9461 + 9462 +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj); 9463 + 9464 +// Symlink operations 9465 +yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name, __u32 mode, __u32 uid, __u32 gid, const YCHAR *alias); 9466 +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj); 9467 + 9468 +// Special inodes (fifos, sockets and devices) 9469 +yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid,__u32 rdev); 9470 + 9471 + 9472 +// Special directories 9473 +yaffs_Object *yaffs_Root(yaffs_Device *dev); 9474 +yaffs_Object *yaffs_LostNFound(yaffs_Device *dev); 10951 9475 + 10952 9476 +#ifdef CONFIG_YAFFS_WINCE 10953 +/ * CONFIG_YAFFS_WINCE special stuff */10954 +void yfsd_WinFileTimeNow(__u32 target[2]);9477 +// CONFIG_YAFFS_WINCE special stuff 9478 +void yfsd_WinFileTimeNow(__u32 target[2]); 10955 9479 +#endif 10956 9480 + 10957 9481 +#ifdef __KERNEL__ 10958 9482 + 10959 +void yaffs_HandleDeferedFree(yaffs_Object * obj); 10960 +#endif 10961 + 10962 +/* Debug dump */ 10963 +int yaffs_DumpObject(yaffs_Object * obj); 10964 + 10965 +void yaffs_GutsTest(yaffs_Device * dev); 10966 + 10967 +/* A few useful functions */ 10968 +void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); 10969 +void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn); 10970 +int yaffs_CheckFF(__u8 * buffer, int nBytes); 10971 +void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi); 10972 + 10973 +#endif 10974 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffsinterface.h linux-2.6.18.2.patched/fs/yaffs2/yaffsinterface.h 10975 --- linux-2.6.18.2/fs/yaffs2/yaffsinterface.h 1970-01-01 01:00:00.000000000 +0100 10976 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffsinterface.h 2006-11-25 00:15:32.000000000 +0100 10977 @@ -0,0 +1,23 @@ 9483 +void yaffs_HandleDeferedFree(yaffs_Object *obj); 9484 +#endif 9485 + 9486 + 9487 + 9488 + 9489 +// Debug dump 9490 +int yaffs_DumpObject(yaffs_Object *obj); 9491 + 9492 + 9493 +void yaffs_GutsTest(yaffs_Device *dev); 9494 + 9495 + 9496 +void yaffs_InitialiseTags(yaffs_ExtendedTags *tags); 9497 +void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND,int lyn); 9498 +int yaffs_CheckFF(__u8 *buffer,int nBytes); 9499 + 9500 +#endif 9501 + 9502 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h 9503 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h 1970-01-01 01:00:00.000000000 +0100 9504 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h 2006-12-10 03:57:50.000000000 +0100 9505 @@ -0,0 +1,25 @@ 10978 9506 +/* 10979 9507 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 10992 9520 + * 10993 9521 + */ 10994 + 9522 + 10995 9523 +#ifndef __YAFFSINTERFACE_H__ 10996 9524 +#define __YAFFSINTERFACE_H__ 10997 9525 + 9526 + 10998 9527 +int yaffs_Initialise(unsigned nBlocks); 10999 9528 + 11000 9529 +#endif 11001 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.c 11002 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.c 1970-01-01 01:00:00.000000000 +0100 11003 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.c 2006-11-25 00:15:31.000000000 +0100 11004 @@ -0,0 +1,234 @@ 9530 + 9531 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c 9532 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c 1970-01-01 01:00:00.000000000 +0100 9533 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c 2006-12-10 04:26:05.000000000 +0100 9534 @@ -0,0 +1,211 @@ 11005 9535 +/* 11006 9536 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 11018 9548 + */ 11019 9549 + 11020 +/* mtd interface for YAFFS2 */ 11021 + 11022 +const char *yaffs_mtdif2_c_version = 11023 + "$Id: yaffs_mtdif2.c,v 1.15 2006/11/08 06:24:34 charles Exp $"; 11024 + 9550 +// mtd interface for YAFFS2 9551 + 9552 +const char *yaffs_mtdif2_c_version = "$Id: yaffs_mtdif2.c,v 1.6 2005/08/01 20:52:35 luc Exp $"; 9553 + 11025 9554 +#include "yportenv.h" 11026 9555 + 9556 +#ifdef CONFIG_YAFFS_YAFFS2 11027 9557 + 11028 9558 +#include "yaffs_mtdif2.h" … … 11034 9564 +#include "yaffs_packedtags2.h" 11035 9565 + 11036 +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, 11037 + const __u8 * data, 11038 + const yaffs_ExtendedTags * tags) 9566 + 9567 + 9568 + 9569 +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags) 11039 9570 +{ 11040 9571 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 11041 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))11042 9572 + struct mtd_oob_ops ops; 11043 +#else11044 9573 + size_t dummy; 11045 +#endif11046 9574 + int retval = 0; 11047 9575 + 11048 + loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; 9576 + 9577 + loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk; 11049 9578 + 11050 9579 + yaffs_PackedTags2 pt; 11051 + 11052 + T(YAFFS_TRACE_MTD, 11053 + (TSTR 11054 + ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" 11055 + TENDSTR), chunkInNAND, data, tags)); 9580 + 9581 + T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR),chunkInNAND,data,tags)); 11056 9582 + 11057 9583 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) … … 11072 9598 + BUG(); /* both tags and data should always be present */ 11073 9599 +#else 11074 + if (tags) {11075 + yaffs_PackTags2(&pt, tags);11076 + }11077 + 11078 + if (data && tags) {11079 + if (dev->useNANDECC)11080 + retval =11081 + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,11082 + &dummy, data, (__u8 *) & pt,NULL);9600 + if(tags) 9601 + { 9602 + yaffs_PackTags2(&pt,tags); 9603 + } 9604 + 9605 + if(data && tags) 9606 + { 9607 + if(dev->useNANDECC) 9608 + retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,(__u8 *)&pt,NULL); 11083 9609 + else 11084 + retval = 11085 + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, 11086 + &dummy, data, (__u8 *) & pt, NULL); 11087 + } else { 11088 + if (data) 11089 + retval = 11090 + mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, 11091 + data); 11092 + if (tags) 11093 + retval = 11094 + mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, 11095 + (__u8 *) & pt); 11096 + 11097 + } 11098 +#endif 11099 + 11100 + if (retval == 0) 11101 + return YAFFS_OK; 9610 + retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,(__u8 *)&pt,NULL); 9611 + } 11102 9612 + else 11103 + return YAFFS_FAIL; 11104 +} 11105 + 11106 +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, 11107 + __u8 * data, yaffs_ExtendedTags * tags) 9613 + { 9614 + if(data) 9615 + retval = mtd->write(mtd,addr,dev->nBytesPerChunk,&dummy,data); 9616 + if(tags) 9617 + retval = mtd->write_oob(mtd,addr,mtd->oobsize,&dummy,(__u8 *)&pt); 9618 + 9619 + } 9620 + 9621 +#endif 9622 + if (retval == 0) 9623 + return YAFFS_OK; 9624 + else 9625 + return YAFFS_FAIL; 9626 +} 9627 + 9628 +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) 11108 9629 +{ 11109 9630 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 11110 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))11111 9631 + struct mtd_oob_ops ops; 11112 +#endif11113 9632 + size_t dummy; 11114 + int retval = 0; 11115 + 11116 + loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; 11117 + 9633 + int retval = 0; 9634 + 9635 + 9636 + loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk; 9637 + 11118 9638 + yaffs_PackedTags2 pt; 11119 9639 + 11120 + T(YAFFS_TRACE_MTD, 11121 + (TSTR 11122 + ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" 11123 + TENDSTR), chunkInNAND, data, tags)); 9640 + T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR),chunkInNAND,data,tags)); 11124 9641 + 11125 9642 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) … … 11137 9654 + } 11138 9655 +#else 11139 + if (data && tags) { 11140 + if (dev->useNANDECC) { 11141 + retval = 11142 + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, 11143 + &dummy, data, dev->spareBuffer, 11144 + NULL); 11145 + } else { 11146 + retval = 11147 + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, 11148 + &dummy, data, dev->spareBuffer, 11149 + NULL); 11150 + } 11151 + } else { 11152 + if (data) 11153 + retval = 11154 + mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy, 11155 + data); 11156 + if (tags) 11157 + retval = 11158 + mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, 11159 + dev->spareBuffer); 11160 + } 11161 +#endif 11162 + 11163 + memcpy(&pt, dev->spareBuffer, sizeof(pt)); 11164 + 11165 + if (tags) 11166 + yaffs_UnpackTags2(tags, &pt); 11167 + 11168 + if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) 11169 + tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; 11170 + 11171 + if (retval == 0) 11172 + return YAFFS_OK; 9656 + if(data && tags) 9657 + { 9658 + if(dev->useNANDECC) 9659 + { 9660 + retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,dev->spareBuffer,NULL); 9661 + } 9662 + else 9663 + { 9664 + retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,dev->spareBuffer,NULL); 9665 + } 9666 + memcpy(&pt,dev->spareBuffer,sizeof(pt)); 9667 + } 11173 9668 + else 11174 + return YAFFS_FAIL; 9669 + { 9670 + if(data) 9671 + retval = mtd->read(mtd,addr,dev->nBytesPerChunk,&dummy,data); 9672 + if(tags) { 9673 + retval = mtd->read_oob(mtd,addr,mtd->oobsize,&dummy,dev->spareBuffer); 9674 + memcpy(&pt, mtd->oobinfo.oobfree[0][0] + (char *)dev->spareBuffer, sizeof(pt)); 9675 + } 9676 + } 9677 + 9678 + if(tags) 9679 + yaffs_UnpackTags2(tags,&pt); 9680 +#endif 9681 + if (retval == 0) 9682 + return YAFFS_OK; 9683 + else 9684 + return YAFFS_FAIL; 11175 9685 +} 11176 9686 + … … 11179 9689 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 11180 9690 + int retval; 11181 + T(YAFFS_TRACE_MTD, 11182 + (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo)); 11183 + 11184 + retval = 11185 + mtd->block_markbad(mtd, 11186 + blockNo * dev->nChunksPerBlock * 11187 + dev->nDataBytesPerChunk); 11188 + 11189 + if (retval == 0) 11190 + return YAFFS_OK; 11191 + else 11192 + return YAFFS_FAIL; 11193 + 11194 +} 11195 + 11196 +int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, 11197 + yaffs_BlockState * state, int *sequenceNumber) 9691 + T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR),blockNo)); 9692 + 9693 + 9694 + retval = mtd->block_markbad(mtd,blockNo * dev->nChunksPerBlock * dev->nBytesPerChunk); 9695 + 9696 + if (retval == 0) 9697 + return YAFFS_OK; 9698 + else 9699 + return YAFFS_FAIL; 9700 + 9701 +} 9702 + 9703 +int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) 11198 9704 +{ 11199 9705 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 11200 9706 + int retval; 11201 + 11202 + T(YAFFS_TRACE_MTD, 11203 + (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo)); 11204 + retval = 11205 + mtd->block_isbad(mtd, 11206 + blockNo * dev->nChunksPerBlock * 11207 + dev->nDataBytesPerChunk); 11208 + 11209 + if (retval) { 11210 + T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); 11211 + 9707 + 9708 + T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR),blockNo)); 9709 + retval = mtd->block_isbad(mtd,blockNo* dev->nChunksPerBlock * dev->nBytesPerChunk); 9710 + 9711 + if(retval) 9712 + { 9713 + T(YAFFS_TRACE_MTD,(TSTR("block is bad" TENDSTR))); 9714 + 11212 9715 + *state = YAFFS_BLOCK_STATE_DEAD; 11213 9716 + *sequenceNumber = 0; 11214 + } else { 9717 + } 9718 + else 9719 + { 11215 9720 + yaffs_ExtendedTags t; 11216 + nandmtd2_ReadChunkWithTagsFromNAND(dev, 11217 + blockNo * 11218 + dev->nChunksPerBlock, NULL, 11219 + &t); 11220 + 11221 + if (t.chunkUsed) { 11222 + *sequenceNumber = t.sequenceNumber; 11223 + *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; 11224 + } else { 11225 + *sequenceNumber = 0; 11226 + *state = YAFFS_BLOCK_STATE_EMPTY; 11227 + } 11228 + } 11229 + T(YAFFS_TRACE_MTD, 11230 + (TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber, 11231 + *state)); 11232 + 11233 + if (retval == 0) 11234 + return YAFFS_OK; 11235 + else 11236 + return YAFFS_FAIL; 11237 +} 11238 + 11239 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.h 11240 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.h 1970-01-01 01:00:00.000000000 +0100 11241 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.h 2006-11-25 00:15:32.000000000 +0100 11242 @@ -0,0 +1,29 @@ 9721 + nandmtd2_ReadChunkWithTagsFromNAND(dev,blockNo * dev->nChunksPerBlock,NULL, &t); 9722 + 9723 + if(t.chunkUsed) 9724 + { 9725 + *sequenceNumber = t.sequenceNumber; 9726 + *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; 9727 + } 9728 + else 9729 + { 9730 + *sequenceNumber = 0; 9731 + *state = YAFFS_BLOCK_STATE_EMPTY; 9732 + } 9733 + } 9734 + T(YAFFS_TRACE_MTD,(TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,*state)); 9735 + 9736 + if (retval == 0) 9737 + return YAFFS_OK; 9738 + else 9739 + return YAFFS_FAIL; 9740 +} 9741 + 9742 +#endif 9743 + 9744 + 9745 + 9746 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h 9747 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h 1970-01-01 01:00:00.000000000 +0100 9748 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h 2006-12-10 03:57:50.000000000 +0100 9749 @@ -0,0 +1,27 @@ 11243 9750 +/* 11244 9751 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 11256 9763 + */ 11257 9764 + 9765 + 11258 9766 +#ifndef __YAFFS_MTDIF2_H__ 11259 9767 +#define __YAFFS_MTDIF2_H__ 11260 9768 + 9769 + 11261 9770 +#include "yaffs_guts.h" 11262 +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, 11263 + const __u8 * data, 11264 + const yaffs_ExtendedTags * tags); 11265 +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, 11266 + __u8 * data, yaffs_ExtendedTags * tags); 9771 +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags); 9772 +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags); 11267 9773 +int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); 11268 +int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, 11269 + yaffs_BlockState * state, int *sequenceNumber); 11270 + 11271 +#endif 11272 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.c 11273 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.c 1970-01-01 01:00:00.000000000 +0100 11274 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.c 2006-11-25 00:15:31.000000000 +0100 11275 @@ -0,0 +1,241 @@ 9774 +int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber); 9775 + 9776 +#endif 9777 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c 9778 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c 1970-01-01 01:00:00.000000000 +0100 9779 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c 2006-12-10 04:19:40.000000000 +0100 9780 @@ -0,0 +1,228 @@ 11276 9781 +/* 11277 9782 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 11289 9794 + */ 11290 9795 + 11291 +const char *yaffs_mtdif_c_version = 11292 + "$Id: yaffs_mtdif.c,v 1.16 2006/11/08 06:24:34 charles Exp $"; 11293 + 9796 +const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.7 2005/08/01 20:52:35 luc Exp $"; 9797 + 11294 9798 +#include "yportenv.h" 11295 9799 + 9800 +#ifdef CONFIG_YAFFS_YAFFS1 11296 9801 + 11297 9802 +#include "yaffs_mtdif.h" … … 11302 9807 +#include "linux/mtd/nand.h" 11303 9808 + 11304 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))11305 9809 +static struct nand_oobinfo yaffs_oobinfo = { 11306 9810 + .useecc = 1, … … 11308 9812 + .eccpos = {8, 9, 10, 13, 14, 15} 11309 9813 +}; 11310 + 9814 +static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob) 9815 +{ 9816 + oob[0] = spare->tagByte0; 9817 + oob[1] = spare->tagByte1; 9818 + oob[2] = spare->tagByte2; 9819 + oob[3] = spare->tagByte3; 9820 + oob[4] = spare->tagByte4; 9821 + oob[5] = spare->tagByte5 & 0x3f; 9822 + oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80; 9823 + oob[5] |= spare->pageStatus == 0 ? 0: 0x40; 9824 + oob[6] = spare->tagByte6; 9825 + oob[7] = spare->tagByte7; 9826 +} 9827 + 9828 +static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob) 9829 +{ 9830 + struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare; 9831 + spare->tagByte0 = oob[0]; 9832 + spare->tagByte1 = oob[1]; 9833 + spare->tagByte2 = oob[2]; 9834 + spare->tagByte3 = oob[3]; 9835 + spare->tagByte4 = oob[4]; 9836 + spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f; 9837 + spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y'; 9838 + spare->pageStatus = oob[5] & 0x40 ? 0xff : 0; 9839 + spare->tagByte6 = oob[6]; 9840 + spare->tagByte7 = oob[7]; 9841 + 9842 + nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */ 9843 +} 11311 9844 +static struct nand_oobinfo yaffs_noeccinfo = { 11312 9845 + .useecc = 0, 11313 9846 +}; 11314 +#endif 11315 + 9847 + 9848 + 9849 +int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare) 9850 +{ 9851 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 9852 + struct mtd_oob_ops ops; 9853 + size_t dummy; 9854 + int retval = 0; 9855 + 9856 + loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk; 9857 + 11316 9858 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 11317 +static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob) 11318 +{ 11319 + oob[0] = spare->tagByte0; 11320 + oob[1] = spare->tagByte1; 11321 + oob[2] = spare->tagByte2; 11322 + oob[3] = spare->tagByte3; 11323 + oob[4] = spare->tagByte4; 11324 + oob[5] = spare->tagByte5 & 0x3f; 11325 + oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80; 11326 + oob[5] |= spare->pageStatus == 0 ? 0: 0x40; 11327 + oob[6] = spare->tagByte6; 11328 + oob[7] = spare->tagByte7; 11329 +} 11330 + 11331 +static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob) 11332 +{ 11333 + struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare; 11334 + spare->tagByte0 = oob[0]; 11335 + spare->tagByte1 = oob[1]; 11336 + spare->tagByte2 = oob[2]; 11337 + spare->tagByte3 = oob[3]; 11338 + spare->tagByte4 = oob[4]; 11339 + spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f; 11340 + spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y'; 11341 + spare->pageStatus = oob[5] & 0x40 ? 0xff : 0; 11342 + spare->tagByte6 = oob[6]; 11343 + spare->tagByte7 = oob[7]; 11344 + 11345 + nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */ 11346 +} 11347 +#endif 11348 + 11349 +int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, 11350 + const __u8 * data, const yaffs_Spare * spare) 9859 + __u8 spareAsBytes[8]; /* OOB */ 9860 + 9861 + if (data && !spare) 9862 + retval = mtd->write(mtd, addr, dev->nDataBytesPerChunk, 9863 + &dummy, data); 9864 + else if (spare) { 9865 + if (dev->useNANDECC) { 9866 + translate_spare2oob(spare, spareAsBytes); 9867 + ops.mode = MTD_OOB_AUTO; 9868 + ops.ooblen = 8; /* temp hack */ 9869 + } else { 9870 + ops.mode = MTD_OOB_RAW; 9871 + ops.ooblen = YAFFS_BYTES_PER_SPARE; 9872 + } 9873 + ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen; 9874 + ops.datbuf = (u8 *)data; 9875 + ops.ooboffs = 0; 9876 + ops.oobbuf = spareAsBytes; 9877 + retval = mtd->write_oob(mtd, addr, &ops); 9878 + } 9879 +#else 9880 + __u8 *spareAsBytes = (__u8 *)spare; 9881 + 9882 + if(data && spare) 9883 + { 9884 + if(dev->useNANDECC) 9885 + retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_oobinfo); 9886 + else 9887 + retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_noeccinfo); 9888 + } 9889 + else 9890 + { 9891 + if(data) 9892 + retval = mtd->write(mtd,addr,dev->nBytesPerChunk,&dummy,data); 9893 + if(spare) 9894 + retval = mtd->write_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes); 9895 + } 9896 +#endif 9897 + if (retval == 0) 9898 + return YAFFS_OK; 9899 + else 9900 + return YAFFS_FAIL; 9901 +} 9902 + 9903 +int nandmtd_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare) 11351 9904 +{ 11352 9905 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 9906 + struct mtd_oob_ops ops; 9907 + size_t dummy; 9908 + int retval = 0; 9909 + 9910 + loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk; 11353 9911 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 11354 + struct mtd_oob_ops ops; 11355 +#endif 11356 + size_t dummy; 11357 + int retval = 0; 11358 + 11359 + loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; 11360 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 11361 + __u8 spareAsBytes[8]; /* OOB */ 11362 + 11363 + if (data && !spare) 11364 + retval = mtd->write(mtd, addr, dev->nDataBytesPerChunk, 11365 + &dummy, data); 11366 + else if (spare) { 11367 + if (dev->useNANDECC) { 11368 + translate_spare2oob(spare, spareAsBytes); 11369 + ops.mode = MTD_OOB_AUTO; 11370 + ops.ooblen = 8; /* temp hack */ 11371 + } else { 11372 + ops.mode = MTD_OOB_RAW; 11373 + ops.ooblen = YAFFS_BYTES_PER_SPARE; 11374 + } 11375 + ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen; 11376 + ops.datbuf = (u8 *)data; 11377 + ops.ooboffs = 0; 11378 + ops.oobbuf = spareAsBytes; 11379 + retval = mtd->write_oob(mtd, addr, &ops); 11380 + } 11381 +#else 11382 + __u8 *spareAsBytes = (__u8 *) spare; 11383 + 11384 + if (data && spare) { 11385 + if (dev->useNANDECC) 11386 + retval = 11387 + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, 11388 + &dummy, data, spareAsBytes, 11389 + &yaffs_oobinfo); 9912 + __u8 spareAsBytes[8]; /* OOB */ 9913 + 9914 + if (data && !spare) 9915 + retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk, 9916 + &dummy, data); 9917 + else if (spare) { 9918 + if (dev->useNANDECC) { 9919 + ops.mode = MTD_OOB_AUTO; 9920 + ops.ooblen = 8; /* temp hack */ 9921 + } else { 9922 + ops.mode = MTD_OOB_RAW; 9923 + ops.ooblen = YAFFS_BYTES_PER_SPARE; 9924 + } 9925 + ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen; 9926 + ops.datbuf = data; 9927 + ops.ooboffs = 0; 9928 + ops.oobbuf = spareAsBytes; 9929 + retval = mtd->read_oob(mtd, addr, &ops); 9930 + if (dev->useNANDECC) 9931 + translate_oob2spare(spare, spareAsBytes); 9932 + } 9933 +#else 9934 + __u8 *spareAsBytes = (__u8 *)spare; 9935 + 9936 + if(data && spare) 9937 + { 9938 + if(dev->useNANDECC) 9939 + { // Careful, this call adds 2 ints to the end of the spare data. Calling function should 9940 + // allocate enough memory for spare, i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. 9941 + retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_oobinfo); 9942 + } 11390 9943 + else 11391 + retval = 11392 + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, 11393 + &dummy, data, spareAsBytes, 11394 + &yaffs_noeccinfo); 11395 + } else { 11396 + if (data) 11397 + retval = 11398 + mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, 11399 + data); 11400 + if (spare) 11401 + retval = 11402 + mtd->write_oob(mtd, addr, YAFFS_BYTES_PER_SPARE, 11403 + &dummy, spareAsBytes); 11404 + } 11405 +#endif 11406 + 11407 + if (retval == 0) 11408 + return YAFFS_OK; 9944 + { 9945 + retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_noeccinfo); 9946 + } 9947 + } 11409 9948 + else 11410 + return YAFFS_FAIL; 11411 +} 11412 + 11413 +int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, 11414 + yaffs_Spare * spare) 9949 + { 9950 + if(data) 9951 + retval = mtd->read(mtd,addr,dev->nBytesPerChunk,&dummy,data); 9952 + if(spare) 9953 + retval = mtd->read_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes); 9954 + } 9955 +#endif 9956 + if (retval == 0) 9957 + return YAFFS_OK; 9958 + else 9959 + return YAFFS_FAIL; 9960 +} 9961 + 9962 +// Callback not needed for NAND 9963 +#if 0 9964 +static void nandmtd_EraseCallback(struct erase_info *ei) 9965 +{ 9966 + yaffs_Device *dev = (yaffs_Device *)ei->priv; 9967 + up(&dev->sem); 9968 +} 9969 +#endif 9970 + 9971 + 9972 +int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) 11415 9973 +{ 11416 9974 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 11417 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 11418 + struct mtd_oob_ops ops; 11419 +#endif 11420 + size_t dummy; 11421 + int retval = 0; 11422 + 11423 + loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; 11424 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) 11425 + __u8 spareAsBytes[8]; /* OOB */ 11426 + 11427 + if (data && !spare) 11428 + retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk, 11429 + &dummy, data); 11430 + else if (spare) { 11431 + if (dev->useNANDECC) { 11432 + ops.mode = MTD_OOB_AUTO; 11433 + ops.ooblen = 8; /* temp hack */ 11434 + } else { 11435 + ops.mode = MTD_OOB_RAW; 11436 + ops.ooblen = YAFFS_BYTES_PER_SPARE; 11437 + } 11438 + ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen; 11439 + ops.datbuf = data; 11440 + ops.ooboffs = 0; 11441 + ops.oobbuf = spareAsBytes; 11442 + retval = mtd->read_oob(mtd, addr, &ops); 11443 + if (dev->useNANDECC) 11444 + translate_oob2spare(spare, spareAsBytes); 11445 + } 11446 +#else 11447 + __u8 *spareAsBytes = (__u8 *) spare; 11448 + 11449 + if (data && spare) { 11450 + if (dev->useNANDECC) { 11451 + /* Careful, this call adds 2 ints */ 11452 + /* to the end of the spare data. Calling function */ 11453 + /* should allocate enough memory for spare, */ 11454 + /* i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. */ 11455 + retval = 11456 + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, 11457 + &dummy, data, spareAsBytes, 11458 + &yaffs_oobinfo); 11459 + } else { 11460 + retval = 11461 + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, 11462 + &dummy, data, spareAsBytes, 11463 + &yaffs_noeccinfo); 11464 + } 11465 + } else { 11466 + if (data) 11467 + retval = 11468 + mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy, 11469 + data); 11470 + if (spare) 11471 + retval = 11472 + mtd->read_oob(mtd, addr, YAFFS_BYTES_PER_SPARE, 11473 + &dummy, spareAsBytes); 11474 + } 11475 +#endif 11476 + 11477 + if (retval == 0) 11478 + return YAFFS_OK; 11479 + else 11480 + return YAFFS_FAIL; 11481 +} 11482 + 11483 +int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber) 11484 +{ 11485 + struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); 11486 + __u32 addr = 11487 + ((loff_t) blockNumber) * dev->nDataBytesPerChunk 11488 + * dev->nChunksPerBlock; 9975 + __u32 addr = ((loff_t) blockNumber) * dev->nBytesPerChunk * dev->nChunksPerBlock; 11489 9976 + struct erase_info ei; 11490 + int retval = 0;11491 + 9977 + int retval = 0; 9978 + 11492 9979 + ei.mtd = mtd; 11493 9980 + ei.addr = addr; 11494 + ei.len = dev->n DataBytesPerChunk * dev->nChunksPerBlock;9981 + ei.len = dev->nBytesPerChunk * dev->nChunksPerBlock; 11495 9982 + ei.time = 1000; 11496 9983 + ei.retries = 2; 11497 9984 + ei.callback = NULL; 11498 + ei.priv = (u_long) dev; 11499 + 11500 + /* Todo finish off the ei if required */ 11501 + 11502 + sema_init(&dev->sem, 0); 11503 + 11504 + retval = mtd->erase(mtd, &ei); 11505 + 11506 + if (retval == 0) 11507 + return YAFFS_OK; 11508 + else 11509 + return YAFFS_FAIL; 11510 +} 11511 + 11512 +int nandmtd_InitialiseNAND(yaffs_Device * dev) 9985 + ei.priv = (u_long)dev; 9986 + 9987 + // Todo finish off the ei if required 9988 + 9989 + sema_init(&dev->sem,0); 9990 + 9991 + retval = mtd->erase(mtd,&ei); 9992 + 9993 + //No need for callback 9994 + // down(&dev->sem); // Wait for the erasure to complete 9995 + 9996 + if (retval == 0) 9997 + return YAFFS_OK; 9998 + else 9999 + return YAFFS_FAIL; 10000 +} 10001 + 10002 +int nandmtd_InitialiseNAND(yaffs_Device *dev) 11513 10003 +{ 11514 10004 + return YAFFS_OK; 11515 10005 +} 11516 10006 + 11517 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.h 11518 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.h 1970-01-01 01:00:00.000000000 +0100 11519 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.h 2006-11-25 00:15:32.000000000 +0100 11520 @@ -0,0 +1,31 @@ 10007 +#endif // CONFIG_YAFFS_YAFFS1 10008 + 10009 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h 10010 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h 1970-01-01 01:00:00.000000000 +0100 10011 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h 2006-12-10 03:57:50.000000000 +0100 10012 @@ -0,0 +1,33 @@ 11521 10013 +/* 11522 10014 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 11535 10027 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. 11536 10028 + * 11537 + * $Id: yaffs_mtdif.h,v 1. 3 2005/08/11 01:07:43 martyExp $10029 + * $Id: yaffs_mtdif.h,v 1.2 2005/07/19 20:41:59 charles Exp $ 11538 10030 + */ 11539 10031 + … … 11543 10035 +#include "yaffs_guts.h" 11544 10036 + 11545 +int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, 11546 + const __u8 * data, const yaffs_Spare * spare); 11547 +int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, 11548 + yaffs_Spare * spare); 11549 +int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber); 11550 +int nandmtd_InitialiseNAND(yaffs_Device * dev); 11551 +#endif 11552 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_nand.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.c 11553 --- linux-2.6.18.2/fs/yaffs2/yaffs_nand.c 1970-01-01 01:00:00.000000000 +0100 11554 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.c 2006-11-25 00:15:31.000000000 +0100 11555 @@ -0,0 +1,135 @@ 11556 +/* 11557 + * YAFFS: Yet another FFS. A NAND-flash specific file system. 11558 + * 11559 + * Copyright (C) 2002 Aleph One Ltd. 11560 + * for Toby Churchill Ltd and Brightstar Engineering 11561 + * 11562 + * Created by Charles Manning <charles@aleph1.co.uk> 11563 + * 11564 + * This program is free software; you can redistribute it and/or modify 11565 + * it under the terms of the GNU General Public License version 2 as 11566 + * published by the Free Software Foundation. 11567 + * 11568 + */ 11569 + 11570 +const char *yaffs_nand_c_version = 11571 + "$Id: yaffs_nand.c,v 1.5 2006/11/08 09:52:12 charles Exp $"; 11572 + 11573 +#include "yaffs_nand.h" 11574 +#include "yaffs_tagscompat.h" 11575 +#include "yaffs_tagsvalidity.h" 11576 + 11577 + 11578 +int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, 11579 + __u8 * buffer, 11580 + yaffs_ExtendedTags * tags) 11581 +{ 11582 + int result; 11583 + yaffs_ExtendedTags localTags; 11584 + 11585 + int realignedChunkInNAND = chunkInNAND - dev->chunkOffset; 11586 + 11587 + /* If there are no tags provided, use local tags to get prioritised gc working */ 11588 + if(!tags) 11589 + tags = &localTags; 11590 + 11591 + if (dev->readChunkWithTagsFromNAND) 11592 + result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer, 11593 + tags); 11594 + else 11595 + result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev, 11596 + realignedChunkInNAND, 11597 + buffer, 11598 + tags); 11599 + if(tags && 11600 + tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ 11601 + 11602 + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock); 11603 + yaffs_HandleChunkError(dev,bi); 11604 + } 11605 + 11606 + return result; 11607 +} 11608 + 11609 +int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, 11610 + int chunkInNAND, 11611 + const __u8 * buffer, 11612 + yaffs_ExtendedTags * tags) 11613 +{ 11614 + chunkInNAND -= dev->chunkOffset; 11615 + 11616 + 11617 + if (tags) { 11618 + tags->sequenceNumber = dev->sequenceNumber; 11619 + tags->chunkUsed = 1; 11620 + if (!yaffs_ValidateTags(tags)) { 11621 + T(YAFFS_TRACE_ERROR, 11622 + (TSTR("Writing uninitialised tags" TENDSTR))); 11623 + YBUG(); 11624 + } 11625 + T(YAFFS_TRACE_WRITE, 11626 + (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND, 11627 + tags->objectId, tags->chunkId)); 11628 + } else { 11629 + T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR))); 11630 + YBUG(); 11631 + } 11632 + 11633 + if (dev->writeChunkWithTagsToNAND) 11634 + return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer, 11635 + tags); 11636 + else 11637 + return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev, 11638 + chunkInNAND, 11639 + buffer, 11640 + tags); 11641 +} 11642 + 11643 +int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo) 11644 +{ 11645 + blockNo -= dev->blockOffset; 11646 + 11647 +; 11648 + if (dev->markNANDBlockBad) 11649 + return dev->markNANDBlockBad(dev, blockNo); 11650 + else 11651 + return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo); 11652 +} 11653 + 11654 +int yaffs_QueryInitialBlockState(yaffs_Device * dev, 11655 + int blockNo, 11656 + yaffs_BlockState * state, 11657 + unsigned *sequenceNumber) 11658 +{ 11659 + blockNo -= dev->blockOffset; 11660 + 11661 + if (dev->queryNANDBlock) 11662 + return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber); 11663 + else 11664 + return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo, 11665 + state, 11666 + sequenceNumber); 11667 +} 11668 + 11669 + 11670 +int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, 11671 + int blockInNAND) 11672 +{ 11673 + int result; 11674 + 11675 + blockInNAND -= dev->blockOffset; 11676 + 11677 + 11678 + dev->nBlockErasures++; 11679 + result = dev->eraseBlockInNAND(dev, blockInNAND); 11680 + 11681 + return result; 11682 +} 11683 + 11684 +int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev) 11685 +{ 11686 + return dev->initialiseNAND(dev); 11687 +} 11688 + 11689 + 11690 + 11691 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_nandemul2k.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_nandemul2k.h 11692 --- linux-2.6.18.2/fs/yaffs2/yaffs_nandemul2k.h 1970-01-01 01:00:00.000000000 +0100 11693 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_nandemul2k.h 2006-11-25 00:15:32.000000000 +0100 11694 @@ -0,0 +1,42 @@ 10037 +int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare); 10038 +int nandmtd_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare); 10039 +int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); 10040 +int nandmtd_InitialiseNAND(yaffs_Device *dev); 10041 +#endif 10042 + 10043 + 10044 + 10045 + 10046 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h 10047 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h 1970-01-01 01:00:00.000000000 +0100 10048 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h 2006-12-10 03:57:50.000000000 +0100 10049 @@ -0,0 +1,38 @@ 11695 10050 +/* 11696 10051 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 11710 10065 + * yaffs_nandemul2k.h: Interface to emulated NAND functions (2k page size) 11711 10066 + * 11712 + * $Id: yaffs_nandemul2k.h,v 1. 2 2005/08/11 02:37:49 martyExp $10067 + * $Id: yaffs_nandemul2k.h,v 1.1 2004/12/17 04:39:04 charles Exp $ 11713 10068 + */ 11714 + 10069 + 11715 10070 +#ifndef __YAFFS_NANDEMUL2K_H__ 11716 10071 +#define __YAFFS_NANDEMUL2K_H__ 11717 10072 + 11718 +#include "yaffs_guts.h" 11719 + 11720 +int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, 11721 + int chunkInNAND, const __u8 * data, 11722 + yaffs_ExtendedTags * tags); 11723 +int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev, 11724 + int chunkInNAND, __u8 * data, 11725 + yaffs_ExtendedTags * tags); 10073 +#include "yaffs_guts.h" 10074 + 10075 + 10076 +int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_ExtendedTags *tags); 10077 +int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags); 11726 10078 +int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); 11727 +int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, 11728 + yaffs_BlockState * state, int *sequenceNumber); 11729 +int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, 11730 + int blockInNAND); 10079 +int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber); 10080 +int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND); 11731 10081 +int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev); 11732 10082 +int nandemul2k_GetBytesPerChunk(void); … … 11735 10085 + 11736 10086 +#endif 11737 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_nand.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.h 11738 --- linux-2.6.18.2/fs/yaffs2/yaffs_nand.h 1970-01-01 01:00:00.000000000 +0100 11739 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.h 2006-11-25 00:15:32.000000000 +0100 11740 @@ -0,0 +1,43 @@ 11741 +/* 11742 + * YAFFS: Yet another FFS. A NAND-flash specific file system. 11743 + * 11744 + * Copyright (C) 2002 Aleph One Ltd. 11745 + * for Toby Churchill Ltd and Brightstar Engineering 11746 + * 11747 + * Created by Charles Manning <charles@aleph1.co.uk> 11748 + * 11749 + * This program is free software; you can redistribute it and/or modify 11750 + * it under the terms of the GNU General Public License version 2 as 11751 + * published by the Free Software Foundation. 11752 + * 11753 + */ 11754 + 11755 +#ifndef __YAFFS_NAND_H__ 11756 +#define __YAFFS_NAND_H__ 11757 +#include "yaffs_guts.h" 11758 + 11759 + 11760 + 11761 +int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, 11762 + __u8 * buffer, 11763 + yaffs_ExtendedTags * tags); 11764 + 11765 +int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, 11766 + int chunkInNAND, 11767 + const __u8 * buffer, 11768 + yaffs_ExtendedTags * tags); 11769 + 11770 +int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo); 11771 + 11772 +int yaffs_QueryInitialBlockState(yaffs_Device * dev, 11773 + int blockNo, 11774 + yaffs_BlockState * state, 11775 + unsigned *sequenceNumber); 11776 + 11777 +int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, 11778 + int blockInNAND); 11779 + 11780 +int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev); 11781 + 11782 +#endif 11783 + 11784 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.c 11785 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.c 1970-01-01 01:00:00.000000000 +0100 11786 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.c 2006-11-25 00:15:32.000000000 +0100 11787 @@ -0,0 +1,39 @@ 10087 + 10088 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c 10089 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c 1970-01-01 01:00:00.000000000 +0100 10090 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c 2006-12-10 03:57:50.000000000 +0100 10091 @@ -0,0 +1,42 @@ 11788 10092 +#include "yaffs_packedtags1.h" 11789 10093 +#include "yportenv.h" 11790 10094 + 11791 +void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags *t)10095 +void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t) 11792 10096 +{ 11793 10097 + pt->chunkId = t->chunkId; … … 11799 10103 + pt->unusedStuff = 0; 11800 10104 + pt->shouldBeFF = 0xFFFFFFFF; 11801 + 11802 +} 11803 + 11804 +void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt) 11805 +{ 11806 + static const __u8 allFF[] = 11807 + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 11808 +0xff }; 11809 + 11810 + if (memcmp(allFF, pt, sizeof(yaffs_PackedTags1))) { 10105 + 10106 +} 10107 + 10108 +void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt) 10109 +{ 10110 + static const __u8 allFF[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff}; 10111 + 10112 + if(memcmp(allFF,pt,sizeof(yaffs_PackedTags1))) 10113 + { 11811 10114 + t->blockBad = 0; 11812 + if (pt->shouldBeFF != 0xFFFFFFFF) { 10115 + if(pt->shouldBeFF != 0xFFFFFFFF) 10116 + { 11813 10117 + t->blockBad = 1; 11814 10118 + } … … 11817 10121 + t->chunkId = pt->chunkId; 11818 10122 + t->byteCount = pt->byteCount; 11819 + t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;10123 + t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; 11820 10124 + t->chunkDeleted = (pt->deleted) ? 0 : 1; 11821 10125 + t->serialNumber = pt->serialNumber; 11822 + } else { 11823 + memset(t, 0, sizeof(yaffs_ExtendedTags)); 11824 + 11825 + } 11826 +} 11827 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.h 11828 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.h 1970-01-01 01:00:00.000000000 +0100 11829 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.h 2006-11-25 00:15:32.000000000 +0100 11830 @@ -0,0 +1,22 @@ 10126 + } 10127 + else 10128 + { 10129 + memset(t,0,sizeof(yaffs_ExtendedTags)); 10130 + 10131 + } 10132 +} 10133 + 10134 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h 10135 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h 1970-01-01 01:00:00.000000000 +0100 10136 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h 2006-12-10 03:57:50.000000000 +0100 10137 @@ -0,0 +1,28 @@ 11831 10138 +// This is used to pack YAFFS1 tags, not YAFFS2 tags. 11832 10139 + … … 11834 10141 +#define __YAFFS_PACKEDTAGS1_H__ 11835 10142 + 10143 + 11836 10144 +#include "yaffs_guts.h" 11837 10145 + 11838 +typedef struct { 11839 + unsigned chunkId:20; 11840 + unsigned serialNumber:2; 11841 + unsigned byteCount:10; 11842 + unsigned objectId:18; 11843 + unsigned ecc:12; 11844 + unsigned deleted:1; 11845 + unsigned unusedStuff:1; 11846 + unsigned shouldBeFF; 10146 +typedef struct 10147 +{ 10148 + unsigned chunkId:20; 10149 + unsigned serialNumber:2; 10150 + unsigned byteCount:10; 10151 + unsigned objectId:18; 10152 + unsigned ecc:12; 10153 + unsigned deleted:1; 10154 + unsigned unusedStuff:1; 10155 + unsigned shouldBeFF; 11847 10156 + 11848 10157 +} yaffs_PackedTags1; 11849 10158 + 11850 +void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t); 11851 +void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt); 11852 +#endif 11853 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.c 11854 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.c 1970-01-01 01:00:00.000000000 +0100 11855 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.c 2006-11-25 00:15:32.000000000 +0100 11856 @@ -0,0 +1,184 @@ 10159 + 10160 + 10161 +void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t); 10162 +void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt); 10163 +#endif 10164 + 10165 + 10166 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c 10167 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c 1970-01-01 01:00:00.000000000 +0100 10168 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c 2006-12-10 03:57:50.000000000 +0100 10169 @@ -0,0 +1,164 @@ 11857 10170 +/* 11858 10171 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 11869 10182 + * version 2.1 as published by the Free Software Foundation. 11870 10183 + */ 11871 + 10184 + 11872 10185 +#include "yaffs_packedtags2.h" 11873 10186 +#include "yportenv.h" 11874 10187 +#include "yaffs_tagsvalidity.h" 11875 10188 + 11876 +/* This code packs a set of extended tags into a binary structure for 11877 + * NAND storage 11878 + */ 11879 + 11880 +/* Some of the information is "extra" struff which can be packed in to 11881 + * speed scanning 11882 + * This is defined by having the EXTRA_HEADER_INFO_FLAG set. 11883 + */ 11884 + 11885 +/* Extra flags applied to chunkId */ 10189 + 10190 + 10191 +// This code packs a set of extended tags into a binary structure for NAND storage 10192 + 10193 +// Some of the information is "extra" struff which can be packed in to speed scanning 10194 +// This is defined by having the EXTRA_HEADER_INFO_FLAG set. 10195 + 10196 + 10197 +// Extra flags applied to chunkId 11886 10198 + 11887 10199 +#define EXTRA_HEADER_INFO_FLAG 0x80000000 … … 11892 10204 +#define ALL_EXTRA_FLAGS 0xF0000000 11893 10205 + 11894 +/* Also, the top 4 bits of the object Id are set to the object type. */ 10206 + 10207 + 10208 +// Also, the top 4 bits of the object Id are set to the object type. 11895 10209 +#define EXTRA_OBJECT_TYPE_SHIFT (28) 11896 10210 +#define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT) 11897 10211 + 11898 +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) 11899 +{ 11900 + T(YAFFS_TRACE_MTD, 11901 + (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), 11902 + pt->t.objectId, pt->t.chunkId, pt->t.byteCount, 11903 + pt->t.sequenceNumber)); 11904 +} 11905 + 11906 +static void yaffs_DumpTags2(const yaffs_ExtendedTags * t) 11907 +{ 11908 + T(YAFFS_TRACE_MTD, 11909 + (TSTR 11910 + ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte " 11911 + "%d del %d ser %d seq %d" 11912 + TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId, 11913 + t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, 11914 + t->sequenceNumber)); 11915 + 11916 +} 11917 + 11918 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t) 10212 + 10213 + 10214 +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt) 10215 +{ 10216 + T(YAFFS_TRACE_MTD,(TSTR("packed tags obj %d chunk %d byte %d seq %d"TENDSTR),pt->t.objectId,pt->t.chunkId,pt->t.byteCount,pt->t.sequenceNumber)); 10217 +} 10218 + 10219 +static void yaffs_DumpTags2(const yaffs_ExtendedTags *t) 10220 +{ 10221 + T(YAFFS_TRACE_MTD,(TSTR("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"TENDSTR), 10222 + t->eccResult, t->blockBad, t->chunkUsed, t->objectId, t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, t->sequenceNumber)); 10223 + 10224 +} 10225 + 10226 +void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t) 11919 10227 +{ 11920 10228 + pt->t.chunkId = t->chunkId; … … 11922 10230 + pt->t.byteCount = t->byteCount; 11923 10231 + pt->t.objectId = t->objectId; 11924 + 11925 + if (t->chunkId == 0 && t->extraHeaderInfoAvailable) { 11926 + /* Store the extra header info instead */ 11927 + /* We save the parent object in the chunkId */ 11928 + pt->t.chunkId = EXTRA_HEADER_INFO_FLAG 11929 + | t->extraParentObjectId; 11930 + if (t->extraIsShrinkHeader) { 11931 + pt->t.chunkId |= EXTRA_SHRINK_FLAG; 11932 + } 11933 + if (t->extraShadows) { 11934 + pt->t.chunkId |= EXTRA_SHADOWS_FLAG; 11935 + } 11936 + 10232 + 10233 + if(t->chunkId == 0 && t->extraHeaderInfoAvailable) 10234 + { 10235 + // Store the extra header info instead 10236 + pt->t.chunkId = EXTRA_HEADER_INFO_FLAG | t->extraParentObjectId; // We save the parent object in the chunkId 10237 + if(t->extraIsShrinkHeader) 10238 + { 10239 + pt->t.chunkId |= EXTRA_SHRINK_FLAG; 10240 + } 10241 + if(t->extraShadows) 10242 + { 10243 + pt->t.chunkId |= EXTRA_SHADOWS_FLAG; 10244 + } 10245 + 11937 10246 + pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK; 11938 + pt->t.objectId |= 11939 + (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT); 11940 + 11941 + if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { 11942 + pt->t.byteCount = t->extraEquivalentObjectId; 11943 + } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) { 11944 + pt->t.byteCount = t->extraFileLength; 11945 + } else { 11946 + pt->t.byteCount = 0; 11947 + } 11948 + } 11949 + 10247 + pt->t.objectId |= (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT); 10248 + 10249 + if(t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) 10250 + { 10251 + pt->t.byteCount = t->extraEquivalentObjectId; 10252 + } 10253 + else if(t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) 10254 + { 10255 + pt->t.byteCount = t->extraFileLength; 10256 + } 10257 + else 10258 + { 10259 + pt->t.byteCount = 0; 10260 + } 10261 + } 10262 + 11950 10263 + yaffs_DumpPackedTags2(pt); 11951 10264 + yaffs_DumpTags2(t); 11952 + 10265 + 11953 10266 +#ifndef YAFFS_IGNORE_TAGS_ECC 11954 + { 11955 + yaffs_ECCCalculateOther((unsigned char *)&pt->t, 11956 + sizeof(yaffs_PackedTags2TagsPart), 11957 + &pt->ecc); 11958 + } 11959 +#endif 11960 +} 11961 + 11962 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) 11963 +{ 11964 + 11965 + memset(t, 0, sizeof(yaffs_ExtendedTags)); 11966 + 10267 + { 10268 + yaffs_ECCCalculateOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&pt->ecc); 10269 + } 10270 +#endif 10271 +} 10272 + 10273 +void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt) 10274 +{ 10275 + 10276 + 10277 + memset(t,0,sizeof(yaffs_ExtendedTags)); 10278 + 11967 10279 + yaffs_InitialiseTags(t); 11968 + 11969 + if (pt->t.sequenceNumber != 0xFFFFFFFF) { 11970 + /* Page is in use */ 10280 + 10281 + if(pt->t.sequenceNumber != 0xFFFFFFFF) 10282 + { 10283 + // Page is in use 11971 10284 +#ifdef YAFFS_IGNORE_TAGS_ECC 11972 10285 + { 11973 + t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;10286 + t->eccResult = 0; 11974 10287 + } 11975 10288 +#else 11976 10289 + { 11977 10290 + yaffs_ECCOther ecc; 11978 + int result; 11979 + yaffs_ECCCalculateOther((unsigned char *)&pt->t, 11980 + sizeof 11981 + (yaffs_PackedTags2TagsPart), 11982 + &ecc); 11983 + result = 11984 + yaffs_ECCCorrectOther((unsigned char *)&pt->t, 11985 + sizeof 11986 + (yaffs_PackedTags2TagsPart), 11987 + &pt->ecc, &ecc); 11988 + switch(result){ 11989 + case 0: 11990 + t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; 11991 + break; 11992 + case 1: 11993 + t->eccResult = YAFFS_ECC_RESULT_FIXED; 11994 + break; 11995 + case -1: 11996 + t->eccResult = YAFFS_ECC_RESULT_UNFIXED; 11997 + break; 11998 + default: 11999 + t->eccResult = YAFFS_ECC_RESULT_UNKNOWN; 12000 + } 10291 + yaffs_ECCCalculateOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&ecc); 10292 + t->eccResult = yaffs_ECCCorrectOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&pt->ecc,&ecc); 12001 10293 + } 12002 10294 +#endif … … 12004 10296 + t->chunkUsed = 1; 12005 10297 + t->objectId = pt->t.objectId; 12006 + t->chunkId = pt->t.chunkId;10298 + t->chunkId = pt->t.chunkId; 12007 10299 + t->byteCount = pt->t.byteCount; 12008 10300 + t->chunkDeleted = 0; 12009 10301 + t->serialNumber = 0; 12010 10302 + t->sequenceNumber = pt->t.sequenceNumber; 12011 + 12012 + /* Do extra header info stuff */ 12013 + 12014 + if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) { 10303 + 10304 + // Do extra header info stuff 10305 + 10306 + if(pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) 10307 + { 12015 10308 + t->chunkId = 0; 12016 10309 + t->byteCount = 0; 12017 + 10310 + 12018 10311 + t->extraHeaderInfoAvailable = 1; 12019 + t->extraParentObjectId = 12020 + pt->t.chunkId & (~(ALL_EXTRA_FLAGS)); 12021 + t->extraIsShrinkHeader = 12022 + (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; 12023 + t->extraShadows = 12024 + (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; 12025 + t->extraObjectType = 12026 + pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT; 10312 + t->extraParentObjectId = pt->t.chunkId & (~(ALL_EXTRA_FLAGS)); 10313 + t->extraIsShrinkHeader = (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; 10314 + t->extraShadows = (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; 10315 + t->extraObjectType = pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT; 12027 10316 + t->objectId &= ~EXTRA_OBJECT_TYPE_MASK; 12028 + 12029 + if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { 12030 + t->extraEquivalentObjectId = pt->t.byteCount; 12031 + } else { 12032 + t->extraFileLength = pt->t.byteCount; 10317 + 10318 + if(t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) 10319 + { 10320 + t->extraEquivalentObjectId = pt->t.byteCount; 10321 + } 10322 + else 10323 + { 10324 + t->extraFileLength = pt->t.byteCount; 12033 10325 + } 12034 10326 + } … … 12039 10331 + 12040 10332 +} 12041 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.h 12042 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.h 1970-01-01 01:00:00.000000000 +0100 12043 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.h 2006-11-25 00:15:32.000000000 +0100 12044 @@ -0,0 +1,23 @@ 12045 +/* This is used to pack YAFFS2 tags, not YAFFS1tags. */ 10333 + 10334 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h 10335 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h 1970-01-01 01:00:00.000000000 +0100 10336 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h 2006-12-10 03:57:50.000000000 +0100 10337 @@ -0,0 +1,30 @@ 10338 +// This is used to pack YAFFS2 tags, not YAFFS1tags. 12046 10339 + 12047 10340 +#ifndef __YAFFS_PACKEDTAGS2_H__ 12048 10341 +#define __YAFFS_PACKEDTAGS2_H__ 12049 10342 + 10343 + 12050 10344 +#include "yaffs_guts.h" 12051 10345 +#include "yaffs_ecc.h" 12052 10346 + 12053 +typedef struct { 12054 + unsigned sequenceNumber; 12055 + unsigned objectId; 12056 + unsigned chunkId; 12057 + unsigned byteCount; 10347 + 10348 +typedef struct 10349 +{ 10350 + unsigned sequenceNumber; 10351 + unsigned objectId; 10352 + unsigned chunkId; 10353 + unsigned byteCount; 12058 10354 +} yaffs_PackedTags2TagsPart; 12059 10355 + 12060 +typedef struct { 12061 + yaffs_PackedTags2TagsPart t; 12062 + yaffs_ECCOther ecc; 10356 +typedef struct 10357 +{ 10358 + yaffs_PackedTags2TagsPart t; 10359 + yaffs_ECCOther ecc; 12063 10360 +} yaffs_PackedTags2; 12064 10361 + 12065 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t); 12066 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt); 12067 +#endif 12068 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_qsort.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.c 12069 --- linux-2.6.18.2/fs/yaffs2/yaffs_qsort.c 1970-01-01 01:00:00.000000000 +0100 12070 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.c 2006-11-25 00:15:32.000000000 +0100 12071 @@ -0,0 +1,156 @@ 12072 +/* 12073 + * Copyright (c) 1992, 1993 12074 + * The Regents of the University of California. All rights reserved. 12075 + * 12076 + * Redistribution and use in source and binary forms, with or without 12077 + * modification, are permitted provided that the following conditions 12078 + * are met: 12079 + * 1. Redistributions of source code must retain the above copyright 12080 + * notice, this list of conditions and the following disclaimer. 12081 + * 2. Redistributions in binary form must reproduce the above copyright 12082 + * notice, this list of conditions and the following disclaimer in the 12083 + * documentation and/or other materials provided with the distribution. 12084 + * 3. Neither the name of the University nor the names of its contributors 12085 + * may be used to endorse or promote products derived from this software 12086 + * without specific prior written permission. 12087 + * 12088 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 12089 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12090 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 12091 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 12092 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 12093 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 12094 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 12095 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 12096 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 12097 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 12098 + * SUCH DAMAGE. 12099 + */ 12100 + 12101 +#include "yportenv.h" 12102 +//#include <linux/string.h> 12103 + 12104 +/* 12105 + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". 12106 + */ 12107 +#define swapcode(TYPE, parmi, parmj, n) { \ 12108 + long i = (n) / sizeof (TYPE); \ 12109 + register TYPE *pi = (TYPE *) (parmi); \ 12110 + register TYPE *pj = (TYPE *) (parmj); \ 12111 + do { \ 12112 + register TYPE t = *pi; \ 12113 + *pi++ = *pj; \ 12114 + *pj++ = t; \ 12115 + } while (--i > 0); \ 12116 +} 12117 + 12118 +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 12119 + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 12120 + 12121 +static __inline void 12122 +swapfunc(char *a, char *b, int n, int swaptype) 12123 +{ 12124 + if (swaptype <= 1) 12125 + swapcode(long, a, b, n) 12126 + else 12127 + swapcode(char, a, b, n) 12128 +} 12129 + 12130 +#define swap(a, b) \ 12131 + if (swaptype == 0) { \ 12132 + long t = *(long *)(a); \ 12133 + *(long *)(a) = *(long *)(b); \ 12134 + *(long *)(b) = t; \ 12135 + } else \ 12136 + swapfunc(a, b, es, swaptype) 12137 + 12138 +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 12139 + 12140 +static __inline char * 12141 +med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *)) 12142 +{ 12143 + return cmp(a, b) < 0 ? 12144 + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) 12145 + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); 12146 +} 12147 + 12148 +#define min(a,b) (((a) < (b)) ? (a) : (b)) 12149 +void 12150 +qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)) 12151 +{ 12152 + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 12153 + int d, r, swaptype, swap_cnt; 12154 + register char *a = aa; 12155 + 12156 +loop: SWAPINIT(a, es); 12157 + swap_cnt = 0; 12158 + if (n < 7) { 12159 + for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es) 12160 + for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 12161 + pl -= es) 12162 + swap(pl, pl - es); 12163 + return; 12164 + } 12165 + pm = (char *)a + (n / 2) * es; 12166 + if (n > 7) { 12167 + pl = (char *)a; 12168 + pn = (char *)a + (n - 1) * es; 12169 + if (n > 40) { 12170 + d = (n / 8) * es; 12171 + pl = med3(pl, pl + d, pl + 2 * d, cmp); 12172 + pm = med3(pm - d, pm, pm + d, cmp); 12173 + pn = med3(pn - 2 * d, pn - d, pn, cmp); 12174 + } 12175 + pm = med3(pl, pm, pn, cmp); 12176 + } 12177 + swap(a, pm); 12178 + pa = pb = (char *)a + es; 12179 + 12180 + pc = pd = (char *)a + (n - 1) * es; 12181 + for (;;) { 12182 + while (pb <= pc && (r = cmp(pb, a)) <= 0) { 12183 + if (r == 0) { 12184 + swap_cnt = 1; 12185 + swap(pa, pb); 12186 + pa += es; 12187 + } 12188 + pb += es; 12189 + } 12190 + while (pb <= pc && (r = cmp(pc, a)) >= 0) { 12191 + if (r == 0) { 12192 + swap_cnt = 1; 12193 + swap(pc, pd); 12194 + pd -= es; 12195 + } 12196 + pc -= es; 12197 + } 12198 + if (pb > pc) 12199 + break; 12200 + swap(pb, pc); 12201 + swap_cnt = 1; 12202 + pb += es; 12203 + pc -= es; 12204 + } 12205 + if (swap_cnt == 0) { /* Switch to insertion sort */ 12206 + for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) 12207 + for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 12208 + pl -= es) 12209 + swap(pl, pl - es); 12210 + return; 12211 + } 12212 + 12213 + pn = (char *)a + n * es; 12214 + r = min(pa - (char *)a, pb - pa); 12215 + vecswap(a, pb - r, r); 12216 + r = min((long)(pd - pc), (long)(pn - pd - es)); 12217 + vecswap(pb, pn - r, r); 12218 + if ((r = pb - pa) > es) 12219 + qsort(a, r / es, es, cmp); 12220 + if ((r = pd - pc) > es) { 12221 + /* Iterate rather than recurse to save stack space */ 12222 + a = pn - r; 12223 + n = r / es; 12224 + goto loop; 12225 + } 12226 +/* qsort(pn - r, r / es, es, cmp);*/ 12227 +} 12228 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_qsort.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.h 12229 --- linux-2.6.18.2/fs/yaffs2/yaffs_qsort.h 1970-01-01 01:00:00.000000000 +0100 12230 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.h 2006-11-25 00:15:32.000000000 +0100 12231 @@ -0,0 +1,23 @@ 12232 +/* 12233 + * YAFFS: Yet another FFS. A NAND-flash specific file system. 12234 + * yaffs_qsort.h: Interface to BSD-licensed qsort routine. 12235 + * 12236 + * Copyright (C) 2002 Aleph One Ltd. 12237 + * for Toby Churchill Ltd and Brightstar Engineering 12238 + * 12239 + * Created by Charles Manning <charles@aleph1.co.uk> 12240 + * 12241 + * This program is free software; you can redistribute it and/or modify 12242 + * it under the terms of the GNU Lesser General Public License version 2.1 as 12243 + * published by the Free Software Foundation. 12244 + * 12245 + * $Id: yaffs_qsort.h,v 1.2 2006/11/07 23:20:09 charles Exp $ 12246 + */ 12247 + 12248 +#ifndef __YAFFS_QSORT_H__ 12249 +#define __YAFFS_QSORT_H__ 12250 + 12251 +extern void qsort (void *const base, size_t total_elems, size_t size, 12252 + int (*cmp)(const void *, const void *)); 12253 + 12254 +#endif 12255 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.c 12256 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.c 1970-01-01 01:00:00.000000000 +0100 12257 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.c 2006-11-25 00:15:32.000000000 +0100 12258 @@ -0,0 +1,532 @@ 10362 + 10363 +void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t); 10364 +void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt); 10365 +#endif 10366 + 10367 + 10368 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c 10369 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c 1970-01-01 01:00:00.000000000 +0100 10370 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c 2006-12-10 03:57:50.000000000 +0100 10371 @@ -0,0 +1,698 @@ 12259 10372 +/* 12260 10373 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 12269 10382 + * published by the Free Software Foundation. 12270 10383 + * 12271 + * $Id: yaffs_tagscompat.c,v 1. 8 2005/11/29 20:54:32 marty Exp $10384 + * $Id: yaffs_tagscompat.c,v 1.3 2005/07/31 06:47:12 marty Exp $ 12272 10385 + */ 12273 10386 + … … 12276 10389 +#include "yaffs_ecc.h" 12277 10390 + 12278 +static void yaffs_HandleReadDataError(yaffs_Device * dev,int chunkInNAND);10391 +static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND); 12279 10392 +#ifdef NOTYET 12280 +static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND); 12281 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, 12282 + const __u8 * data, 12283 + const yaffs_Spare * spare); 12284 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, 12285 + const yaffs_Spare * spare); 12286 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND); 12287 +#endif 12288 + 12289 +static const char yaffs_countBitsTable[256] = { 12290 + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 12291 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 12292 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 12293 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 12294 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 12295 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 12296 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 12297 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 12298 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 12299 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 12300 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 12301 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 12302 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 12303 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 12304 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 12305 + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 10393 +static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND); 10394 +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare); 10395 +static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_Spare *spare); 10396 +static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND); 10397 +#endif 10398 + 10399 + 10400 +static const char yaffs_countBitsTable[256] = 10401 +{ 10402 +0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, 10403 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 10404 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 10405 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 10406 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 10407 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 10408 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 10409 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 10410 +1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 10411 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 10412 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 10413 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 10414 +2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 10415 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 10416 +3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 10417 +4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 12306 10418 +}; 12307 10419 + … … 12313 10425 +} 12314 10426 + 12315 +/********** Tags ECC calculations *********/ 12316 + 12317 +void yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare) 12318 +{ 12319 + yaffs_ECCCalculate(data, spare->ecc1); 12320 + yaffs_ECCCalculate(&data[256], spare->ecc2); 12321 +} 12322 + 12323 +void yaffs_CalcTagsECC(yaffs_Tags * tags) 12324 +{ 12325 + /* Calculate an ecc */ 12326 + 12327 + unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes; 12328 + unsigned i, j; 12329 + unsigned ecc = 0; 10427 + 10428 +/////////////// Tags ECC calculations /////////////////// 10429 + 10430 +void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) 10431 +{ 10432 + yaffs_ECCCalculate(data , spare->ecc1); 10433 + yaffs_ECCCalculate(&data[256] , spare->ecc2); 10434 +} 10435 + 10436 +void yaffs_CalcTagsECC(yaffs_Tags *tags) 10437 +{ 10438 + // Calculate an ecc 10439 + 10440 + unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; 10441 + unsigned i,j; 10442 + unsigned ecc = 0; 12330 10443 + unsigned bit = 0; 12331 10444 + 12332 10445 + tags->ecc = 0; 12333 10446 + 12334 + for (i = 0; i < 8; i++) { 12335 + for (j = 1; j & 0xff; j <<= 1) { 10447 + for(i = 0; i < 8; i++) 10448 + { 10449 + for(j = 1; j &0xff; j<<=1) 10450 + { 12336 10451 + bit++; 12337 + if (b[i] & j) { 10452 + if(b[i] & j) 10453 + { 12338 10454 + ecc ^= bit; 12339 10455 + } … … 12343 10459 + tags->ecc = ecc; 12344 10460 + 12345 +} 12346 + 12347 +int yaffs_CheckECCOnTags(yaffs_Tags * tags) 10461 + 10462 +} 10463 + 10464 +int yaffs_CheckECCOnTags(yaffs_Tags *tags) 12348 10465 +{ 12349 10466 + unsigned ecc = tags->ecc; … … 12352 10469 + 12353 10470 + ecc ^= tags->ecc; 12354 + 12355 + if (ecc && ecc <= 64) { 12356 + /* TODO: Handle the failure better. Retire? */ 12357 + unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes; 10471 + 10472 + if(ecc && ecc <= 64) 10473 + { 10474 + // TODO: Handle the failure better. Retire? 10475 + unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; 12358 10476 + 12359 10477 + ecc--; … … 12361 10479 + b[ecc / 8] ^= (1 << (ecc & 7)); 12362 10480 + 12363 + / * Now recvalc the ecc */10481 + // Now recvalc the ecc 12364 10482 + yaffs_CalcTagsECC(tags); 12365 10483 + 12366 + return 1; /* recovered error */ 12367 + } else if (ecc) { 12368 + /* Wierd ecc failure value */ 12369 + /* TODO Need to do somethiong here */ 12370 + return -1; /* unrecovered error */ 10484 + return 1; // recovered error 10485 + } 10486 + else if(ecc) 10487 + { 10488 + // Wierd ecc failure value 10489 + // TODO Need to do somethiong here 10490 + return -1; //unrecovered error 12371 10491 + } 12372 10492 + … … 12374 10494 +} 12375 10495 + 12376 +/********** Tags **********/ 12377 + 12378 +static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr, 12379 + yaffs_Tags * tagsPtr) 12380 +{ 12381 + yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr; 10496 +//////////////////////////// Tags /////////////////////////////////////// 10497 + 10498 +static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr) 10499 +{ 10500 + yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; 12382 10501 + 12383 10502 + yaffs_CalcTagsECC(tagsPtr); 12384 + 10503 + 12385 10504 + sparePtr->tagByte0 = tu->asBytes[0]; 12386 10505 + sparePtr->tagByte1 = tu->asBytes[1]; … … 12393 10512 +} 12394 10513 + 12395 +static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr, 12396 + yaffs_Tags * tagsPtr) 12397 +{ 12398 + yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr; 10514 +static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr) 10515 +{ 10516 + yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; 12399 10517 + int result; 12400 10518 + 12401 + tu->asBytes[0] = sparePtr->tagByte0; 12402 + tu->asBytes[1] = sparePtr->tagByte1; 12403 + tu->asBytes[2] = sparePtr->tagByte2; 12404 + tu->asBytes[3] = sparePtr->tagByte3; 12405 + tu->asBytes[4] = sparePtr->tagByte4; 12406 + tu->asBytes[5] = sparePtr->tagByte5; 12407 + tu->asBytes[6] = sparePtr->tagByte6; 12408 + tu->asBytes[7] = sparePtr->tagByte7; 12409 + 12410 + result = yaffs_CheckECCOnTags(tagsPtr); 12411 + if (result > 0) { 10519 + tu->asBytes[0]= sparePtr->tagByte0; 10520 + tu->asBytes[1]= sparePtr->tagByte1; 10521 + tu->asBytes[2]= sparePtr->tagByte2; 10522 + tu->asBytes[3]= sparePtr->tagByte3; 10523 + tu->asBytes[4]= sparePtr->tagByte4; 10524 + tu->asBytes[5]= sparePtr->tagByte5; 10525 + tu->asBytes[6]= sparePtr->tagByte6; 10526 + tu->asBytes[7]= sparePtr->tagByte7; 10527 + 10528 + result = yaffs_CheckECCOnTags(tagsPtr); 10529 + if(result> 0) 10530 + { 12412 10531 + dev->tagsEccFixed++; 12413 + } else if (result < 0) { 10532 + } 10533 + else if(result <0) 10534 + { 12414 10535 + dev->tagsEccUnfixed++; 12415 10536 + } 12416 10537 +} 12417 10538 + 12418 +static void yaffs_SpareInitialise(yaffs_Spare * spare)12419 +{ 12420 + memset(spare, 0xFF,sizeof(yaffs_Spare));12421 +} 12422 + 12423 + static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,12424 + int chunkInNAND, const __u8 * data,12425 + yaffs_Spare * spare)12426 + {12427 + if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock){12428 + T(YAFFS_TRACE_ERROR,12429 + (TSTR("**>> yaffs chunk %d is not valid" TENDSTR),12430 + chunkInNAND));10539 +static void yaffs_SpareInitialise(yaffs_Spare *spare) 10540 +{ 10541 + memset(spare,0xFF,sizeof(yaffs_Spare)); 10542 +} 10543 + 10544 + 10545 + 10546 + 10547 +static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare) 10548 +{ 10549 + if(chunkInNAND < dev->startBlock * dev->nChunksPerBlock) 10550 + { 10551 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d is not valid" TENDSTR),chunkInNAND)); 12431 10552 + return YAFFS_FAIL; 12432 10553 + } 12433 10554 + 12434 10555 + dev->nPageWrites++; 12435 + return dev->writeChunkToNAND(dev, chunkInNAND, data, spare); 12436 +} 10556 + return dev->writeChunkToNAND(dev,chunkInNAND,data,spare); 10557 +} 10558 + 10559 + 12437 10560 + 12438 10561 +static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, 12439 + int chunkInNAND,12440 + __u8 * data,12441 + yaffs_Spare *spare,12442 + yaffs_ECCResult *eccResult,12443 + int doErrorCorrection)10562 + int chunkInNAND, 10563 + __u8 *data, 10564 + yaffs_Spare *spare, 10565 + yaffs_ECCResult *eccResult, 10566 + int doErrorCorrection) 12444 10567 +{ 12445 10568 + int retVal; … … 12447 10570 + 12448 10571 + dev->nPageReads++; 12449 + 12450 + if (!spare && data) { 12451 + /* If we don't have a real spare, then we use a local one. */ 12452 + /* Need this for the calculation of the ecc */ 10572 + 10573 + 10574 + 10575 + 10576 + if(!spare && data) 10577 + { 10578 + // If we don't have a real spare, then we use a local one. 10579 + // Need this for the calculation of the ecc 12453 10580 + spare = &localSpare; 12454 10581 + } 12455 + 12456 + if (!dev->useNANDECC) { 12457 + retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare); 12458 + if (data && doErrorCorrection) { 12459 + /* Do ECC correction */ 12460 + /* Todo handle any errors */ 12461 + int eccResult1, eccResult2; 12462 + __u8 calcEcc[3]; 12463 + 12464 + yaffs_ECCCalculate(data, calcEcc); 12465 + eccResult1 = 12466 + yaffs_ECCCorrect(data, spare->ecc1, calcEcc); 12467 + yaffs_ECCCalculate(&data[256], calcEcc); 12468 + eccResult2 = 12469 + yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc); 12470 + 12471 + if (eccResult1 > 0) { 12472 + T(YAFFS_TRACE_ERROR, 12473 + (TSTR 12474 + ("**>>yaffs ecc error fix performed on chunk %d:0" 12475 + TENDSTR), chunkInNAND)); 10582 + 10583 + 10584 + if(!dev->useNANDECC) 10585 + { 10586 + retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,spare); 10587 + if(data && doErrorCorrection) 10588 + { 10589 + // Do ECC correction 10590 + //Todo handle any errors 10591 + int eccResult1,eccResult2; 10592 + __u8 calcEcc[3]; 10593 + 10594 + yaffs_ECCCalculate(data,calcEcc); 10595 + eccResult1 = yaffs_ECCCorrect (data,spare->ecc1, calcEcc); 10596 + yaffs_ECCCalculate(&data[256],calcEcc); 10597 + eccResult2 = yaffs_ECCCorrect(&data[256],spare->ecc2, calcEcc); 10598 + 10599 + if(eccResult1>0) 10600 + { 10601 + T(YAFFS_TRACE_ERROR, (TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND)); 12476 10602 + dev->eccFixed++; 12477 + } else if (eccResult1 < 0) { 12478 + T(YAFFS_TRACE_ERROR, 12479 + (TSTR 12480 + ("**>>yaffs ecc error unfixed on chunk %d:0" 12481 + TENDSTR), chunkInNAND)); 10603 + } 10604 + else if(eccResult1<0) 10605 + { 10606 + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND)); 12482 10607 + dev->eccUnfixed++; 12483 10608 + } 12484 10609 + 12485 + if (eccResult2 > 0) { 12486 + T(YAFFS_TRACE_ERROR, 12487 + (TSTR 12488 + ("**>>yaffs ecc error fix performed on chunk %d:1" 12489 + TENDSTR), chunkInNAND)); 10610 + if(eccResult2>0) 10611 + { 10612 + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND)); 12490 10613 + dev->eccFixed++; 12491 + } else if (eccResult2 < 0) { 12492 + T(YAFFS_TRACE_ERROR, 12493 + (TSTR 12494 + ("**>>yaffs ecc error unfixed on chunk %d:1" 12495 + TENDSTR), chunkInNAND)); 10614 + } 10615 + else if(eccResult2<0) 10616 + { 10617 + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND)); 12496 10618 + dev->eccUnfixed++; 12497 10619 + } 12498 10620 + 12499 + if (eccResult1 || eccResult2) { 12500 + /* We had a data problem on this page */ 12501 + yaffs_HandleReadDataError(dev, chunkInNAND); 10621 + if(eccResult1 || eccResult2) 10622 + { 10623 + // Hoosterman, we had a data problem on this page 10624 + yaffs_HandleReadDataError(dev,chunkInNAND); 12502 10625 + } 12503 + 12504 + if (eccResult1 < 0 || eccResult2 < 0)10626 + 10627 + if(eccResult1 < 0 || eccResult2 < 0) 12505 10628 + *eccResult = YAFFS_ECC_RESULT_UNFIXED; 12506 + else if (eccResult1 > 0 || eccResult2 > 0)10629 + else if(eccResult1 > 0 || eccResult2 > 0) 12507 10630 + *eccResult = YAFFS_ECC_RESULT_FIXED; 12508 10631 + else 12509 10632 + *eccResult = YAFFS_ECC_RESULT_NO_ERROR; 12510 10633 + } 12511 + } else { 12512 + /* Must allocate enough memory for spare+2*sizeof(int) */ 12513 + /* for ecc results from device. */ 12514 + struct yaffs_NANDSpare nspare; 12515 + retVal = 12516 + dev->readChunkFromNAND(dev, chunkInNAND, data, 12517 + (yaffs_Spare *) & nspare); 12518 + memcpy(spare, &nspare, sizeof(yaffs_Spare)); 12519 + if (data && doErrorCorrection) { 12520 + if (nspare.eccres1 > 0) { 12521 + T(YAFFS_TRACE_ERROR, 12522 + (TSTR 12523 + ("**>>mtd ecc error fix performed on chunk %d:0" 12524 + TENDSTR), chunkInNAND)); 12525 + } else if (nspare.eccres1 < 0) { 12526 + T(YAFFS_TRACE_ERROR, 12527 + (TSTR 12528 + ("**>>mtd ecc error unfixed on chunk %d:0" 12529 + TENDSTR), chunkInNAND)); 10634 + } 10635 + else 10636 + { 10637 + // Must allocate enough memory for spare+2*sizeof(int) for ecc results from device. 10638 + struct yaffs_NANDSpare nspare; 10639 + retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare); 10640 + memcpy (spare, &nspare, sizeof(yaffs_Spare)); 10641 + if(data && doErrorCorrection) 10642 + { 10643 + if(nspare.eccres1>0) 10644 + { 10645 + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND)); 12530 10646 + } 12531 + 12532 + if (nspare.eccres2 > 0) { 12533 + T(YAFFS_TRACE_ERROR, 12534 + (TSTR 12535 + ("**>>mtd ecc error fix performed on chunk %d:1" 12536 + TENDSTR), chunkInNAND)); 12537 + } else if (nspare.eccres2 < 0) { 12538 + T(YAFFS_TRACE_ERROR, 12539 + (TSTR 12540 + ("**>>mtd ecc error unfixed on chunk %d:1" 12541 + TENDSTR), chunkInNAND)); 10647 + else if(nspare.eccres1<0) 10648 + { 10649 + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND)); 12542 10650 + } 12543 10651 + 12544 + if (nspare.eccres1 || nspare.eccres2) {12545 + /* We had a data problem on this page */12546 + yaffs_HandleReadDataError(dev, chunkInNAND);10652 + if(nspare.eccres2>0) 10653 + { 10654 + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND)); 12547 10655 + } 12548 + 12549 + if (nspare.eccres1 < 0 || nspare.eccres2 < 0) 10656 + else if(nspare.eccres2<0) 10657 + { 10658 + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND)); 10659 + } 10660 + 10661 + if(nspare.eccres1 || nspare.eccres2) 10662 + { 10663 + // Hoosterman, we had a data problem on this page 10664 + yaffs_HandleReadDataError(dev,chunkInNAND); 10665 + } 10666 + 10667 + if(nspare.eccres1 < 0 || nspare.eccres2 < 0) 12550 10668 + *eccResult = YAFFS_ECC_RESULT_UNFIXED; 12551 + else if (nspare.eccres1 > 0 || nspare.eccres2 > 0)10669 + else if(nspare.eccres1 > 0 || nspare.eccres2 > 0) 12552 10670 + *eccResult = YAFFS_ECC_RESULT_FIXED; 12553 10671 + else 12554 10672 + *eccResult = YAFFS_ECC_RESULT_NO_ERROR; 12555 10673 + 10674 + 12556 10675 + } 12557 10676 + } … … 12560 10679 + 12561 10680 +#ifdef NOTYET 12562 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, 12563 + int chunkInNAND) 10681 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND) 12564 10682 +{ 12565 10683 + … … 12567 10685 + static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK]; 12568 10686 + static __u8 data[YAFFS_BYTES_PER_CHUNK]; 12569 + /* Might as well always allocate the larger size for */ 12570 + /* dev->useNANDECC == true; */ 10687 + // Might as well always allocate the larger size for dev->useNANDECC == true; 12571 10688 + static __u8 spare[sizeof(struct yaffs_NANDSpare)]; 12572 10689 + 12573 + dev->readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare); 12574 + 12575 + if (!init) { 12576 + memset(cmpbuf, 0xff, YAFFS_BYTES_PER_CHUNK); 10690 + dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare *)spare); 10691 + 10692 + if(!init) 10693 + { 10694 + memset(cmpbuf,0xff,YAFFS_BYTES_PER_CHUNK); 12577 10695 + init = 1; 12578 10696 + } 12579 10697 + 12580 + if (memcmp(cmpbuf, data, YAFFS_BYTES_PER_CHUNK)) 12581 + return YAFFS_FAIL; 12582 + if (memcmp(cmpbuf, spare, 16)) 12583 + return YAFFS_FAIL; 10698 + if(memcmp(cmpbuf,data,YAFFS_BYTES_PER_CHUNK)) return YAFFS_FAIL; 10699 + if(memcmp(cmpbuf,spare,16)) return YAFFS_FAIL; 10700 + 12584 10701 + 12585 10702 + return YAFFS_OK; … … 12588 10705 +#endif 12589 10706 + 12590 +/* 12591 + * Functions for robustisizing 12592 + */ 12593 + 12594 +static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND) 12595 +{ 12596 + int blockInNAND = chunkInNAND / dev->nChunksPerBlock; 12597 + 12598 + /* Mark the block for retirement */ 12599 + yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1; 12600 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, 12601 + (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND)); 12602 + 12603 + /* TODO: 12604 + * Just do a garbage collection on the affected block 12605 + * then retire the block 12606 + * NB recursion 12607 + */ 12608 +} 10707 +#if 0 10708 +int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND) 10709 +{ 10710 + dev->nBlockErasures++; 10711 + return dev->eraseBlockInNAND(dev,blockInNAND); 10712 +} 10713 + 10714 +int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev) 10715 +{ 10716 + return dev->initialiseNAND(dev); 10717 +} 10718 + 10719 +#endif 10720 + 10721 +#if 0 10722 +static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8 *data, yaffs_Spare *spare,int useReserve) 10723 +{ 10724 + int chunk; 10725 + 10726 + int writeOk = 1; 10727 + int attempts = 0; 10728 + 10729 + unsigned char rbData[YAFFS_BYTES_PER_CHUNK]; 10730 + yaffs_Spare rbSpare; 10731 + 10732 + do{ 10733 + chunk = yaffs_AllocateChunk(dev,useReserve); 10734 + 10735 + if(chunk >= 0) 10736 + { 10737 + 10738 + // First check this chunk is erased... 10739 +#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK 10740 + writeOk = yaffs_CheckChunkErased(dev,chunk); 10741 +#endif 10742 + if(!writeOk) 10743 + { 10744 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d was not erased" TENDSTR),chunk)); 10745 + } 10746 + else 10747 + { 10748 + writeOk = yaffs_WriteChunkToNAND(dev,chunk,data,spare); 10749 + } 10750 + attempts++; 10751 + if(writeOk) 10752 + { 10753 + // Readback & verify 10754 + // If verify fails, then delete this chunk and try again 10755 + // To verify we compare everything except the block and 10756 + // page status bytes. 10757 + // NB We check a raw read without ECC correction applied 10758 + yaffs_ReadChunkFromNAND(dev,chunk,rbData,&rbSpare,0); 10759 + 10760 +#ifndef CONFIG_YAFFS_DISABLE_WRITE_VERIFY 10761 + if(!yaffs_VerifyCompare(data,rbData,spare,&rbSpare)) 10762 + { 10763 + // Didn't verify 10764 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write verify failed on chunk %d" TENDSTR), chunk)); 10765 + 10766 + writeOk = 0; 10767 + } 10768 +#endif 10769 + 10770 + } 10771 + if(writeOk) 10772 + { 10773 + // Copy the data into the write buffer. 10774 + // NB We do this at the end to prevent duplicates in the case of a write error. 10775 + //Todo 10776 + yaffs_HandleWriteChunkOk(dev,chunk,data,spare); 10777 + } 10778 + else 10779 + { 10780 + yaffs_HandleWriteChunkError(dev,chunk); 10781 + } 10782 + } 10783 + 10784 + } while(chunk >= 0 && ! writeOk); 10785 + 10786 + if(attempts > 1) 10787 + { 10788 + T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write required %d attempts" TENDSTR),attempts)); 10789 + dev->nRetriedWrites+= (attempts - 1); 10790 + } 10791 + 10792 + return chunk; 10793 +} 10794 + 10795 +#endif 10796 + 10797 +/// 10798 +// Functions for robustisizing 10799 +// 10800 +// 10801 +#if 0 10802 + 10803 +static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND) 10804 +{ 10805 + // Ding the blockStatus in the first two pages of the block. 10806 + 10807 + yaffs_Spare spare; 10808 + 10809 + memset(&spare, 0xff,sizeof(yaffs_Spare)); 10810 + 10811 + spare.blockStatus = 0; 10812 + 10813 + // TODO change this retirement marking for other NAND types 10814 + yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL , &spare); 10815 + yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1, NULL , &spare); 10816 + 10817 + yaffs_GetBlockInfo(dev,blockInNAND)->blockState = YAFFS_BLOCK_STATE_DEAD; 10818 + dev->nRetiredBlocks++; 10819 +} 10820 + 10821 +#endif 10822 + 10823 +#if 0 10824 +static int yaffs_RewriteBufferedBlock(yaffs_Device *dev) 10825 +{ 10826 + dev->doingBufferedBlockRewrite = 1; 10827 + // 10828 + // Remove erased chunks 10829 + // Rewrite existing chunks to a new block 10830 + // Set current write block to the new block 10831 + 10832 + dev->doingBufferedBlockRewrite = 0; 10833 + 10834 + return 1; 10835 +} 10836 + 10837 +#endif 10838 + 10839 +static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND) 10840 +{ 10841 + int blockInNAND = chunkInNAND/dev->nChunksPerBlock; 10842 + 10843 + // Mark the block for retirement 10844 + yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1; 10845 + T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>>Block %d marked for retirement" TENDSTR),blockInNAND)); 10846 + 10847 + 10848 + //TODO 10849 + // Just do a garbage collection on the affected block then retire the block 10850 + // NB recursion 10851 +} 10852 + 12609 10853 + 12610 10854 +#ifdef NOTYET 12611 +static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND) 12612 +{ 12613 +} 12614 + 12615 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, 12616 + const __u8 * data, 12617 + const yaffs_Spare * spare) 12618 +{ 12619 +} 12620 + 12621 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, 12622 + const yaffs_Spare * spare) 12623 +{ 12624 +} 12625 + 12626 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND) 12627 +{ 12628 + int blockInNAND = chunkInNAND / dev->nChunksPerBlock; 12629 + 12630 + /* Mark the block for retirement */ 12631 + yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1; 12632 + /* Delete the chunk */ 12633 + yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__); 12634 +} 12635 + 12636 +static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1, 12637 + const yaffs_Spare * s0, const yaffs_Spare * s1) 12638 +{ 12639 + 12640 + if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 || 12641 + s0->tagByte0 != s1->tagByte0 || 12642 + s0->tagByte1 != s1->tagByte1 || 12643 + s0->tagByte2 != s1->tagByte2 || 12644 + s0->tagByte3 != s1->tagByte3 || 12645 + s0->tagByte4 != s1->tagByte4 || 12646 + s0->tagByte5 != s1->tagByte5 || 12647 + s0->tagByte6 != s1->tagByte6 || 12648 + s0->tagByte7 != s1->tagByte7 || 12649 + s0->ecc1[0] != s1->ecc1[0] || 12650 + s0->ecc1[1] != s1->ecc1[1] || 12651 + s0->ecc1[2] != s1->ecc1[2] || 12652 + s0->ecc2[0] != s1->ecc2[0] || 12653 + s0->ecc2[1] != s1->ecc2[1] || s0->ecc2[2] != s1->ecc2[2]) { 12654 + return 0; 12655 + } 10855 +static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND) 10856 +{ 10857 +} 10858 + 10859 +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare) 10860 +{ 10861 +} 10862 + 10863 +static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_Spare *spare) 10864 +{ 10865 +} 10866 + 10867 +static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND) 10868 +{ 10869 + int blockInNAND = chunkInNAND/dev->nChunksPerBlock; 10870 + 10871 + // Mark the block for retirement 10872 + yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1; 10873 + // Delete the chunk 10874 + yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__); 10875 +} 10876 + 10877 + 10878 + 10879 + 10880 +static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1) 10881 +{ 10882 + 10883 + 10884 + if( memcmp(d0,d1,YAFFS_BYTES_PER_CHUNK) != 0 || 10885 + s0->tagByte0 != s1->tagByte0 || 10886 + s0->tagByte1 != s1->tagByte1 || 10887 + s0->tagByte2 != s1->tagByte2 || 10888 + s0->tagByte3 != s1->tagByte3 || 10889 + s0->tagByte4 != s1->tagByte4 || 10890 + s0->tagByte5 != s1->tagByte5 || 10891 + s0->tagByte6 != s1->tagByte6 || 10892 + s0->tagByte7 != s1->tagByte7 || 10893 + s0->ecc1[0] != s1->ecc1[0] || 10894 + s0->ecc1[1] != s1->ecc1[1] || 10895 + s0->ecc1[2] != s1->ecc1[2] || 10896 + s0->ecc2[0] != s1->ecc2[0] || 10897 + s0->ecc2[1] != s1->ecc2[1] || 10898 + s0->ecc2[2] != s1->ecc2[2] ) 10899 + { 10900 + return 0; 10901 + } 12656 10902 + 12657 10903 + return 1; 12658 10904 +} 12659 +#endif /* NOTYET */ 12660 + 12661 +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev, 12662 + int chunkInNAND, 12663 + const __u8 * data, 12664 + const yaffs_ExtendedTags * 12665 + eTags) 10905 +#endif /* NOTYET */ 10906 + 10907 +#if 0 10908 +typedef struct 10909 +{ 10910 + 10911 + unsigned validMarker0; 10912 + unsigned chunkUsed; // Status of the chunk: used or unused 10913 + unsigned objectId; // If 0 then this is not part of an object (unused) 10914 + unsigned chunkId; // If 0 then this is a header 10915 + unsigned byteCount; // Only valid for data chunks 10916 + // The following stuff only has meaning when we read 10917 + yaffs_ECCResult eccResult; // Only valid when we read. 10918 + unsigned blockBad; // Only valid on reading 10919 + 10920 + // YAFFS 1 stuff 10921 + unsigned chunkDeleted; // The chunk is marked deleted 10922 + unsigned serialNumber; // Yaffs1 2-bit serial number 10923 + 10924 + // YAFFS2 stuff 10925 + unsigned sequenceNumber; // The sequence number of this block 10926 + 10927 + unsigned validMarker1; 10928 + 10929 +} yaffs_ExtendedTags; 10930 + 10931 + 10932 +typedef struct 10933 +{ 10934 + unsigned chunkId:20; 10935 + unsigned serialNumber:2; 10936 + unsigned byteCount:10; 10937 + unsigned objectId:18; 10938 + unsigned ecc:12; 10939 + unsigned unusedStuff:2; 10940 +} yaffs_Tags; 10941 + 10942 + 10943 +#endif 10944 + 10945 +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *eTags) 12666 10946 +{ 12667 10947 + yaffs_Spare spare; 12668 + yaffs_Tags tags; 12669 + 10948 + yaffs_Tags tags; 10949 + 12670 10950 + yaffs_SpareInitialise(&spare); 12671 + 12672 + if (eTags->chunkDeleted) { 10951 + 10952 + if(eTags->chunkDeleted) 10953 + { 12673 10954 + spare.pageStatus = 0; 12674 + } else { 10955 + } 10956 + else 10957 + { 12675 10958 + tags.objectId = eTags->objectId; 12676 10959 + tags.chunkId = eTags->chunkId; 12677 10960 + tags.byteCount = eTags->byteCount; 12678 10961 + tags.serialNumber = eTags->serialNumber; 12679 + 12680 + if (!dev->useNANDECC && data) { 12681 + yaffs_CalcECC(data, &spare); 12682 + } 12683 + yaffs_LoadTagsIntoSpare(&spare, &tags); 12684 + 12685 + } 12686 + 12687 + return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare); 12688 +} 12689 + 12690 +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, 12691 + int chunkInNAND, 12692 + __u8 * data, 12693 + yaffs_ExtendedTags * eTags) 10962 + 10963 +// NCB 10964 + if (!dev->useNANDECC && data) 10965 + { 10966 + yaffs_CalcECC(data,&spare); 10967 + } 10968 + 10969 +// /NCB 10970 + yaffs_LoadTagsIntoSpare(&spare,&tags); 10971 + 10972 + } 10973 + 10974 + return yaffs_WriteChunkToNAND(dev,chunkInNAND,data,&spare); 10975 +} 10976 + 10977 + 10978 +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *eTags) 12694 10979 +{ 12695 10980 + … … 12697 10982 + yaffs_Tags tags; 12698 10983 + yaffs_ECCResult eccResult; 12699 + 12700 + static yaffs_Spare spareFF; 12701 + static int init; 12702 + 12703 + if (!init) { 12704 + memset(&spareFF, 0xFF, sizeof(spareFF)); 12705 + init = 1; 12706 + } 12707 + 12708 + if (yaffs_ReadChunkFromNAND 12709 + (dev, chunkInNAND, data, &spare, &eccResult, 1)) { 12710 + /* eTags may be NULL */ 10984 + 10985 +// NCB 10986 + static yaffs_Spare spareFF; 10987 + static int init; 10988 + 10989 + if(!init) 10990 + { 10991 + memset(&spareFF,0xFF,sizeof(spareFF)); 10992 + init = 1; 10993 + } 10994 +// /NCB 10995 + if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,data,&spare,&eccResult,1)) 10996 + { 10997 +// added NCB - eTags may be NULL 12711 10998 + if (eTags) { 12712 10999 + 12713 + int deleted = 12714 + (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0; 12715 + 12716 + eTags->chunkDeleted = deleted; 12717 + eTags->eccResult = eccResult; 12718 + eTags->blockBad = 0; /* We're reading it */ 12719 + /* therefore it is not a bad block */ 12720 + eTags->chunkUsed = 12721 + (memcmp(&spareFF, &spare, sizeof(spareFF)) != 12722 + 0) ? 1 : 0; 12723 + 12724 + if (eTags->chunkUsed) { 12725 + yaffs_GetTagsFromSpare(dev, &spare, &tags); 12726 + 12727 + eTags->objectId = tags.objectId; 12728 + eTags->chunkId = tags.chunkId; 12729 + eTags->byteCount = tags.byteCount; 12730 + eTags->serialNumber = tags.serialNumber; 12731 + } 12732 + } 12733 + 12734 + return YAFFS_OK; 12735 + } else { 11000 + int deleted = (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0; 11001 + 11002 + yaffs_GetTagsFromSpare(dev,&spare,&tags); 11003 + 11004 + eTags->chunkDeleted = deleted; 11005 + eTags->objectId = tags.objectId; 11006 + eTags->chunkId = tags.chunkId; 11007 + eTags->byteCount = tags.byteCount; 11008 + eTags->serialNumber = tags.serialNumber; 11009 + eTags->eccResult = eccResult; 11010 + eTags->blockBad = 0; // We're reading it therefore it is not a bad block 11011 + 11012 +// NCB added 18/2/2005 11013 + eTags->chunkUsed = (memcmp(&spareFF,&spare,sizeof(spareFF)) != 0) ? 1:0; 11014 + } 11015 + 11016 + return YAFFS_OK; 11017 + } 11018 + else 11019 + { 12736 11020 + return YAFFS_FAIL; 12737 11021 + } 12738 11022 +} 12739 11023 + 12740 +int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, 12741 + int blockInNAND) 11024 +int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockInNAND) 12742 11025 +{ 12743 11026 + 12744 11027 + yaffs_Spare spare; 12745 11028 + 12746 + memset(&spare, 0xff, sizeof(yaffs_Spare)); 12747 + 12748 + spare.blockStatus = 'Y'; 12749 + 12750 + yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL, 12751 + &spare); 12752 + yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1, 12753 + NULL, &spare); 12754 + 11029 + memset(&spare, 0xff,sizeof(yaffs_Spare)); 11030 + 11031 + spare.blockStatus = 0; 11032 + 11033 + yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL , &spare); 11034 + yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1, NULL , &spare); 11035 + 12755 11036 + return YAFFS_OK; 12756 + 12757 +} 12758 + 12759 +int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, 12760 + int blockNo, yaffs_BlockState * 12761 + state, 12762 + int *sequenceNumber) 12763 +{ 12764 + 12765 + yaffs_Spare spare0, spare1; 12766 + static yaffs_Spare spareFF; 12767 + static int init; 12768 + yaffs_ECCResult dummy; 12769 + 12770 + if (!init) { 12771 + memset(&spareFF, 0xFF, sizeof(spareFF)); 12772 + init = 1; 12773 + } 12774 + 12775 + *sequenceNumber = 0; 12776 + 12777 + yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock, NULL, 12778 + &spare0, &dummy, 1); 12779 + yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock + 1, NULL, 12780 + &spare1, &dummy, 1); 12781 + 12782 + if (yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7) 12783 + *state = YAFFS_BLOCK_STATE_DEAD; 12784 + else if (memcmp(&spareFF, &spare0, sizeof(spareFF)) == 0) 12785 + *state = YAFFS_BLOCK_STATE_EMPTY; 12786 + else 12787 + *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; 12788 + 12789 + return YAFFS_OK; 12790 +} 12791 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.h 12792 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.h 1970-01-01 01:00:00.000000000 +0100 12793 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.h 2006-11-25 00:15:32.000000000 +0100 12794 @@ -0,0 +1,40 @@ 11037 + 11038 +} 11039 + 11040 + 11041 +int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) 11042 +{ 11043 + 11044 + yaffs_Spare spare0,spare1; 11045 + static yaffs_Spare spareFF; 11046 + static int init; 11047 + yaffs_ECCResult dummy; 11048 + 11049 + if(!init) 11050 + { 11051 + memset(&spareFF,0xFF,sizeof(spareFF)); 11052 + init = 1; 11053 + } 11054 + 11055 + *sequenceNumber = 0; 11056 + 11057 + yaffs_ReadChunkFromNAND(dev,blockNo * dev->nChunksPerBlock,NULL,&spare0,&dummy,1); 11058 + yaffs_ReadChunkFromNAND(dev,blockNo * dev->nChunksPerBlock + 1,NULL,&spare1,&dummy,1); 11059 + 11060 + if(yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7) 11061 + *state = YAFFS_BLOCK_STATE_DEAD; 11062 + else if(memcmp(&spareFF,&spare0,sizeof(spareFF)) == 0) 11063 + *state = YAFFS_BLOCK_STATE_EMPTY; 11064 + else 11065 + *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; 11066 + 11067 + return YAFFS_OK; 11068 +} 11069 + 11070 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h 11071 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h 1970-01-01 01:00:00.000000000 +0100 11072 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h 2006-12-10 03:57:50.000000000 +0100 11073 @@ -0,0 +1,30 @@ 12795 11074 +/* 12796 11075 + * YAFFS: Yet another FFS. A NAND-flash specific file system. … … 12805 11084 + * published by the Free Software Foundation. 12806 11085 + * 12807 + * $Id: yaffs_tagscompat.h,v 1. 2 2005/08/11 02:33:03 martyExp $11086 + * $Id: yaffs_tagscompat.h,v 1.1 2004/11/03 08:14:07 charles Exp $ 12808 11087 + */ 12809 11088 + 12810 +/ * This provides a ramdisk under yaffs.12811 + *NB this is not intended for NAND emulation.12812 + *Use this with dev->useNANDECC enabled, then ECC overheads are not required.12813 + */11089 +// This provides a rma disk under yaffs. 11090 +// NB this is not intended for NAND emulation. 11091 +// Use this with dev->useNANDECC enabled, then ECC overheads are not required. 11092 + 12814 11093 +#ifndef __YAFFS_TAGSCOMPAT_H__ 12815 11094 +#define __YAFFS_TAGSCOMPAT_H__ 12816 11095 + 11096 + 12817 11097 +#include "yaffs_guts.h" 12818 +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev, 12819 + int chunkInNAND, 12820 + const __u8 * data, 12821 + const yaffs_ExtendedTags * 12822 + tags); 12823 +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, 12824 + int chunkInNAND, 12825 + __u8 * data, 12826 + yaffs_ExtendedTags * 12827 + tags); 12828 +int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, 12829 + int blockNo); 12830 +int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, 12831 + int blockNo, yaffs_BlockState * 12832 + state, int *sequenceNumber); 12833 + 12834 +#endif 12835 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.c 12836 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.c 1970-01-01 01:00:00.000000000 +0100 12837 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.c 2006-11-25 00:15:32.000000000 +0100 12838 @@ -0,0 +1,31 @@ 11098 +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags); 11099 +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags); 11100 +int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); 11101 +int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber); 11102 + 11103 +#endif 11104 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c 11105 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c 1970-01-01 01:00:00.000000000 +0100 11106 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c 2006-12-10 03:57:50.000000000 +0100 11107 @@ -0,0 +1,35 @@ 12839 11108 + 12840 11109 +/* … … 12850 11119 + * published by the Free Software Foundation. 12851 11120 + * 12852 + * $Id: yaffs_tagsvalidity.c,v 1. 2 2005/08/11 02:33:03 martyExp $11121 + * $Id: yaffs_tagsvalidity.c,v 1.1 2005/04/29 18:09:16 charles Exp $ 12853 11122 + */ 11123 +//yaffs_tagsvalidity.c 12854 11124 + 12855 11125 +#include "yaffs_tagsvalidity.h" 12856 11126 + 12857 +void yaffs_InitialiseTags(yaffs_ExtendedTags * tags) 12858 +{ 12859 + memset(tags, 0, sizeof(yaffs_ExtendedTags)); 11127 + 11128 + 11129 +void yaffs_InitialiseTags(yaffs_ExtendedTags *tags) 11130 +{ 11131 + memset(tags,0,sizeof(yaffs_ExtendedTags)); 12860 11132 + tags->validMarker0 = 0xAAAAAAAA; 12861 11133 + tags->validMarker1 = 0x55555555; 12862 11134 +} 12863 11135 + 12864 +int yaffs_ValidateTags(yaffs_ExtendedTags * tags)11136 +int yaffs_ValidateTags(yaffs_ExtendedTags *tags) 12865 11137 +{ 12866 11138 + return (tags->validMarker0 == 0xAAAAAAAA && … … 12868 11140 + 12869 11141 +} 12870 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.h 12871 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.h 1970-01-01 01:00:00.000000000 +0100 12872 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.h 2006-11-25 00:15:32.000000000 +0100 12873 @@ -0,0 +1,25 @@ 11142 + 11143 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h 11144 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h 1970-01-01 01:00:00.000000000 +0100 11145 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h 2006-12-10 03:57:50.000000000 +0100 11146 @@ -0,0 +1,27 @@ 12874 11147 + 12875 11148 +/* … … 12885 11158 + * published by the Free Software Foundation. 12886 11159 + * 12887 + * $Id: yaffs_tagsvalidity.h,v 1. 2 2005/08/11 02:33:03 martyExp $11160 + * $Id: yaffs_tagsvalidity.h,v 1.1 2005/04/29 18:09:16 charles Exp $ 12888 11161 + */ 12889 11162 +//yaffs_tagsvalidity.h 12890 11163 + 11164 + 12891 11165 +#ifndef __YAFFS_TAGS_VALIDITY_H__ 12892 11166 +#define __YAFFS_TAGS_VALIDITY_H__ … … 12894 11168 +#include "yaffs_guts.h" 12895 11169 + 12896 +void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); 12897 +int yaffs_ValidateTags(yaffs_ExtendedTags * tags); 12898 +#endif 12899 diff -NaurB linux-2.6.18.2/fs/yaffs2/yportenv.h linux-2.6.18.2.patched/fs/yaffs2/yportenv.h 12900 --- linux-2.6.18.2/fs/yaffs2/yportenv.h 1970-01-01 01:00:00.000000000 +0100 12901 +++ linux-2.6.18.2.patched/fs/yaffs2/yportenv.h 2006-11-25 00:15:32.000000000 +0100 11170 +void yaffs_InitialiseTags(yaffs_ExtendedTags *tags); 11171 +int yaffs_ValidateTags(yaffs_ExtendedTags *tags); 11172 +#endif 11173 + 11174 diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h 11175 --- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h 1970-01-01 01:00:00.000000000 +0100 11176 +++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h 2006-12-10 03:57:50.000000000 +0100 12902 11177 @@ -0,0 +1,165 @@ 12903 11178 +/* … … 12918 11193 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. 12919 11194 + * 12920 + * $Id: yportenv.h,v 1. 11 2006/05/21 09:39:12charles Exp $11195 + * $Id: yportenv.h,v 1.6 2005/07/31 00:26:57 charles Exp $ 12921 11196 + * 12922 11197 + */ 12923 + 11198 + 12924 11199 +#ifndef __YPORTENV_H__ 12925 11200 +#define __YPORTENV_H__ 12926 11201 + 11202 + 12927 11203 +#if defined CONFIG_YAFFS_WINCE 12928 11204 + … … 12931 11207 +#elif defined __KERNEL__ 12932 11208 + 12933 + #include "moduleconfig.h"12934 + 12935 +/ * Linux kernel */11209 + 11210 + 11211 +// Linux kernel 12936 11212 +#include <linux/config.h> 12937 11213 +#include <linux/kernel.h> … … 12940 11216 +#include <linux/string.h> 12941 11217 +#include <linux/slab.h> 12942 +#include <linux/vmalloc.h>12943 11218 + 12944 11219 +#define YCHAR char … … 12956 11231 +#define YAFFS_LOSTNFOUND_PREFIX "obj" 12957 11232 + 12958 +/ * #define YPRINTF(x) printk x */11233 +//#define YPRINTF(x) printk x 12959 11234 +#define YMALLOC(x) kmalloc(x,GFP_KERNEL) 12960 11235 +#define YFREE(x) kfree(x) 12961 +#define YMALLOC_ALT(x) vmalloc(x)12962 +#define YFREE_ALT(x) vfree(x)12963 +#define YMALLOC_DMA(x) YMALLOC(x)12964 +12965 +// KR - added for use in scan so processes aren't blocked indefinitely.12966 +#define YYIELD() schedule()12967 11236 + 12968 11237 +#define YAFFS_ROOT_MODE 0666 … … 12984 11253 +#define TOUT(p) printk p 12985 11254 + 11255 + 12986 11256 +#elif defined CONFIG_YAFFS_DIRECT 12987 11257 + 12988 +/ * Direct interface */11258 +// Direct interface 12989 11259 +#include "ydirectenv.h" 12990 11260 + 12991 11261 +#elif defined CONFIG_YAFFS_UTIL 12992 11262 + 12993 +/ * Stuff for YAFFS utilities */11263 +// Stuff for YAFFS utilities 12994 11264 + 12995 11265 +#include "stdlib.h" … … 13001 11271 +#define YMALLOC(x) malloc(x) 13002 11272 +#define YFREE(x) free(x) 13003 +#define YMALLOC_ALT(x) malloc(x) 13004 +#define YFREE_ALT(x) free(x) 11273 + 13005 11274 + 13006 11275 +#define YCHAR char … … 13015 11284 +#define Y_INLINE inline 13016 11285 + 13017 +/* #define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s)) */ 13018 +/* #define YALERT(s) YINFO(s) */ 11286 +//#define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s)) 11287 +//#define YALERT(s) YINFO(s) 11288 + 13019 11289 + 13020 11290 +#define TENDSTR "\n" … … 13022 11292 +#define TOUT(p) printf p 13023 11293 + 11294 + 13024 11295 +#define YAFFS_LOSTNFOUND_NAME "lost+found" 13025 11296 +#define YAFFS_LOSTNFOUND_PREFIX "obj" 13026 +/* #define YPRINTF(x) printf x */ 11297 +//#define YPRINTF(x) printf x 11298 + 13027 11299 + 13028 11300 +#define YAFFS_ROOT_MODE 0666 … … 13033 11305 + 13034 11306 +#else 13035 +/ * Should have specified a configuration type */11307 +// Should have specified a configuration type 13036 11308 +#error Unknown configuration 13037 11309 + 13038 +#endif 11310 +#endif 11311 + 13039 11312 + 13040 11313 +extern unsigned yaffs_traceMask; … … 13055 11328 +#define YAFFS_TRACE_SCAN_DEBUG 0x00002000 13056 11329 +#define YAFFS_TRACE_MTD 0x00004000 13057 +#define YAFFS_TRACE_CHECKPOINT 0x0000800013058 11330 +#define YAFFS_TRACE_ALWAYS 0x40000000 13059 11331 +#define YAFFS_TRACE_BUG 0x80000000 13060 11332 + 13061 +#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ERROR)) TOUT(p);} while(0) 11333 +#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ERROR)) TOUT(p);} while(0) 11334 + 13062 11335 + 13063 11336 +#ifndef CONFIG_YAFFS_WINCE … … 13066 11339 + 13067 11340 +#endif 11341 + 11342 +
Note:
See TracChangeset
for help on using the changeset viewer.
