From d3a46536d1812c81e1c494235ce8f7e25ebb0e1b Mon Sep 17 00:00:00 2001
From: charles
Date: Tue, 14 Jan 2003 23:15:29 +0000
Subject: [PATCH] *** empty log message ***
---
Documentation/yaffs2.html | 40 +-
mtdemul/nandemul.c | 2 +-
snMakefile | 6 +-
utils/Makefile | 2 +-
utils/mkyaffs | Bin 16029 -> 16029 bytes
wince/yaffsfsd.c | 1137 +++++++++++++++++++++++--------------
yaffs_fileem.c | 2 +-
yaffs_fs.c | 51 +-
yaffs_guts.c | 982 +++++++++++++++++++++-----------
yaffs_guts.h | 106 ++--
yaffs_mtdif.c | 28 +-
yaffsdev.c | 76 ++-
yaffsdev.proj | Bin 53248 -> 53248 bytes
yportenv.h | 48 +-
14 files changed, 1662 insertions(+), 818 deletions(-)
diff --git a/Documentation/yaffs2.html b/Documentation/yaffs2.html
index e83dcc6..9014465 100644
--- a/Documentation/yaffs2.html
+++ b/Documentation/yaffs2.html
@@ -7,7 +7,7 @@
-
+
YAFFS2
@@ -224,7 +224,7 @@ sequence Id order) rather than in their order on the media. This
implies that at start up, the blocks must be read and their block
sequence determined.
Performance
-These numbers are indicative of relative performance. These only
+
These numbers are indicative of relative performance. These only
apply to the NAND data transfer and do not include other overheads.
As an example, read/write cycle times of 100nS are used (though
NAND can typically do 50nS), "seek time" of 10uS and
@@ -747,7 +747,41 @@ transfer time relative to an 8-bit bus.
-$Id: yaffs2.html,v 1.1 2002-11-26 01:15:37 charles Exp $
+MTD Interface
+As mentioned before, YAFFS2 requires a chunk-size of at least 1kB
+to get a large enough spare area to support the increased size of the
+tags. This is not really a disadvantage, but should rather be viewed
+as an opportunity to exploit the NAND hardware more effectively. In
+particular:
+
+ Newer, larger, NAND with 2kB pages can be used in chunks of
+ 2kB. Keeping the relationship of one chunk per page improves
+ robustness and performance (rather than say trying to "fake"
+ 512byte pages). A block comprises 64x2kB pages.
+ Some devices have 512byte pages, but are arranged as multiple
+ "bit planes" which can be programmed and erased in
+ parallel. For example, the Samsung K9K1G08U0M can support 4
+ simultaneous operations. YAFFS2 can exploit this by using 2kB chunks
+ by using groups of 4 pages - one on each bitplane. Virtual blocks
+ would be built which comprise 32x2kB chunks.
+
+To this end, yaffs_guts is being re-crafted to support arbitrary
+chunk size (power of 2, >= 1024), with arbitrary block size.
+Currently, YAFFS also makes some other assumptions which will need
+to be changed:
+
+ Spare layout. Might need to be changed. This is relatively
+ simple to shuffle around.
+ Bad block detection. Currently YAFFS uses the SmartMedia
+ detection (checks first two pages for bad block markers). Needs to
+ be more flexible. eg. Sandisk/Toshiba MLC parts mark the last two
+ pages in a block.
+ ECC was on this list, but now seems flexible enough. Thanx
+ Thomas.
+
+Some of these differences can be absorbed in the yaffs_mtd layer.
+Some will need to be handles inside the mtd itself.
+$Id: yaffs2.html,v 1.2 2003-01-14 23:15:41 charles Exp $
diff --git a/mtdemul/nandemul.c b/mtdemul/nandemul.c
index 12fe39d..52a6a64 100644
--- a/mtdemul/nandemul.c
+++ b/mtdemul/nandemul.c
@@ -30,7 +30,7 @@
#include
#include
#include
-
+#include
#define T(x) printk x
#define ALLOCATE(x) kmalloc(x,GFP_KERNEL)
diff --git a/snMakefile b/snMakefile
index c27a5cb..cbd34df 100644
--- a/snMakefile
+++ b/snMakefile
@@ -1,6 +1,6 @@
#########################################################
# Makefile auto generated by Cygnus Source Navigator.
-# Target: yaffsdev_disk Date: Nov 26 2002 Time: 01:05:25 PM
+# Target: yaffsdev_disk Date: Dec 18 2002 Time: 04:44:42 PM
#
@@ -70,9 +70,9 @@ yaffsdev: $(yaffsdev_disk_OBJECTS)
nand_ecc.o: /opt/yaffs/yportenv.h
-yaffs_fileem.o: /opt/2.4.18/linux/include/linux/stat.h /opt/2.4.18/linux/include/linux/types.h /usr/include/fcntl.h /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h /usr/include/unistd.h /opt/yaffs/yaffs_fileem.h /opt/yaffs/yaffs_guts.h /opt/yaffs/yaffsinterface.h
+yaffs_fileem.o: /opt/yaffs/yaffs_fileem.h /opt/yaffs/yaffs_guts.h /opt/yaffs/yaffsinterface.h
yaffs_guts.o: /opt/yaffs/yaffs_guts.h /opt/yaffs/yaffsinterface.h /opt/yaffs/yportenv.h
-yaffsdev.o: /usr/include/fcntl.h /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h /usr/include/unistd.h /opt/yaffs/yaffs_fileem.h /opt/yaffs/yaffs_guts.h /opt/yaffs/yaffs_nandemul.h /opt/yaffs/yaffsinterface.h /opt/yaffs/yportenv.h
+yaffsdev.o: /opt/yaffs/yaffs_fileem.h /opt/yaffs/yaffs_guts.h /opt/yaffs/yaffs_nandemul.h /opt/yaffs/yaffsinterface.h /opt/yaffs/yportenv.h
clean:
rm -f *.o
diff --git a/utils/Makefile b/utils/Makefile
index 1e0d432..f4f94c0 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -16,7 +16,7 @@
KERNELDIR = /usr/src/kernel-headers-2.4.18
-CFLAGS = -I$(KERNELDIR)/include -I.. -O2 -Wall
+CFLAGS = -I$(KERNELDIR)/include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL
CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
diff --git a/utils/mkyaffs b/utils/mkyaffs
index 5ed31f26b564af6b8a6523109ab970bf6083aa4f..28870e6b1680b473b66eae66a0c0a3652651968b 100755
GIT binary patch
delta 34
pcmbPRJGXYjM@~^Q1tS9kV_gG7T|*NEBV#K=Q!5k0&1_uLO#r^~34s6r
delta 34
ocmbPRJGXYjM@~^w1tS9kBV9uvGFC7!urf5ZGBDfB#x>mp0KSU}dH?_b
diff --git a/wince/yaffsfsd.c b/wince/yaffsfsd.c
index dc64c1a..7e202bf 100644
--- a/wince/yaffsfsd.c
+++ b/wince/yaffsfsd.c
@@ -1,6 +1,6 @@
/*
* YAFFS: Yet another FFS. A NAND-flash specific file system.
- * yaffsfsd.c: The FSD layer for the WinCE version of YAFFS.
+ * ynandif.c: NAND interface functions for the WinCE port of YAFFS.
*
* Copyright (C) 2002 Trimble Navigation Ltd.
*
@@ -18,27 +18,42 @@
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * $Id: yaffsfsd.c,v 1.1 2002-11-08 07:30:00 charles Exp $
+ * Acknowledgements:
+ * Various clean-ups and WinCE4 support by Steve Fogle
+ * $Id: yaffsfsd.c,v 1.2 2003-01-14 23:15:41 charles Exp $
*/
#include
#include
#include
-#include
+#include
+//slf021104b begin
+#include
+//slf021104b end
#define MAX_WIN_FILE 200
#define YFSD_NAME_LENGTH 128
#define YFSD_FULL_PATH_NAME_SIZE 500
-
+
#define YFSD_DISK_NAME L"Disk"
-#define YFSD_BOOT_NAME L"Boot"
+#define YFSD_BOOT_NAME L"Boot"
#define PARTITION_START_NUMBER (1280)
-#define MSGSTATE 1
+//#define MSGSTATE 1
+#define MSGSTATE 0
//#define DISABLE_BOOT_PARTITION
-
-unsigned yaffs_traceMask=0xffffffff;
+//slf021105a begin
+// Define DO_PARTITION_TABLE to cause the partition table
+// information to be retrieved from the block driver.
+//#define DO_PARTITION_TABLE
+// How many partitions the disk might have. 2 gives
+// space for the "Disk" and "Boot" partitions.
+#define MAXPARTITIONS (2)
+//slf021105a end
+
+//unsigned yaffs_traceMask=0xffffffff;
+unsigned yaffs_traceMask=0;
typedef struct
@@ -59,10 +74,13 @@ typedef struct
yaffs_Object *obj;
DWORD offset;
BOOL isopen;
- BOOL writePermitted;
BOOL dirty;
WCHAR *fullName;
yfsd_Volume *myVolume;
+ BOOL writePermitted;
+ BOOL readPermitted;
+ BOOL shareRead;
+ BOOL shareWrite;
} yfsd_WinFile;
@@ -92,9 +110,11 @@ typedef struct
#include
-
-static yfsd_Volume disk_volume;
-static yfsd_Volume boot_volume;
+//slf021105a begin
+//static yfsd_Volume disk_volume;
+//static yfsd_Volume boot_volume;
+static yfsd_Volume * disk_volumes[MAXPARTITIONS];
+//slf021105a end;
static CRITICAL_SECTION yaffsLock;
static CRITICAL_SECTION winFileLock;
@@ -192,7 +212,10 @@ yfsd_WinFile * yfsd_GetWinFile(void)
if(!yfsd_winFile[i].isopen)
{
yfsd_winFile[i].isopen = 1;
- yfsd_winFile[i].writePermitted = 0;
+ yfsd_winFile[i].writePermitted = 0;
+ yfsd_winFile[i].readPermitted = 0;
+ yfsd_winFile[i].shareRead = 0;
+ yfsd_winFile[i].shareWrite = 0;
yfsd_winFile[i].dirty = 0;
yfsd_winFile[i].fullName = NULL;
yfsd_winFile[i].obj = NULL;
@@ -238,19 +261,47 @@ void yfsd_FlushAllFiles(void)
if(yfsd_winFile[i].isopen &&
yfsd_winFile[i].obj)
{
- yaffs_FlushFile(yfsd_winFile[i].obj);
+ yaffs_FlushFile(yfsd_winFile[i].obj,1);
}
}
yfsd_UnlockWinFiles();
yfsd_UnlockYAFFS();
-}
+}
+
+//slf021104d begin
+//////////////////////////////////////////////////////////////////////
+// Search through winFiles to see if any are open.
+
+BOOL yfsd_FilesOpen(void)
+{
+ int i;
+ BOOL rval;
+ RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));
+
+ yfsd_LockWinFiles();
+ for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)
+ {
+ if(yfsd_winFile[i].isopen)
+ {
+ rval = TRUE;
+ break;
+ }
+ }
+ yfsd_UnlockWinFiles();
+ return rval;
+}
+//slf021104d end
PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
{
- // todo check for bounds
- wcscpy(fpn,L"\\");
- wcscat(fpn,vol->volName);
+ // todo check for bounds
+ //slf021104b begin
+ //volName already has the initial backslash if it needs it.
+ //wcscpy(fpn,L"\\");
+ //wcscat(fpn,vol->volName);
+ wcscpy(fpn,vol->volName);
+ //slf021104b end
if(pathName[0] != '\\')
{
wcscat(fpn,L"\\");
@@ -263,7 +314,7 @@ PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
// FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
-
+
void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
{
@@ -347,15 +398,15 @@ void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
}
-
-
-// Minimal name test for now
-BOOL yfsd_NameIsValid (const char *name)
-{
- int length = strlen(name);
-
- return (length > 0 && length <= YFSD_NAME_LENGTH);
-
+
+
+// Minimal name test for now
+BOOL yfsd_NameIsValid (const char *name)
+{
+ int length = strlen(name);
+
+ return (length > 0 && length <= YFSD_NAME_LENGTH);
+
}
// File attributes:
@@ -375,58 +426,58 @@ BOOL yfsd_NameIsValid (const char *name)
//
//
// in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
-
-// The following are valid ones we get presented with,
-// but must filter out the stuff we don't unserstand
-//#define FILE_ATTRIBUTE_READONLY 0x00000001
-//#define FILE_ATTRIBUTE_HIDDEN 0x00000002
-//#define FILE_ATTRIBUTE_SYSTEM 0x00000004
-//#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
-//#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
-//#define FILE_ATTRIBUTE_INROM 0x00000040
-//#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
-//#define FILE_ATTRIBUTE_NORMAL 0x00000080
-//#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
-//#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
-//#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
-//#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
-//#define FILE_ATTRIBUTE_OFFLINE 0x00001000
-//#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
-//#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
-//#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
-
-
-BOOL yfsd_CheckValidAttributes(DWORD attribs)
-{
-
- RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
-
-#if 0
- // If NORMAL, then nothing else
- if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
- return FALSE;
- if(attribs == FILE_ATTRIBUTE_NORMAL)
- return TRUE;
-#endif
- // Check that the bits are in the valid set
- if(attribs & ~(0x3FE7))
- return FALSE;
-
- return TRUE;
-
+
+// The following are valid ones we get presented with,
+// but must filter out the stuff we don't unserstand
+//#define FILE_ATTRIBUTE_READONLY 0x00000001
+//#define FILE_ATTRIBUTE_HIDDEN 0x00000002
+//#define FILE_ATTRIBUTE_SYSTEM 0x00000004
+//#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
+//#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
+//#define FILE_ATTRIBUTE_INROM 0x00000040
+//#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
+//#define FILE_ATTRIBUTE_NORMAL 0x00000080
+//#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
+//#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
+//#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+//#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
+//#define FILE_ATTRIBUTE_OFFLINE 0x00001000
+//#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
+//#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+//#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
+
+
+BOOL yfsd_CheckValidAttributes(DWORD attribs)
+{
+
+ RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
+
+#if 0
+ // If NORMAL, then nothing else
+ if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
+ return FALSE;
+ if(attribs == FILE_ATTRIBUTE_NORMAL)
+ return TRUE;
+#endif
+ // Check that the bits are in the valid set
+ if(attribs & ~(0x3FE7))
+ return FALSE;
+
+ return TRUE;
+
}
DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
{
DWORD result;
- result = obj->st_mode &
- (FILE_ATTRIBUTE_READONLY |
- FILE_ATTRIBUTE_ARCHIVE |
- FILE_ATTRIBUTE_HIDDEN |
+ result = obj->st_mode &
+ (FILE_ATTRIBUTE_READONLY |
+ FILE_ATTRIBUTE_ARCHIVE |
+ FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM);
-
- if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
+
+ if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
if(result & ~FILE_ATTRIBUTE_NORMAL)
{
@@ -436,7 +487,7 @@ DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
{
result = FILE_ATTRIBUTE_NORMAL;
}
-
+
return result;
}
@@ -496,7 +547,7 @@ yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *p
RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
// start at the root of this device
- current = yaffs_Root(device);
+ current = yaffs_Root(device);
*processed = '\0';
do
@@ -553,8 +604,14 @@ yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
{
- RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
- vol->volName = volName;
+ //slf021104b Begin
+ WCHAR szName[MAX_PATH];
+ DWORD dwAvail;
+ //slf021104b end
+ RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
+ //slf021104b Begin filled in later.
+ //vol->volName = volName;
+ //slf021104b end
yfsd_LockYAFFS();
@@ -568,7 +625,8 @@ BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock,
vol->dev.initialiseNAND = ynandif_InitialiseNAND;
vol->dev.startBlock = startBlock;
if (endBlock != -1)
- vol->dev.endBlock = endBlock;
+ vol->dev.endBlock = endBlock;
+ vol->dev.nShortOpCaches = 10; // a nice number of caches.
// nBlocks is set the total size of the disk, not the partition
// vol->dev.nBlocks = endBlock - startBlock + 1;
@@ -611,11 +669,51 @@ BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock,
yfsd_UnlockYAFFS();
vol->isMounted = 1;
-
- vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
+
+ //slf021104b begin
+ //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
+ // If the caller passed a volume name use it.
+ if (volName[0])
+ wcscpy( szName, volName);
+#if WINCEOSVER >= 400
+ // The user passed an empty volume name. On CE 4.xx try to get
+ // if from the block driver (which got it from the registry).
+ else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL))
+#else
+ else
+#endif
+ {
+ // Didn't get a volume name so use "Disk" by default.
+ wcscpy( szName, YFSD_DISK_NAME);
+ }
+ vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);
+ //slf021104b end
if(vol->mgrVolume)
- {
+ {
+ //slf021104b Begin
+ // Get some space for the volume name.
+ vol->volName = malloc( MAX_PATH * sizeof(WCHAR));
+ if (vol->volName)
+ {
+#if WINCEOSVER >= 400
+ // Get the name we were really mounted under.
+ FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);
+
+ // If we got mounted as root then throw away the backslash
+ // so we won't get a double backslash when volName is
+ // prepended to the path in the full path name calculation
+ // that is used for shell callbacks.
+ if (0 == wcscmp(vol->volName,L"\\"))
+ vol->volName[0] = 0;
+#else
+ // Use the name we asked to be mounted under for
+ // our root.
+ wcscpy(vol->volName,L"\\");
+ wcscat(vol->volName, szName);
+#endif
+ }
+ //slf021104b end
return TRUE;
}
else
@@ -629,6 +727,14 @@ BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock,
BOOL YFSD_MountDisk(HDSK hdsk)
{
+//slf021105a begin
+#ifdef DO_PARTITION_TABLE
+ ynandif_partition PartTable[MAXPARTITIONS];
+ DWORD dwAvail;
+ int i;
+ BOOL rval = FALSE;
+#endif
+//slf021105a end
int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
//int i;
// Called to mount a disk.
@@ -646,29 +752,124 @@ BOOL YFSD_MountDisk(HDSK hdsk)
yfsd_InitialiseWinFiles();
yaffsLockInited = 1;
}
-
-#ifdef DISABLE_BOOT_PARTITION
- // Only want disk volume
- YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
-
-
- if(disk_volume.isMounted)
- {
- return TRUE;
- }
+
+ //slf021105a begin
+ memset(disk_volumes,0,sizeof(disk_volumes));
+#ifdef DO_PARTITION_TABLE
+ memset(&PartTable,0,sizeof(PartTable));
+ // Call the block driver to get the partition table from it.
+ if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL))
+ {
+ // Scan throught the table it return.
+ for (i=0; i PartTable[i].startBlock))
+ {
+ // Found a partion. Get a volume structure to hold it.
+ disk_volumes[i] = malloc(sizeof(yfsd_Volume));
+ if (disk_volumes[i])
+ {
+ memset(disk_volumes[i],0,sizeof(yfsd_Volume));
+ // Go init the volume. Note that if the block driver wants the
+ // name to come from the registry it will have returned an
+ // empty name string.
+ YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);
+ if (disk_volumes[i]->isMounted)
+ rval = TRUE; //Hey, we found at least on partition.
+ }
+ }
+ }
+ }
+
+ return rval;
+
#else
- // Want both boot and disk
- YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
- YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
-
-
- if(disk_volume.isMounted && boot_volume.isMounted)
- {
- return TRUE;
- }
-#endif
-
- return FALSE;
+#ifdef DISABLE_BOOT_PARTITION
+ // Only want disk volume
+ disk_volumes[0] = malloc(sizeof(yfsd_Volume));
+ if (disk_volumes[0])
+ {
+ memset(disk_volumes[0],0,sizeof(yfsd_Volume));
+ YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);
+
+ if(disk_volumes[0].isMounted)
+ {
+ return TRUE;
+ }
+ }
+ if (disk_volumes[0])
+ {
+ free(disk_volumes[0];
+ disk_volumes[0] = NULL;
+ }
+#else
+ // Want both boot and disk
+ disk_volumes[0] = malloc(sizeof(yfsd_Volume));
+ disk_volumes[1] = malloc(sizeof(yfsd_Volume));
+ if (disk_volumes[0] && disk_volumes[1])
+ {
+ memset(disk_volumes[0],0,sizeof(yfsd_Volume));
+ memset(disk_volumes[1],0,sizeof(yfsd_Volume));
+ YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
+ YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
+
+ if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)
+ {
+ return TRUE;
+ }
+ }
+
+ // If we got this far something went wrong. Make sure to
+ // free any memory we allocated.
+ if (disk_volumes[0])
+ {
+ if (disk_volumes[0]->volName)
+ {
+ free(disk_volumes[0]->volName);
+ }
+ free(disk_volumes[0]);
+ disk_volumes[0] = NULL;
+ }
+ if (disk_volumes[1])
+ {
+ if (disk_volumes[1]->volName)
+ {
+ free(disk_volumes[1]->volName);
+ }
+ free(disk_volumes[1]);
+ disk_volumes[1] = NULL;
+ }
+#endif
+
+ return FALSE;
+
+ // Only want disk volume
+// YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
+//
+//
+// if(disk_volume.isMounted)
+// {
+// return TRUE;
+// }
+//#else
+// // Want both boot and disk
+// YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
+// YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
+//
+//
+// if(disk_volume.isMounted && boot_volume.isMounted)
+// {
+// return TRUE;
+// }
+//#endif
+//
+// return FALSE;
+#endif
+//slf021105a end
// yfsd_SetGuards();
@@ -679,17 +880,47 @@ BOOL YFSD_MountDisk(HDSK hdsk)
BOOL YFSD_UnmountDisk(HDSK hdsk)
{
+//slf021105a begin
+ int i;
+//slf021105a end
RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
- yfsd_FlushAllFiles();
-
- yfsd_LockYAFFS();
- yaffs_Deinitialise(&disk_volume.dev);
- yaffs_Deinitialise(&boot_volume.dev);
- yfsd_UnlockYAFFS();
-
- FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
- FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
+ //slf021104d begin
+ // If there are any files open don't let them dismount
+ // it or the system will get very confused.
+ if (yfsd_FilesOpen())
+ return FALSE;
+
+ //yfsd_FlushAllFiles();
+ //slf021104d end
+
+ yfsd_LockYAFFS();
+//slf021105a begin
+// yaffs_Deinitialise(&disk_volume.dev);
+// yaffs_Deinitialise(&boot_volume.dev);
+// yfsd_UnlockYAFFS();
+//
+// FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
+// FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
+
+ // Walk through the partions deinitializing, deregistering
+ // and freeing them.
+ for (i=0; idev));
+ FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);
+ if (disk_volumes[i]->volName)
+ {
+ free(disk_volumes[i]->volName);
+ }
+ free(disk_volumes[i]);
+ disk_volumes[i] = NULL;
+ }
+ }
+ yfsd_UnlockYAFFS();
+//slf021105a end
return TRUE;
}
@@ -711,22 +942,35 @@ BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTE
parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
- if(parent && yfsd_NameIsValid(name))
- {
- newDir = yaffs_MknodDirectory(parent,name,0,0,0);
- }
-
- if(newDir)
+ //slf021101b begin
+ if (parent)
{
- objSize = yaffs_GetObjectFileLength(newDir);
- attribs = yfsd_GetObjectWinAttributes(newDir);
- modifiedTime[0] = newDir->win_mtime[0];
- modifiedTime[1] = newDir->win_mtime[1];
+ if(yfsd_NameIsValid(name))
+ {
+ newDir = yaffs_MknodDirectory(parent,name,0,0,0);
+ if(newDir)
+ {
+ objSize = yaffs_GetObjectFileLength(newDir);
+ attribs = yfsd_GetObjectWinAttributes(newDir);
+ modifiedTime[0] = newDir->win_mtime[0];
+ modifiedTime[1] = newDir->win_mtime[1];
+ }
+ else
+ {
+ if(yaffs_FindObjectByName(parent,name))
+ SetLastError(ERROR_ALREADY_EXISTS);
+ else
+ SetLastError(ERROR_DISK_FULL);
+ }
+ }
+ else
+ SetLastError(ERROR_INVALID_NAME);
}
else
{
SetLastError(ERROR_PATH_NOT_FOUND);
}
+ //slf021101b end
yfsd_UnlockYAFFS();
@@ -752,10 +996,12 @@ BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTE
}
- if(parent && !newDir)
- {
- SetLastError(ERROR_DISK_FULL);
- }
+//slf021101b begin
+// if(parent && !newDir)
+// {
+// SetLastError(ERROR_DISK_FULL);
+// }
+//slf021101b end
return newDir ? TRUE : FALSE;
}
@@ -871,19 +1117,19 @@ DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
{
- yaffs_Object *obj = NULL;
- DWORD mtime[2];
- DWORD attribs;
+ yaffs_Object *obj = NULL;
+ DWORD mtime[2];
+ DWORD attribs;
DWORD objSize;
int result = 0;
- RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
-
- if(!yfsd_CheckValidAttributes(dwFileAttributes))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
+
+ if(!yfsd_CheckValidAttributes(dwFileAttributes))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
}
yfsd_LockYAFFS();
@@ -894,11 +1140,11 @@ BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAt
{
obj->st_mode = dwFileAttributes;
obj->dirty = 1;
- result = yaffs_FlushFile(obj);
- attribs = yfsd_GetObjectWinAttributes(obj);
- objSize = yaffs_GetObjectFileLength(obj);
- mtime[0] = obj->win_mtime[0];
- mtime[1] = obj->win_mtime[1];
+ result = yaffs_FlushFile(obj,0);
+ attribs = yfsd_GetObjectWinAttributes(obj);
+ objSize = yaffs_GetObjectFileLength(obj);
+ mtime[0] = obj->win_mtime[0];
+ mtime[1] = obj->win_mtime[1];
}
else
{
@@ -971,7 +1217,7 @@ BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName
int result = 0;
int objIsDir = 0;
DWORD attribs;
- DWORD objSize;
+ DWORD objSize;
DWORD mtime[2];
RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
@@ -994,9 +1240,9 @@ BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName
{
objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
attribs = yfsd_GetObjectWinAttributes(obj);
- objSize = yaffs_GetObjectFileLength(obj);
- mtime[0] = obj->win_mtime[0];
- mtime[1] = obj->win_mtime[1];
+ objSize = yaffs_GetObjectFileLength(obj);
+ mtime[0] = obj->win_mtime[0];
+ mtime[1] = obj->win_mtime[1];
}
}
else
@@ -1036,8 +1282,18 @@ BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName
BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
{
- RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
- return FALSE;
+ //slf021104c begin
+ BOOL fSuccess;
+ //slf021104c end
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
+
+ //slf021104c begin
+ if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))
+ fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);
+ return fSuccess;
+ //return FALSE;
+ //slf021104c end
}
BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
@@ -1232,8 +1488,8 @@ BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
return found;
}
-
-#if 0
+
+#if 0
// slower one
BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
{
@@ -1309,77 +1565,77 @@ out_of_here:
return found;
}
-
-#else
-// faster one
-BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
-{
-
- struct list_head *i;
- yaffs_Object *l;
- BOOL found = 0;
-
- char name[YAFFS_MAX_NAME_LENGTH+1];
-
- if(!pSearch->foundObjects)
- {
- pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
- pSearch->foundObjects->next = NULL;
- pSearch->foundObjects->obj = 0;
- }
-
-
- yfsd_LockYAFFS();
-
- list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
- {
-
- l = list_entry(i, yaffs_Object,siblings);
- if(!yfsd_ObjectAlreadyFound(pSearch,l))
- {
- // Only look at things we have not looked at already
- yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
-
- if(regularMatch(pSearch->pattern,name))
- {
- found = 1;
- // fill out find data
-
- pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
-
- yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
- yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
- yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
-
- pfd->nFileSizeHigh = 0;
- pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
- pfd->dwOID = 0; // wtf is this???
-
- MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
-
- RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
- pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
- l->variant.fileVariant.scannedFileSize));
- goto out_of_here;
- }
-
- }
-
-
- }
-
-out_of_here:
- yfsd_UnlockYAFFS();
-
-
- if(!found)
- {
- SetLastError(ERROR_NO_MORE_FILES);
- }
- return found;
-
-}
-#endif
+
+#else
+// faster one
+BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
+{
+
+ struct list_head *i;
+ yaffs_Object *l;
+ BOOL found = 0;
+
+ char name[YAFFS_MAX_NAME_LENGTH+1];
+
+ if(!pSearch->foundObjects)
+ {
+ pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
+ pSearch->foundObjects->next = NULL;
+ pSearch->foundObjects->obj = 0;
+ }
+
+
+ yfsd_LockYAFFS();
+
+ list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
+ {
+
+ l = list_entry(i, yaffs_Object,siblings);
+ if(!yfsd_ObjectAlreadyFound(pSearch,l))
+ {
+ // Only look at things we have not looked at already
+ yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
+
+ if(regularMatch(pSearch->pattern,name))
+ {
+ found = 1;
+ // fill out find data
+
+ pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
+
+ yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
+ yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
+ yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
+
+ pfd->nFileSizeHigh = 0;
+ pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
+ pfd->dwOID = 0; // wtf is this???
+
+ MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
+
+ RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
+ pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
+ l->variant.fileVariant.scannedFileSize));
+ goto out_of_here;
+ }
+
+ }
+
+
+ }
+
+out_of_here:
+ yfsd_UnlockYAFFS();
+
+
+ if(!found)
+ {
+ SetLastError(ERROR_NO_MORE_FILES);
+ }
+ return found;
+
+}
+#endif
HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
{
@@ -1484,7 +1740,12 @@ HANDLE YFSD_CreateFileW(
unsigned modifiedTime[2];
unsigned objSize;
- BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
+ BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
+ BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;
+ BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;
+ BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;
+
+ BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;
BOOL fileCreated = FALSE;
@@ -1502,11 +1763,11 @@ HANDLE YFSD_CreateFileW(
RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
}
- if(!yfsd_CheckValidAttributes(mode))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
+ if(!yfsd_CheckValidAttributes(mode))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
yfsd_LockYAFFS();
@@ -1516,24 +1777,26 @@ HANDLE YFSD_CreateFileW(
if(parent && yfsd_NameIsValid(name))
{
-
- obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
- if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
- {
- // Naughty, naughty. Don't do file ops on directories
- SetLastError(ERROR_ACCESS_DENIED);
- fileCreated = FALSE;
- obj = NULL;
- }
- else if(dwCreate == CREATE_NEW)
+ if(dwCreate == CREATE_NEW)
{
RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
- obj = yaffs_MknodFile(parent,name,mode,0,0);
+ //slf021101c begin
+ obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
if(!obj)
- SetLastError(ERROR_DISK_FULL);
- fileCreated = TRUE;
+ {
+ obj = yaffs_MknodFile(parent,name,mode,0,0);
+ if(!obj)
+ SetLastError(ERROR_DISK_FULL);
+ fileCreated = TRUE;
+ }
+ else
+ {
+ obj = NULL;
+ SetLastError(ERROR_ALREADY_EXISTS);
+ }
+ //slf021101c end
}
else if( dwCreate == OPEN_ALWAYS)
{
@@ -1558,6 +1821,14 @@ HANDLE YFSD_CreateFileW(
obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
if(!obj)
SetLastError(ERROR_FILE_NOT_FOUND);
+ //slf021101c begin
+ else
+ if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ obj = NULL;
+ }
+ //slf021101c end
}
else if(dwCreate == TRUNCATE_EXISTING)
{
@@ -1590,7 +1861,7 @@ HANDLE YFSD_CreateFileW(
obj->st_mode = mode;
obj->dirty = 1;
yaffs_ResizeFile(obj,0);
- yaffs_FlushFile(obj);
+ yaffs_FlushFile(obj,1);
}
}
else
@@ -1604,7 +1875,41 @@ HANDLE YFSD_CreateFileW(
RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
SetLastError(ERROR_PATH_NOT_FOUND);
}
-
+
+ if(obj)
+ {
+ int i;
+ yfsd_WinFile *p;
+ openRead = openWrite =0;
+ openReadAllowed = openWriteAllowed = 1;
+
+ for(i = 0; i < MAX_WIN_FILE; i++)
+ {
+ p = &yfsd_winFile[i];
+
+ if(p->obj == obj)
+ {
+ if (p->readPermitted) openRead = 1;
+ if (p->writePermitted) openWrite = 1;
+ if (!p->shareRead) openReadAllowed = 0;
+ if (!p->shareWrite) openWriteAllowed = 0;
+ }
+
+ }
+
+ // Now we test if the share works out.
+
+ if((openRead && !shareRead) || // already open for read, but we are not prepared to share it for read
+ (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write
+ (!openReadAllowed && readPermitted) || // already open with read sharing not permitted
+ (!openWriteAllowed && writePermitted)) // same... write
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ obj = NULL;
+ }
+
+
+ }
if(obj)
{
RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
@@ -1625,12 +1930,15 @@ HANDLE YFSD_CreateFileW(
RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
f->obj = obj;
f->offset = 0;
- f->writePermitted = writePermitted;
+ f->writePermitted = writePermitted;
+ f->readPermitted = writePermitted;
+ f->shareRead= shareRead;
+ f->shareWrite = shareWrite;
f->myVolume = pVolume;
obj->inUse++;
- modifiedTime[0] = obj->win_mtime[0];
- modifiedTime[1] = obj->win_mtime[1];
+ modifiedTime[0] = obj->win_mtime[0];
+ modifiedTime[1] = obj->win_mtime[1];
objSize = yaffs_GetObjectFileLength(obj);
RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
}
@@ -1737,8 +2045,8 @@ BOOL yfsd_DoReadFile(
{
nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
if(nread > 0)
- {
- pFile->offset += nread;
+ {
+ pFile->offset += nread;
if(pcbRead)
{
@@ -1748,9 +2056,9 @@ BOOL yfsd_DoReadFile(
}
else
{
- if(pcbRead)
- {
- *pcbRead = maxRead;
+ if(pcbRead)
+ {
+ *pcbRead = maxRead;
}
}
@@ -1794,7 +2102,7 @@ BOOL YFSD_ReadFileWithSeek(
DWORD dwLowOffset,
DWORD dwHighOffset )
{
- BOOL result;
+ BOOL result;
DWORD rememberedOffset;
RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
@@ -1813,16 +2121,16 @@ BOOL YFSD_ReadFileWithSeek(
return FALSE;
}
- yfsd_LockYAFFS();
-
+ yfsd_LockYAFFS();
+
rememberedOffset = pFile->offset;
pFile->offset = dwLowOffset;
// ignore high offset for now
result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
-
- //pFile->offset = rememberedOffset;
+
+ //pFile->offset = rememberedOffset;
yfsd_UnlockYAFFS();
@@ -1909,7 +2217,7 @@ BOOL YFSD_WriteFileWithSeek(
DWORD rememberedOffset;
RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
-
+
if(!pFile || !pFile->obj)
{
@@ -1918,15 +2226,15 @@ BOOL YFSD_WriteFileWithSeek(
}
yfsd_LockYAFFS();
-
- rememberedOffset = pFile->offset;
+
+ rememberedOffset = pFile->offset;
pFile->offset = dwLowOffset;
// ignore high offset for now
result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
-
- //pFile->offset = rememberedOffset;
+
+ //pFile->offset = rememberedOffset;
yfsd_UnlockYAFFS();
@@ -1953,8 +2261,8 @@ DWORD YFSD_SetFilePointer(
return offset;
}
- yfsd_LockYAFFS();
-
+ yfsd_LockYAFFS();
+
oldPos = pFile->offset;
@@ -2028,8 +2336,8 @@ DWORD YFSD_GetFileSize(
fileSize = yaffs_GetObjectFileLength(pFile->obj);
- yfsd_UnlockYAFFS();
- if(pFileSizeHigh)
+ yfsd_UnlockYAFFS();
+ if(pFileSizeHigh)
*pFileSizeHigh = 0;
return fileSize;
@@ -2047,35 +2355,40 @@ BOOL YFSD_GetFileInformationByHandle(
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
- }
-
- yfsd_LockYAFFS();
-
- pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
- yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
- yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
- yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
- pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK?
- pFileInfo->nFileSizeHigh = 0;
- pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj);
- pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
- pFileInfo->nFileIndexHigh = 0;
- pFileInfo->nFileIndexLow = pFile->obj->objectId;
-
+ }
+
+ yfsd_LockYAFFS();
+
+ pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
+ yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
+ yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
+ yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
+ pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK?
+ pFileInfo->nFileSizeHigh = 0;
+ pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj);
+ pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
+ pFileInfo->nFileIndexHigh = 0;
+ pFileInfo->nFileIndexLow = pFile->obj->objectId;
+//slf021104a Begin Window CE 4.0 added an additional field.
+#if _WINCEOSVER >= 400
+ pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);
+#endif
+//slf021104a end
+
yfsd_UnlockYAFFS();
return TRUE;
}
BOOL YFSD_FlushFileBuffers(PFILE pFile )
-{
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
- int nameExists = 0;
- yfsd_Volume *vol = NULL;
- DWORD attribs = 0;
- DWORD objSize = 0;
- DWORD mtime[2];
-
+{
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int nameExists = 0;
+ yfsd_Volume *vol = NULL;
+ DWORD attribs = 0;
+ DWORD objSize = 0;
+ DWORD mtime[2];
+
RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
@@ -2085,40 +2398,40 @@ BOOL YFSD_FlushFileBuffers(PFILE pFile )
return FALSE;
}
- yfsd_LockYAFFS();
+ yfsd_LockYAFFS();
+
+ yaffs_FlushFile(pFile->obj,1);
+ attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+ objSize = yaffs_GetObjectFileLength(pFile->obj);
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
+ if(pFile->fullName)
+ {
+ wcscpy(fpn,pFile->fullName);
+ nameExists = 1;
+ }
+ vol = pFile->myVolume;
- yaffs_FlushFile(pFile->obj);
- attribs = yfsd_GetObjectWinAttributes(pFile->obj);
- objSize = yaffs_GetObjectFileLength(pFile->obj);
- mtime[0] = pFile->obj->win_mtime[0];
- mtime[1] = pFile->obj->win_mtime[1];
- if(pFile->fullName)
- {
- wcscpy(fpn,pFile->fullName);
- nameExists = 1;
- }
- vol = pFile->myVolume;
-
yfsd_UnlockYAFFS();
-
- if(vol && vol->shellFunction && nameExists)
- {
- FILECHANGEINFO fc;
-
- fc.cbSize = sizeof(FILECHANGEINFO);
- fc.wEventId = SHCNE_UPDATEITEM;
- fc.uFlags = SHCNF_PATH;
- fc.dwItem1 = (DWORD)fpn;
- fc.dwItem2 = 0;
- fc.dwAttributes = attribs;
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
- fc.nFileSize = objSize;
-
- vol->shellFunction(&fc);
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
- //yfsd_ShellDirectoryChanged(vol,fpn);
- }
-
+
+ if(vol && vol->shellFunction && nameExists)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)fpn;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ vol->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+ //yfsd_ShellDirectoryChanged(vol,fpn);
+ }
+
return TRUE;
}
@@ -2154,15 +2467,15 @@ BOOL YFSD_SetFileTime(
CONST FILETIME *pLastAccess,
CONST FILETIME *pLastWrite )
{
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
- int nameExists = 0;
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int nameExists = 0;
int result = FALSE;
- yfsd_Volume *vol = NULL;
- DWORD attribs = 0;
- DWORD objSize = 0;
- DWORD mtime[2];
-
-
+ yfsd_Volume *vol = NULL;
+ DWORD attribs = 0;
+ DWORD objSize = 0;
+ DWORD mtime[2];
+
+
RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
if(!pFile || !pFile->obj)
@@ -2174,60 +2487,60 @@ BOOL YFSD_SetFileTime(
yfsd_LockYAFFS();
- if(pCreation)
- {
- yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
- pFile->obj->dirty = 1;
+ if(pCreation)
+ {
+ yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
+ pFile->obj->dirty = 1;
}
- if(pLastAccess)
- {
- yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
- pFile->obj->dirty = 1;
+ if(pLastAccess)
+ {
+ yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
+ pFile->obj->dirty = 1;
}
- if(pLastWrite)
- {
- yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
+ if(pLastWrite)
+ {
+ yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
pFile->obj->dirty = 1;
}
if(pCreation || pLastAccess || pLastWrite)
{
- result = yaffs_FlushFile(pFile->obj);
+ result = yaffs_FlushFile(pFile->obj,0);
}
-
- if(result)
+
+ if(result)
{
- attribs = yfsd_GetObjectWinAttributes(pFile->obj);
- objSize = yaffs_GetObjectFileLength(pFile->obj);
- mtime[0] = pFile->obj->win_mtime[0];
- mtime[1] = pFile->obj->win_mtime[1];
- if(pFile->fullName)
- {
- wcscpy(fpn,pFile->fullName);
- nameExists = 1;
- }
- vol = pFile->myVolume;
- }
-
+ attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+ objSize = yaffs_GetObjectFileLength(pFile->obj);
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
+ if(pFile->fullName)
+ {
+ wcscpy(fpn,pFile->fullName);
+ nameExists = 1;
+ }
+ vol = pFile->myVolume;
+ }
+
yfsd_UnlockYAFFS();
// Call shell function
- if(nameExists && result && vol && vol->shellFunction)
- {
- FILECHANGEINFO fc;
-
- fc.cbSize = sizeof(FILECHANGEINFO);
- fc.wEventId = SHCNE_UPDATEITEM;
- fc.uFlags = SHCNF_PATH;
- fc.dwItem1 = (DWORD)fpn;
- fc.dwItem2 = 0;
- fc.dwAttributes = attribs;
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
- fc.nFileSize = objSize;
-
- vol->shellFunction(&fc);
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
- //yfsd_ShellDirectoryChanged(vol,fpn);
- }
+ if(nameExists && result && vol && vol->shellFunction)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)fpn;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ vol->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+ //yfsd_ShellDirectoryChanged(vol,fpn);
+ }
return TRUE;
}
@@ -2236,12 +2549,12 @@ BOOL YFSD_SetEndOfFile(
PFILE pFile )
{
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
- int nameExists = 0;
- yfsd_Volume *vol = NULL;
- DWORD attribs = 0;
- DWORD objSize = 0;
- DWORD mtime[2];
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int nameExists = 0;
+ yfsd_Volume *vol = NULL;
+ DWORD attribs = 0;
+ DWORD objSize = 0;
+ DWORD mtime[2];
static unsigned char zeros[512];
int result;
@@ -2303,40 +2616,40 @@ PFILE pFile )
{
retVal = TRUE;
}
- if(retVal)
- {
- attribs = yfsd_GetObjectWinAttributes(pFile->obj);
- objSize = yaffs_GetObjectFileLength(pFile->obj);
- mtime[0] = pFile->obj->win_mtime[0];
- mtime[1] = pFile->obj->win_mtime[1];
- if(pFile->fullName)
- {
- wcscpy(fpn,pFile->fullName);
- nameExists = 1;
- }
- vol = pFile->myVolume;
- }
-
-
- yfsd_UnlockYAFFS();
-
- if(nameExists && retVal && vol && vol->shellFunction)
- {
- FILECHANGEINFO fc;
-
- fc.cbSize = sizeof(FILECHANGEINFO);
- fc.wEventId = SHCNE_UPDATEITEM;
- fc.uFlags = SHCNF_PATH;
- fc.dwItem1 = (DWORD)fpn;
- fc.dwItem2 = 0;
- fc.dwAttributes = attribs;
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
- fc.nFileSize = objSize;
-
- vol->shellFunction(&fc);
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
- //yfsd_ShellDirectoryChanged(vol,fpn);
- }
+ if(retVal)
+ {
+ attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+ objSize = yaffs_GetObjectFileLength(pFile->obj);
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
+ if(pFile->fullName)
+ {
+ wcscpy(fpn,pFile->fullName);
+ nameExists = 1;
+ }
+ vol = pFile->myVolume;
+ }
+
+
+ yfsd_UnlockYAFFS();
+
+ if(nameExists && retVal && vol && vol->shellFunction)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)fpn;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ vol->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+ //yfsd_ShellDirectoryChanged(vol,fpn);
+ }
RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
@@ -2367,7 +2680,7 @@ BOOL YFSD_CloseFile( PFILE pFile )
yfsd_Volume *vol = NULL;
DWORD attribs = 0;
DWORD objSize = 0;
- DWORD mtime[2];
+ DWORD mtime[2];
RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
@@ -2383,11 +2696,11 @@ BOOL YFSD_CloseFile( PFILE pFile )
{
pFile->obj->inUse--;
RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
- yaffs_FlushFile(pFile->obj);
+ yaffs_FlushFile(pFile->obj,1);
attribs = yfsd_GetObjectWinAttributes(pFile->obj);
objSize = yaffs_GetObjectFileLength(pFile->obj);
- mtime[0] = pFile->obj->win_mtime[0];
- mtime[1] = pFile->obj->win_mtime[1];
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
if(pFile->fullName)
{
diff --git a/yaffs_fileem.c b/yaffs_fileem.c
index f4a324e..3ee50eb 100644
--- a/yaffs_fileem.c
+++ b/yaffs_fileem.c
@@ -26,7 +26,7 @@
#include
#include
-#define FILE_SIZE_IN_MEG 4
+#define FILE_SIZE_IN_MEG 2
// #define YAFFS_ERROR_TESTING
diff --git a/yaffs_fs.c b/yaffs_fs.c
index 81b8ccf..1f4f5b8 100644
--- a/yaffs_fs.c
+++ b/yaffs_fs.c
@@ -27,7 +27,7 @@
*/
-const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.21 2002-11-26 01:39:53 charles Exp $";
+const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.22 2003-01-14 23:15:29 charles Exp $";
extern const char *yaffs_guts_c_version;
@@ -352,7 +352,7 @@ static int yaffs_file_flush(struct file* file)
yaffs_GrossLock(dev);
- yaffs_FlushFile(obj);
+ yaffs_FlushFile(obj,1);
yaffs_GrossUnlock(dev);
@@ -853,8 +853,11 @@ static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dent
dev = obj->myDev;
yaffs_GrossLock(dev);
-
- link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj);
+
+ if (!S_ISDIR(inode->i_mode)) // Don't link directories
+ {
+ link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj);
+ }
if(link)
@@ -926,7 +929,7 @@ static int yaffs_sync_object(struct file * file, struct dentry *dentry, int data
T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_sync_object\n"));
yaffs_GrossLock(dev);
- yaffs_FlushFile(obj);
+ yaffs_FlushFile(obj,1);
yaffs_GrossUnlock(dev);
return 0;
}
@@ -939,22 +942,44 @@ static int yaffs_sync_object(struct file * file, struct dentry *dentry, int data
static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
{
yaffs_Device *dev;
- int retVal;
+ int retVal = YAFFS_FAIL;
+ int removed = 0;
+ yaffs_Object *target;
dev = yaffs_InodeToObject(old_dir)->myDev;
yaffs_GrossLock(dev);
- // Unlink the target if it exists
- yaffs_Unlink(yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
+ // Check if the target is an existing directory that is not empty.
+ target = yaffs_FindObjectByName(yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
+
+ if(target &&
+ target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
+ !list_empty(&target->variant.directoryVariant.children))
+ {
+ retVal = YAFFS_FAIL;
+ }
+ else
+ {
+
+ // Unlink the target if it exists
+ removed = yaffs_Unlink(yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
- retVal = yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name,
- yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
+ retVal = yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name,
+ yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
+
+ }
yaffs_GrossUnlock(dev);
if(retVal == YAFFS_OK)
{
+ if(removed == YAFFS_OK)
+ {
+ new_dentry->d_inode->i_nlink--;
+ mark_inode_dirty(new_dentry->d_inode);
+ }
+
return 0;
}
else
@@ -1222,6 +1247,10 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
dev->initialiseNAND = nandmtd_InitialiseNAND;
dev->putSuperFunc = yaffs_MTDPutSuper;
+
+#ifdef CONFIG_YAFFS_USE_NANDECC
+ dev->useNANDECC = 1;
+#endif
yaffs_dev = dev;
@@ -1312,6 +1341,8 @@ static char * yaffs_dump_dev(char *buf,yaffs_Device *dev,char *name)
buf +=sprintf(buf,"nDeletedFiles...... %d\n",dev->nDeletedFiles);
buf +=sprintf(buf,"nUnlinkedFiles..... %d\n",dev->nUnlinkedFiles);
buf +=sprintf(buf,"nBackgroudDeletions %d\n",dev->nBackgroundDeletions);
+ buf +=sprintf(buf,"useNANDECC......... %d\n",dev->useNANDECC);
+
return buf;
}
diff --git a/yaffs_guts.c b/yaffs_guts.c
index 9ddabf6..bb714e0 100644
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -14,7 +14,7 @@
*/
//yaffs_guts.c
-const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.15 2002-12-13 00:13:06 charles Exp $";
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.16 2003-01-14 23:15:29 charles Exp $";
#include "yportenv.h"
@@ -72,7 +72,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkIn
static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type);
static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj);
static int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force);
-static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId);
+static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND);
static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);
static int yaffs_CheckStructures(void);
static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit);
@@ -90,7 +90,7 @@ static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaf
static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND);
static int yaffs_UnlinkWorker(yaffs_Object *obj);
-
+static void yaffs_AbortHalfCreatedObject(yaffs_Object *obj);
static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1);
@@ -113,12 +113,63 @@ static int yaffs_CheckFileSanity(yaffs_Object *in);
static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in);
static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId);
+// Chunk bitmap manipulations
+static __inline __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk)
+{
+ if(blk < dev->startBlock || blk > dev->endBlock)
+ {
+ T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),blk));
+ YBUG();
+ }
+ return dev->chunkBits + (dev->chunkBitmapStride * (blk - dev->startBlock));
+}
+
+static __inline__ void yaffs_ClearChunkBits(yaffs_Device *dev,int blk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev,blk);
+
+ memset(blkBits,0,dev->chunkBitmapStride);
+}
+
+static __inline__ void yaffs_ClearChunkBit(yaffs_Device *dev,int blk,int chunk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev,blk);
+
+ blkBits[chunk/8] &= ~ (1<<(chunk & 7));
+}
+
+static __inline__ void yaffs_SetChunkBit(yaffs_Device *dev,int blk,int chunk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev,blk);
+
+ blkBits[chunk/8] |= (1<<(chunk & 7));
+}
+
+static __inline__ int yaffs_CheckChunkBit(yaffs_Device *dev,int blk,int chunk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev,blk);
+ return (blkBits[chunk/8] & (1<<(chunk & 7))) ? 1 :0;
+}
+
+static __inline__ int yaffs_StillSomeChunkBits(yaffs_Device *dev,int blk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev,blk);
+ int i;
+ for(i = 0; i < dev->chunkBitmapStride; i++)
+ {
+ if(*blkBits) return 1;
+ blkBits++;
+ }
+ return 0;
+}
+
+// Function to manipulate block info
static __inline__ yaffs_BlockInfo* yaffs_GetBlockInfo(yaffs_Device *dev, int blk)
{
if(blk < dev->startBlock || blk > dev->endBlock)
{
- T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: block %d is not valid" TENDSTR),blk));
+ T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),blk));
YBUG();
}
return &dev->blockInfo[blk - dev->startBlock];
@@ -154,11 +205,7 @@ static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND
return dev->writeChunkToNAND(dev,chunkInNAND,data,spare);
}
-struct nandspare {
- yaffs_Spare spare;
- int eccres1;
- int eccres2;
-};
+
int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
int chunkInNAND,
@@ -169,12 +216,9 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
int retVal;
yaffs_Spare localSpare;
-#ifndef CONFIG_YAFFS_USE_NANDECC
__u8 calcEcc[3];
int eccResult1,eccResult2;
-#else
- struct nandspare nspare;
-#endif
+ struct yaffs_NANDSpare nspare;
dev->nPageReads++;
@@ -189,7 +233,8 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
}
-#ifndef CONFIG_YAFFS_USE_NANDECC
+ if(!dev->useNANDECC)
+ {
retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,spare);
if(data && doErrorCorrection)
{
@@ -228,37 +273,39 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
yaffs_HandleReadDataError(dev,chunkInNAND);
}
}
-#else
- retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare);
- memcpy (spare, &nspare, sizeof(yaffs_Spare));
- if(data && doErrorCorrection)
- {
- if(nspare.eccres1>0)
- {
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
- }
- else if(nspare.eccres1<0)
- {
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
- }
-
- if(nspare.eccres2>0)
- {
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
- }
- else if(nspare.eccres2<0)
- {
- T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
- }
-
- if(nspare.eccres2 || nspare.eccres2)
- {
- // Hoosterman, we had a data problem on this page
- yaffs_HandleReadDataError(dev,chunkInNAND);
- }
+ }
+ else
+ {
+ retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare);
+ memcpy (spare, &nspare, sizeof(yaffs_Spare));
+ if(data && doErrorCorrection)
+ {
+ if(nspare.eccres1>0)
+ {
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
+ }
+ else if(nspare.eccres1<0)
+ {
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
+ }
+ if(nspare.eccres2>0)
+ {
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
+ }
+ else if(nspare.eccres2<0)
+ {
+ T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
+ }
+
+ if(nspare.eccres2 || nspare.eccres2)
+ {
+ // Hoosterman, we had a data problem on this page
+ yaffs_HandleReadDataError(dev,chunkInNAND);
+ }
+
+ }
}
-#endif
return retVal;
}
@@ -448,7 +495,7 @@ static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND)
// Mark the block for retirement
yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
// Delete the chunk
- yaffs_DeleteChunk(dev,chunkInNAND);
+ yaffs_DeleteChunk(dev,chunkInNAND,1);
}
@@ -505,7 +552,8 @@ static __u16 yaffs_CalcNameSum(const char *name)
{
while ((*bname) && (i <=YAFFS_MAX_NAME_LENGTH))
{
-#ifdef CONFIG_YAFFS_WINCE
+
+#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
sum += toupper(*bname) * i;
#else
sum += (*bname) * i;
@@ -639,9 +687,15 @@ static int yaffs_CreateTnodes(yaffs_Device *dev,int nTnodes)
for(i = 0; i < nTnodes - 1; i++)
{
newTnodes[i].internal[0] = &newTnodes[i+1];
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = 1;
+#endif
}
newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = 1;
+#endif
dev->freeTnodes = newTnodes;
dev->nFreeTnodes+= nTnodes;
dev->nTnodesCreated += nTnodes;
@@ -684,6 +738,13 @@ static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
if(dev->freeTnodes)
{
tn = dev->freeTnodes;
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ if(tn->internal[YAFFS_NTNODES_INTERNAL] != 1)
+ {
+ // Hoosterman, this thing looks like it isn't in the list
+ T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 1" TENDSTR)));
+ }
+#endif
dev->freeTnodes = dev->freeTnodes->internal[0];
dev->nFreeTnodes--;
// zero out
@@ -698,9 +759,20 @@ static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
// FreeTnode frees up a tnode and puts it back on the free list
static void yaffs_FreeTnode(yaffs_Device*dev, yaffs_Tnode *tn)
{
- tn->internal[0] = dev->freeTnodes;
- dev->freeTnodes = tn;
- dev->nFreeTnodes++;
+ if(tn)
+ {
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ if(tn->internal[YAFFS_NTNODES_INTERNAL] != 0)
+ {
+ // Hoosterman, this thing looks like it is already in the list
+ T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 2" TENDSTR)));
+ }
+ tn->internal[YAFFS_NTNODES_INTERNAL] = 1;
+#endif
+ tn->internal[0] = dev->freeTnodes;
+ dev->freeTnodes = tn;
+ dev->nFreeTnodes++;
+ }
}
@@ -970,7 +1042,9 @@ static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, in
}
else if(level == 0)
{
- for(i = YAFFS_NTNODES_LEVEL0 -1; i >= 0; i--) //NB Don't apply the limit here, always delete a whole level0
+ int hitLimit = 0;
+
+ for(i = YAFFS_NTNODES_LEVEL0 -1; i >= 0 && !hitLimit; i--)
{
if(tn->level0[i])
{
@@ -998,11 +1072,15 @@ static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, in
if(found)
{
- yaffs_DeleteChunk(in->myDev,theChunk);
+ yaffs_DeleteChunk(in->myDev,theChunk,1);
in->nDataChunks--;
if(limit)
{
*limit = *limit-1;
+ if(limit <= 0)
+ {
+ hitLimit = 1;
+ }
}
}
@@ -1011,7 +1089,7 @@ static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, in
}
}
- return 1;
+ return (i < 0) ? 1 : 0;
}
@@ -1022,6 +1100,100 @@ static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, in
}
+// SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file.
+// All soft deleting does is increment the block's softdelete count and pulls the chunk out
+// of the tnode.
+// THus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
+//
+static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset)
+{
+ int i;
+ int chunkInInode;
+ int theChunk;
+ yaffs_BlockInfo *theBlock;
+ yaffs_Tags tags;
+ int found;
+ int chunkDeleted;
+ int allDone = 1;
+
+
+ if(tn)
+ {
+ if(level > 0)
+ {
+
+ for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--)
+ {
+ if(tn->internal[i])
+ {
+ allDone = yaffs_SoftDeleteWorker(in,tn->internal[i],level - 1,
+ (chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i);
+ if(allDone)
+ {
+ yaffs_FreeTnode(in->myDev,tn->internal[i]);
+ tn->internal[i] = NULL;
+ }
+ else
+ {
+ //Hoosterman... how could this happen.
+ }
+ }
+ }
+ return (allDone) ? 1 : 0;
+ }
+ else if(level == 0)
+ {
+
+ for(i = YAFFS_NTNODES_LEVEL0 -1; i >=0; i--)
+ {
+ if(tn->level0[i])
+ {
+
+ theChunk = (tn->level0[i] << in->myDev->chunkGroupBits);
+ theBlock = yaffs_GetBlockInfo(in->myDev, theChunk/ YAFFS_CHUNKS_PER_BLOCK);
+ if(theBlock)
+ {
+ theBlock->softDeletions++;
+ }
+ tn->level0[i] = 0;
+ }
+
+ }
+ return 1;
+
+ }
+
+ }
+
+ return 1;
+
+}
+
+
+
+static void yaffs_SoftDeleteFile(yaffs_Object *obj)
+{
+ if(obj->deleted &&
+ obj->variantType == YAFFS_OBJECT_TYPE_FILE &&
+ !obj->softDeleted)
+ {
+ if(obj->nDataChunks <= 0)
+ {
+ // Empty file, just delete it immediately
+ yaffs_FreeTnode(obj->myDev,obj->variant.fileVariant.top);
+ obj->variant.fileVariant.top = NULL;
+ T(YAFFS_TRACE_TRACING,(TSTR("yaffs: Deleting empty file %d" TENDSTR),obj->objectId));
+ yaffs_DoGenericObjectDeletion(obj);
+ }
+ else
+ {
+ yaffs_SoftDeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0);
+ obj->softDeleted = 1;
+ }
+ }
+}
+
+
@@ -1148,7 +1320,7 @@ static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
// Hook them into the free list
for(i = 0; i < nObjects - 1; i++)
{
- (yaffs_Object *)newObjects[i].siblings.next = &newObjects[i+1];
+ newObjects[i].siblings.next = (struct list_head *)(&newObjects[i+1]);
}
newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
@@ -1263,7 +1435,7 @@ static void yaffs_FreeObject(yaffs_Object *tn)
yaffs_UnhashObject(tn);
// Link into the free list.
- (yaffs_Object *)(tn->siblings.next) = dev->freeObjects;
+ tn->siblings.next = (struct list_head *)(dev->freeObjects);
dev->freeObjects = tn;
dev->nFreeObjects++;
}
@@ -1581,11 +1753,11 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type,
break;
}
- if(yaffs_GetNumberOfFreeChunks(dev) <= 0 ||
+ if(/*yaffs_GetNumberOfFreeChunks(dev) <= 0 || */
yaffs_UpdateObjectHeader(in,name,0) < 0)
{
// Could not create the object header, fail the creation
- yaffs_UnlinkWorker(in);
+ yaffs_AbortHalfCreatedObject(in);
in = NULL;
}
@@ -1675,7 +1847,7 @@ int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *
yaffs_Object *obj;
int force = 0;
-#ifdef CONFIG_YAFFS_WINCE
+#ifdef YAFFS_CASE_INSENSITIVE
// Special case for WinCE.
// While look-up is case insensitive, the name isn't.
// THerefore we might want to change x.txt to X.txt
@@ -1790,11 +1962,16 @@ static int yaffs_InitialiseBlocks(yaffs_Device *dev,int nBlocks)
dev->allocationBlock = -1; // force it to get a new one
//Todo we're assuming the malloc will pass.
dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo));
- if(dev->blockInfo)
+ // Set up dynamic blockinfo stuff.
+ dev->chunkBitmapStride = (dev->nChunksPerBlock+7)/8;
+ dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
+ if(dev->blockInfo && dev->chunkBits)
{
memset(dev->blockInfo,0,nBlocks * sizeof(yaffs_BlockInfo));
+ memset(dev->chunkBits,0,dev->chunkBitmapStride * nBlocks);
return YAFFS_OK;
}
+
return YAFFS_FAIL;
}
@@ -1802,6 +1979,9 @@ static int yaffs_InitialiseBlocks(yaffs_Device *dev,int nBlocks)
static void yaffs_DeinitialiseBlocks(yaffs_Device *dev)
{
YFREE(dev->blockInfo);
+ dev->blockInfo = NULL;
+ YFREE(dev->chunkBits);
+ dev->chunkBits = NULL;
}
// FindDiretiestBlock is used to select the dirtiest block (or close enough)
@@ -1814,7 +1994,7 @@ static int yaffs_FindDirtiestBlock(yaffs_Device *dev)
int i;
int dirtiest = -1;
- int pagesInUse = 100; // silly big number
+ int pagesInUse = dev->nChunksPerBlock;
yaffs_BlockInfo *bi;
for(i = dev->startBlock; i <= dev->endBlock && pagesInUse > 2 ; i++)
@@ -1834,10 +2014,10 @@ static int yaffs_FindDirtiestBlock(yaffs_Device *dev)
bi = yaffs_GetBlockInfo(dev,b);
if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
- bi->pagesInUse < pagesInUse)
+ (bi->pagesInUse - bi->softDeletions )< pagesInUse)
{
dirtiest = b;
- pagesInUse = bi->pagesInUse;
+ pagesInUse = (bi->pagesInUse - bi->softDeletions);
}
}
@@ -1868,10 +2048,12 @@ static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo)
if( erasedOk )
{
+ // Clean it up...
bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
dev->nErasedBlocks++;
bi->pagesInUse = 0;
- bi->pageBits = 0;
+ bi->softDeletions = 0;
+ yaffs_ClearChunkBits(dev,blockNo);
T(YAFFS_TRACE_ERASE,(TSTR("Erased block %d" TENDSTR),blockNo));
}
@@ -1886,13 +2068,14 @@ static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo)
static int yaffs_FindBlockForAllocation(yaffs_Device *dev)
{
int i;
+
yaffs_BlockInfo *bi;
if(dev->nErasedBlocks < 1)
{
// Hoosterman we've got a problem.
// Can't get space to gc
- T(YAFFS_TRACE_ERROR, (TSTR("yaffs tradgedy: no space during gc" TENDSTR)));
+ T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no space during gc" TENDSTR)));
return -1;
}
@@ -1902,13 +2085,13 @@ static int yaffs_FindBlockForAllocation(yaffs_Device *dev)
for(i = dev->startBlock; i <= dev->endBlock; i++)
{
dev->allocationBlockFinder++;
- if(dev->allocationBlockFinder < dev->startBlock ||
- dev->allocationBlockFinder > dev->endBlock)
+ if(dev->allocationBlockFinder startBlock || dev->allocationBlockFinder> dev->endBlock)
{
- dev->allocationBlockFinder = dev->startBlock;
+ dev->allocationBlockFinder = dev->startBlock;
}
bi = yaffs_GetBlockInfo(dev,dev->allocationBlockFinder);
+
if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
{
bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING;
@@ -1948,7 +2131,7 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
retVal = (dev->allocationBlock * YAFFS_CHUNKS_PER_BLOCK) +
dev->allocationPage;
bi->pagesInUse++;
- bi->pageBits |= (1 << (dev->allocationPage));
+ yaffs_SetChunkBit(dev,dev->allocationBlock,dev->allocationPage);
dev->allocationPage++;
@@ -1984,29 +2167,30 @@ int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
{
int oldChunk;
int newChunk;
- __u32 mask;
+ int chunkInBlock;
+ int markNAND;
yaffs_Spare spare;
yaffs_Tags tags;
__u8 buffer[YAFFS_BYTES_PER_CHUNK];
- yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,block);
+// yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,block);
yaffs_Object *object;
//T(("Collecting block %d n %d bits %x\n",block, bi->pagesInUse, bi->pageBits));
- for(mask = 1,oldChunk = block * YAFFS_CHUNKS_PER_BLOCK;
- mask && bi->pageBits;
- mask <<= 1, oldChunk++ )
+ for(chunkInBlock = 0,oldChunk = block * YAFFS_CHUNKS_PER_BLOCK;
+ chunkInBlock < dev->nChunksPerBlock && yaffs_StillSomeChunkBits(dev,block);
+ chunkInBlock++, oldChunk++ )
{
- if(bi->pageBits & mask)
+ if(yaffs_CheckChunkBit(dev,block,chunkInBlock))
{
- // This page is in use and needs to be copied off
+ // This page is in use and might need to be copied off
- dev->nGCCopies++;
+ markNAND = 1;
//T(("copying page %x from %d to %d\n",mask,oldChunk,newChunk));
@@ -2023,15 +2207,27 @@ int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
// No need to copy this, just forget about it and fix up the
// object.
- yaffs_PutChunkIntoFile(object, tags.chunkId, 0,0);
+ //yaffs_PutChunkIntoFile(object, tags.chunkId, 0,0);
object->nDataChunks--;
+
+ if(object->nDataChunks <= 0)
+ {
+ // Time to delete the file too
+ yaffs_FreeTnode(object->myDev,object->variant.fileVariant.top);
+ object->variant.fileVariant.top = NULL;
+ T(YAFFS_TRACE_TRACING,(TSTR("yaffs: About to finally delete object %d" TENDSTR),object->objectId));
+ yaffs_DoGenericObjectDeletion(object);
+ }
+ markNAND = 0;
}
else if( 0 /* Todo object && object->deleted && object->nDataChunks == 0 */)
{
// Deleted object header with no data chunks.
- // Can be discarded
+ // Can be discarded and the file deleted.
object->chunkId = 0;
- //Todo some clean up
+ yaffs_FreeTnode(object->myDev,object->variant.fileVariant.top);
+ object->variant.fileVariant.top = NULL;
+ yaffs_DoGenericObjectDeletion(object);
}
else if(object)
@@ -2043,6 +2239,7 @@ int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
tags.serialNumber++;
yaffs_LoadTagsIntoSpare(&spare,&tags);
+ dev->nGCCopies++;
newChunk = yaffs_WriteNewChunkToNAND(dev, buffer, &spare,1);
@@ -2065,7 +2262,7 @@ int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
}
}
- yaffs_DeleteChunk(dev,oldChunk);
+ yaffs_DeleteChunk(dev,oldChunk,markNAND);
}
}
@@ -2076,12 +2273,12 @@ int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
static yaffs_Object *yaffs_FindDeletedUnlinkedFile(yaffs_Device *dev)
{
- // todo find a file to delete
+ // find a file to delete
struct list_head *i;
yaffs_Object *l;
- // To the free chunks add the chunks that are in the deleted unlinked files.
+ //Scan the unlinked files looking for one to delete
list_for_each(i,&dev->unlinkedDir->variant.directoryVariant.children)
{
l = list_entry(i, yaffs_Object,siblings);
@@ -2093,6 +2290,7 @@ static yaffs_Object *yaffs_FindDeletedUnlinkedFile(yaffs_Device *dev)
return NULL;
}
+
static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev)
{
// This does background deletion on unlinked files.. only deleted ones.
@@ -2110,18 +2308,8 @@ static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev)
int limit; // Number of chunks to delete in a file.
// NB this can be exceeded, but not by much.
- limit = 5;
-#if 0
- if(dev->nErasedBlocks <= (YAFFS_RESERVED_BLOCKS + YAFFS_GARBAGE_COLLECT_LOW_WATER))
- {
- limit = 50; // Doing GC soon, so dig deeper
- }
- else
- {
- limit = 5;
- }
-#endif
-
+ limit = -1;
+
delresult = yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit);
if(obj->nDataChunks == 0)
@@ -2129,6 +2317,7 @@ static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev)
// Done all the deleting of data chunks.
// Now dump the header and clean up
yaffs_FreeTnode(dev,obj->variant.fileVariant.top);
+ obj->variant.fileVariant.top = NULL;
yaffs_DoGenericObjectDeletion(obj);
dev->nDeletedFiles--;
dev->nUnlinkedFiles--;
@@ -2144,7 +2333,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev)
{
int block;
- yaffs_DoUnlinkedFileDeletion(dev);
+ //yaffs_DoUnlinkedFileDeletion(dev);
if(dev->nErasedBlocks <= (YAFFS_RESERVED_BLOCKS + YAFFS_GARBAGE_COLLECT_LOW_WATER))
{
@@ -2261,12 +2450,10 @@ static int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, con
yaffs_SpareInitialise(&spare);
-#ifndef CONFIG_YAFFS_USE_NANDECC
- if(buffer)
+ if(!dev->useNANDECC && buffer)
{
yaffs_CalcECC(buffer,&spare);
}
-#endif
yaffs_LoadTagsIntoSpare(&spare,tags);
@@ -2290,13 +2477,10 @@ static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buff
yaffs_SpareInitialise(&spare);
-#ifndef CONFIG_YAFFS_USE_NANDECC
-
- if(buffer)
+ if(!dev->useNANDECC && buffer)
{
yaffs_CalcECC(buffer,&spare);
}
-#endif
yaffs_LoadTagsIntoSpare(&spare,tags);
@@ -2523,7 +2707,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkIn
{
//Hoosterman - how did this happen?
- T(YAFFS_TRACE_ERROR, (TSTR("yaffs tradgedy: existing chunk < 0 in scan" TENDSTR)));
+ T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: existing chunk < 0 in scan" TENDSTR)));
}
@@ -2539,13 +2723,13 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkIn
{
// Use new
// Delete the old one and drop through to update the tnode
- yaffs_DeleteChunk(dev,existingChunk);
+ yaffs_DeleteChunk(dev,existingChunk,1);
}
else
{
// Use existing.
// Delete the new one and return early so that the tnode isn't changed
- yaffs_DeleteChunk(dev,chunkInNAND);
+ yaffs_DeleteChunk(dev,chunkInNAND,1);
return YAFFS_OK;
}
}
@@ -2580,7 +2764,7 @@ int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffe
}
-static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId)
+static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND)
{
int block;
int page;
@@ -2588,16 +2772,26 @@ static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId)
yaffs_BlockInfo *bi;
if(chunkId <= 0) return;
-
+
+ dev->nDeletions++;
block = chunkId / YAFFS_CHUNKS_PER_BLOCK;
page = chunkId % YAFFS_CHUNKS_PER_BLOCK;
- yaffs_SpareInitialise(&spare);
- spare.pageStatus = 0; // To mark it as deleted.
+ if(markNAND)
+ {
+ yaffs_SpareInitialise(&spare);
+
+ spare.pageStatus = 0; // To mark it as deleted.
- yaffs_WriteChunkToNAND(dev,chunkId,NULL,&spare);
- yaffs_HandleUpdateChunk(dev,chunkId,&spare);
+ yaffs_WriteChunkToNAND(dev,chunkId,NULL,&spare);
+ yaffs_HandleUpdateChunk(dev,chunkId,&spare);
+ }
+ else
+ {
+ dev->nUnmarkedDeletions++;
+ }
+
bi = yaffs_GetBlockInfo(dev,block);
@@ -2608,7 +2802,7 @@ static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId)
{
dev->nFreeChunks++;
- bi->pageBits &= ~(1 << page);
+ yaffs_ClearChunkBit(dev,block,page);
bi->pagesInUse--;
if(bi->pagesInUse == 0 &&
@@ -2664,7 +2858,7 @@ int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 *
if(prevChunkId >= 0)
{
- yaffs_DeleteChunk(dev,prevChunkId);
+ yaffs_DeleteChunk(dev,prevChunkId,1);
}
@@ -2791,7 +2985,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force)
// Create new chunk in NAND
- newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev,bufferNew,&newTags,1);
+ newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev,bufferNew,&newTags, (prevChunkId >= 0) ? 1 : 0 );
if(newChunkId >= 0)
{
@@ -2800,7 +2994,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force)
if(prevChunkId >= 0)
{
- yaffs_DeleteChunk(dev,prevChunkId);
+ yaffs_DeleteChunk(dev,prevChunkId,1);
}
in->dirty = 0;
@@ -2823,7 +3017,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force)
// need a very intelligent search.
-#ifdef CONFIG_YAFFS_SHORT_OP_CACHE
+
static void yaffs_FlushFilesChunkCache(yaffs_Object *obj)
@@ -2834,50 +3028,55 @@ static void yaffs_FlushFilesChunkCache(yaffs_Object *obj)
yaffs_ChunkCache *cache;
int chunkWritten;
int nBytes;
+ int nCaches = obj->myDev->nShortOpCaches;
- do{
- cache = NULL;
+ if (nCaches > 0)
+ {
+ do{
+ cache = NULL;
- // Find the dirty cache for this object with the lowest chunk id.
- for(i = 0; i < YAFFS_N_CACHE_CHUNKS; i++)
- {
- if(dev->srCache[i].object == obj &&
- dev->srCache[i].dirty)
+ // Find the dirty cache for this object with the lowest chunk id.
+ for(i = 0; i < nCaches; i++)
{
- if(!cache || dev->srCache[i].chunkId < lowest)
+ if(dev->srCache[i].object == obj &&
+ dev->srCache[i].dirty)
{
- cache = &dev->srCache[i];
- lowest = cache->chunkId;
+ if(!cache || dev->srCache[i].chunkId < lowest)
+ {
+ cache = &dev->srCache[i];
+ lowest = cache->chunkId;
+ }
}
}
- }
- if(cache)
- {
- //Write it out
-
- nBytes = cache->object->variant.fileVariant.fileSize - ((cache->chunkId -1) * YAFFS_BYTES_PER_CHUNK);
-
- if(nBytes > YAFFS_BYTES_PER_CHUNK)
+ if(cache)
{
- nBytes= YAFFS_BYTES_PER_CHUNK;
- }
+ //Write it out
+
+#if 0
+ nBytes = cache->object->variant.fileVariant.fileSize - ((cache->chunkId -1) * YAFFS_BYTES_PER_CHUNK);
- chunkWritten = yaffs_WriteChunkDataToObject(cache->object,
- cache->chunkId,
- cache->data,
- nBytes,1);
+ if(nBytes > YAFFS_BYTES_PER_CHUNK)
+ {
+ nBytes= YAFFS_BYTES_PER_CHUNK;
+ }
+#endif
+ chunkWritten = yaffs_WriteChunkDataToObject(cache->object,
+ cache->chunkId,
+ cache->data,
+ cache->nBytes,1);
- cache->dirty = 0;
- }
+ cache->dirty = 0;
+ }
- } while(cache && chunkWritten > 0);
+ } while(cache && chunkWritten > 0);
- if(cache)
- {
- //Hoosterman, disk full while writing cache out.
- T(YAFFS_TRACE_ERROR, (TSTR("yaffs tradgedy: no space during caceh write" TENDSTR)));
+ if(cache)
+ {
+ //Hoosterman, disk full while writing cache out.
+ T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no space during cache write" TENDSTR)));
+ }
}
}
@@ -2893,32 +3092,39 @@ static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev)
int usage;
int theOne;
- for(i = 0; i < YAFFS_N_CACHE_CHUNKS; i++)
+ if(dev->nShortOpCaches > 0)
{
- if(!dev->srCache[i].object)
+ for(i = 0; i < dev->nShortOpCaches; i++)
{
- //T(("Grabbing empty %d\n",i));
+ if(!dev->srCache[i].object)
+ {
+ //T(("Grabbing empty %d\n",i));
- return &dev->srCache[i];
+ return &dev->srCache[i];
+ }
}
- }
- theOne = -1;
- usage = 0; // just to stop the compiler grizzling
+ theOne = -1;
+ usage = 0; // just to stop the compiler grizzling
- for(i = 0; i < YAFFS_N_CACHE_CHUNKS; i++)
- {
- if(!dev->srCache[i].dirty &&
- ((dev->srCache[i].lastUse < usage && theOne >= 0)||
- theOne < 0))
+ for(i = 0; i < dev->nShortOpCaches; i++)
{
- usage = dev->srCache[i].lastUse;
- theOne = i;
+ if(!dev->srCache[i].dirty &&
+ ((dev->srCache[i].lastUse < usage && theOne >= 0)||
+ theOne < 0))
+ {
+ usage = dev->srCache[i].lastUse;
+ theOne = i;
+ }
}
- }
- //T(("Grabbing non-empty %d\n",theOne));
- return theOne >= 0 ? &dev->srCache[theOne] : NULL;
+ //T(("Grabbing non-empty %d\n",theOne));
+ return theOne >= 0 ? &dev->srCache[theOne] : NULL;
+ }
+ else
+ {
+ return NULL;
+ }
}
@@ -2930,37 +3136,42 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)
int usage;
int i;
- // Try find a non-dirty one...
+ if(dev->nShortOpCaches > 0)
+ {
+ // Try find a non-dirty one...
- cache = yaffs_GrabChunkCacheWorker(dev);
+ cache = yaffs_GrabChunkCacheWorker(dev);
- if(!cache)
- {
- // They were all dirty, find the last recently used object and flush
- // its cache, then find again.
- // NB what's here is not very accurate, we actually flush the object
- // the last recently used page.
+ if(!cache)
+ {
+ // They were all dirty, find the last recently used object and flush
+ // its cache, then find again.
+ // NB what's here is not very accurate, we actually flush the object
+ // the last recently used page.
- theObj = dev->srCache[0].object;
- usage = dev->srCache[0].lastUse;
+ theObj = dev->srCache[0].object;
+ usage = dev->srCache[0].lastUse;
- for(i = 1; i < YAFFS_N_CACHE_CHUNKS; i++)
- {
- if( dev->srCache[i].object &&
- dev->srCache[i].lastUse < usage)
+ for(i = 1; i < dev->nShortOpCaches; i++)
{
- usage = dev->srCache[i].lastUse;
- theObj = dev->srCache[i].object;
+ if( dev->srCache[i].object &&
+ dev->srCache[i].lastUse < usage)
+ {
+ usage = dev->srCache[i].lastUse;
+ theObj = dev->srCache[i].object;
+ }
}
- }
- yaffs_FlushFilesChunkCache(theObj);
+ yaffs_FlushFilesChunkCache(theObj);
- // Try again
- cache = yaffs_GrabChunkCacheWorker(dev);
- }
+ // Try again
+ cache = yaffs_GrabChunkCacheWorker(dev);
+ }
- return cache;
+ return cache;
+ }
+ else
+ return NULL;
}
@@ -2970,43 +3181,48 @@ static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object *obj, int chunk
{
yaffs_Device *dev = obj->myDev;
int i;
-
- for(i = 0; i < YAFFS_N_CACHE_CHUNKS; i++)
+ if(dev->nShortOpCaches > 0)
{
- if(dev->srCache[i].object == obj &&
- dev->srCache[i].chunkId == chunkId)
+ for(i = 0; i < dev->nShortOpCaches; i++)
{
- dev->cacheHits++;
+ if(dev->srCache[i].object == obj &&
+ dev->srCache[i].chunkId == chunkId)
+ {
+ dev->cacheHits++;
- return &dev->srCache[i];
+ return &dev->srCache[i];
+ }
}
}
-
return NULL;
}
// Mark the chunk for the least recently used algorithym
static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache, int isAWrite)
{
- if( dev->srLastUse < 0 ||
- dev->srLastUse > 100000000)
+
+ if(dev->nShortOpCaches > 0)
{
- // Reset the cache usages
- int i;
- for(i = 1; i < YAFFS_N_CACHE_CHUNKS; i++)
+ if( dev->srLastUse < 0 ||
+ dev->srLastUse > 100000000)
{
- dev->srCache[i].lastUse = 0;
+ // Reset the cache usages
+ int i;
+ for(i = 1; i < dev->nShortOpCaches; i++)
+ {
+ dev->srCache[i].lastUse = 0;
+ }
+ dev->srLastUse = 0;
}
- dev->srLastUse = 0;
- }
- dev->srLastUse++;
+ dev->srLastUse++;
- cache->lastUse = dev->srLastUse;
+ cache->lastUse = dev->srLastUse;
- if(isAWrite)
- {
- cache->dirty = 1;
+ if(isAWrite)
+ {
+ cache->dirty = 1;
+ }
}
}
@@ -3015,11 +3231,14 @@ static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache, int
// ie the short cache for this page is no longer valid.
static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId)
{
- yaffs_ChunkCache *cache = yaffs_FindChunkCache(object,chunkId);
-
- if(cache)
+ if(object->myDev->nShortOpCaches > 0)
{
- cache->object = NULL;
+ yaffs_ChunkCache *cache = yaffs_FindChunkCache(object,chunkId);
+
+ if(cache)
+ {
+ cache->object = NULL;
+ }
}
}
@@ -3031,49 +3250,20 @@ static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in)
int i;
yaffs_Device *dev = in->myDev;
- // Now invalidate it.
- for(i = 0; i < YAFFS_N_CACHE_CHUNKS; i++)
- {
- if(dev->srCache[i].object == in)
+ if(dev->nShortOpCaches > 0)
+ {
+ // Now invalidate it.
+ for(i = 0; i < dev->nShortOpCaches; i++)
{
- dev->srCache[i].object = NULL;
+ if(dev->srCache[i].object == in)
+ {
+ dev->srCache[i].object = NULL;
+ }
}
}
}
-#else
-// Stubs for disabling short op caching
-
-static void yaffs_FlushFilesChunkCache(yaffs_Object *obj)
-{}
-
-static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)
-{
- return NULL;
-}
-
-
-static yaffs_ChunkCache *yaffs_FindChunkCache(yaffs_Device *dev, int objectId, int chunkId)
-{
- return NULL;
-}
-
-static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache)
-{
-}
-
-static void yaffs_InvalidateChunkCache(yaffs_Object *obj, int chunkId)
-{
-}
-
-static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in)
-{
-}
-
-
-
-#endif
@@ -3119,27 +3309,32 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB
if(nToCopy != YAFFS_BYTES_PER_CHUNK)
{
// An incomplete start or end chunk (or maybe both start and end chunk)
-#ifdef CONFIG_YAFFS_SHORT_OP_CACHE
- yaffs_ChunkCache *cache;
- // If we can't find the data in the cache, then load it up.
- cache = yaffs_FindChunkCache(in,chunk);
- if(!cache)
+ if(dev->nShortOpCaches > 0)
{
- cache = yaffs_GrabChunkCache(in->myDev);
- cache->object = in;
- cache->chunkId = chunk;
- cache->dirty = 0;
- yaffs_ReadChunkDataFromObject(in,chunk,cache->data);
- }
+ yaffs_ChunkCache *cache;
+ // If we can't find the data in the cache, then load it up.
+ cache = yaffs_FindChunkCache(in,chunk);
+ if(!cache)
+ {
+ cache = yaffs_GrabChunkCache(in->myDev);
+ cache->object = in;
+ cache->chunkId = chunk;
+ cache->dirty = 0;
+ yaffs_ReadChunkDataFromObject(in,chunk,cache->data);
+ cache->nBytes = 0;
+ }
- yaffs_UseChunkCache(dev,cache,0);
+ yaffs_UseChunkCache(dev,cache,0);
+
+ memcpy(buffer,&cache->data[start],nToCopy);
+ }
+ else
+ {
+ // Read into the local buffer then copy...
+ yaffs_ReadChunkDataFromObject(in,chunk,dev->localBuffer);
+ memcpy(buffer,&dev->localBuffer[start],nToCopy);
+ }
- memcpy(buffer,&cache->data[start],nToCopy);
-#else
- // Read into the local buffer then copy...
- yaffs_ReadChunkDataFromObject(in,chunk,dev->localBuffer);
- memcpy(buffer,&dev->localBuffer[start],nToCopy);
-#endif
}
else
{
@@ -3221,42 +3416,44 @@ int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, in
if(nToCopy != YAFFS_BYTES_PER_CHUNK)
{
// An incomplete start or end chunk (or maybe both start and end chunk)
-#ifdef CONFIG_YAFFS_SHORT_OP_CACHE
- yaffs_ChunkCache *cache;
- // If we can't find the data in the cache, then load it up.
- cache = yaffs_FindChunkCache(in,chunk);
- if(!cache && yaffs_CheckSpaceForChunkCache(in->myDev))
+ if(dev->nShortOpCaches > 0)
{
- cache = yaffs_GrabChunkCache(in->myDev);
- cache->object = in;
- cache->chunkId = chunk;
- cache->dirty = 0;
- yaffs_ReadChunkDataFromObject(in,chunk,cache->data);
- }
+ yaffs_ChunkCache *cache;
+ // If we can't find the data in the cache, then load it up.
+ cache = yaffs_FindChunkCache(in,chunk);
+ if(!cache && yaffs_CheckSpaceForChunkCache(in->myDev))
+ {
+ cache = yaffs_GrabChunkCache(in->myDev);
+ cache->object = in;
+ cache->chunkId = chunk;
+ cache->dirty = 0;
+ yaffs_ReadChunkDataFromObject(in,chunk,cache->data);
+ }
- if(cache)
- {
- yaffs_UseChunkCache(dev,cache,1);
- memcpy(&cache->data[start],buffer,nToCopy);
+ if(cache)
+ {
+ yaffs_UseChunkCache(dev,cache,1);
+ memcpy(&cache->data[start],buffer,nToCopy);
+ cache->nBytes = nToWriteBack;
+ }
+ else
+ {
+ chunkWritten = -1; // fail the write
+ }
}
else
{
- chunkWritten = -1; // fail the write
- }
-#else
-
-
- // An incomplete start or end chunk (or maybe both start and end chunk)
- // Read into the local buffer then copy, then copy over and write back.
+ // An incomplete start or end chunk (or maybe both start and end chunk)
+ // Read into the local buffer then copy, then copy over and write back.
- yaffs_ReadChunkDataFromObject(in,chunk,dev->localBuffer);
+ yaffs_ReadChunkDataFromObject(in,chunk,dev->localBuffer);
- memcpy(&dev->localBuffer[start],buffer,nToCopy);
+ memcpy(&dev->localBuffer[start],buffer,nToCopy);
- chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,dev->localBuffer,nToWriteBack,0);
+ chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,dev->localBuffer,nToWriteBack,0);
- //T(("Write with readback to chunk %d %d start %d copied %d wrote back %d\n",chunk,chunkWritten,start, nToCopy, nToWriteBack));
-#endif
+ //T(("Write with readback to chunk %d %d start %d copied %d wrote back %d\n",chunk,chunkWritten,start, nToCopy, nToWriteBack));
+ }
}
else
@@ -3341,7 +3538,7 @@ int yaffs_ResizeFile(yaffs_Object *in, int newSize)
else
{
in->nDataChunks--;
- yaffs_DeleteChunk(dev,chunkId);
+ yaffs_DeleteChunk(dev,chunkId,1);
}
}
@@ -3391,7 +3588,7 @@ loff_t yaffs_GetFileSize(yaffs_Object *obj)
// yaffs_FlushFile() updates the file's
// objectId in NAND
-int yaffs_FlushFile(yaffs_Object *in)
+int yaffs_FlushFile(yaffs_Object *in, int updateTime)
{
int retVal;
if(in->dirty)
@@ -3399,12 +3596,14 @@ int yaffs_FlushFile(yaffs_Object *in)
//T(("flushing object header\n"));
yaffs_FlushFilesChunkCache(in);
-
+ if(updateTime)
+ {
#ifdef CONFIG_YAFFS_WINCE
- yfsd_WinFileTimeNow(in->win_mtime);
+ yfsd_WinFileTimeNow(in->win_mtime);
#else
- in->st_mtime = CURRENT_TIME;
+ in->st_mtime = CURRENT_TIME;
#endif
+ }
retVal = yaffs_UpdateObjectHeader(in,NULL,0);
}
@@ -3425,7 +3624,7 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object *in)
yaffs_InvalidateWholeChunkCache(in);
yaffs_RemoveObjectFromDirectory(in);
- yaffs_DeleteChunk(in->myDev,in->chunkId);
+ yaffs_DeleteChunk(in->myDev,in->chunkId,1);
#ifdef __KERNEL__
if(in->myInode)
{
@@ -3445,6 +3644,7 @@ static int yaffs_UnlinkFile(yaffs_Object *in)
{
#ifdef CONFIG_YAFFS_DISABLE_BACKGROUND_DELETION
+
// Delete the file data & tnodes
yaffs_DeleteWorker(in, in->variant.fileVariant.top, in->variant.fileVariant.topLevel, 0,NULL);
@@ -3457,7 +3657,10 @@ static int yaffs_UnlinkFile(yaffs_Object *in)
int retVal;
int immediateDeletion=0;
retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL,0);
- if(retVal == YAFFS_OK)
+ if(1 || // Ignore the result of the change name. This will only fail
+ // if the disk was completely full (an error condition)
+ // We ignore the error so we can delete files to recover the disk
+ retVal == YAFFS_OK)
{
//in->unlinked = 1;
//in->myDev->nUnlinkedFiles++;
@@ -3468,8 +3671,7 @@ static int yaffs_UnlinkFile(yaffs_Object *in)
immediateDeletion = 1;
}
-#endif
-#ifdef CONFIG_YAFFS_WINCE
+#else
if(in->inUse <= 0)
{
immediateDeletion = 1;
@@ -3482,6 +3684,7 @@ static int yaffs_UnlinkFile(yaffs_Object *in)
T(YAFFS_TRACE_TRACING,(TSTR("yaffs: immediate deletion of file %d" TENDSTR),in->objectId));
in->deleted=1;
in->myDev->nDeletedFiles++;
+ yaffs_SoftDeleteFile(in);
}
}
@@ -3494,18 +3697,33 @@ static int yaffs_UnlinkFile(yaffs_Object *in)
int yaffs_DeleteFile(yaffs_Object *in)
{
int retVal = YAFFS_OK;
- if(!in->unlinked)
+
+ if(in->nDataChunks > 0)
{
- retVal = yaffs_UnlinkFile(in);
+ // Use soft deletion
+ if(!in->unlinked)
+ {
+ retVal = yaffs_UnlinkFile(in);
+ }
+ if(retVal == YAFFS_OK &&
+ in->unlinked &&
+ !in->deleted)
+ {
+ in->deleted = 1;
+ in->myDev->nDeletedFiles++;
+ yaffs_SoftDeleteFile(in);
+ }
+ return in->deleted ? YAFFS_OK : YAFFS_FAIL;
}
- if(retVal == YAFFS_OK &&
- in->unlinked &&
- !in->deleted)
+ else
{
- in->deleted = 1;
- in->myDev->nDeletedFiles++;
+ // The file has no data chunks so we toss it immediately
+ yaffs_FreeTnode(in->myDev,in->variant.fileVariant.top);
+ in->variant.fileVariant.top = NULL;
+ yaffs_DoGenericObjectDeletion(in);
+
+ return YAFFS_OK;
}
- return in->deleted ? YAFFS_OK : YAFFS_FAIL;
}
static int yaffs_DeleteDirectory(yaffs_Object *in)
@@ -3536,6 +3754,20 @@ static int yaffs_DeleteHardLink(yaffs_Object *in)
}
+static void yaffs_AbortHalfCreatedObject(yaffs_Object *obj)
+{
+ switch(obj->variantType)
+ {
+ case YAFFS_OBJECT_TYPE_FILE: yaffs_DeleteFile(obj); break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY: yaffs_DeleteDirectory(obj); break;
+ case YAFFS_OBJECT_TYPE_SYMLINK: yaffs_DeleteSymLink(obj); break;
+ case YAFFS_OBJECT_TYPE_HARDLINK: yaffs_DeleteHardLink(obj); break;
+ case YAFFS_OBJECT_TYPE_SPECIAL: yaffs_DoGenericObjectDeletion(obj); break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN: break; // should not happen.
+ }
+}
+
+
static int yaffs_UnlinkWorker(yaffs_Object *obj)
{
@@ -3687,8 +3919,9 @@ static int yaffs_Scan(yaffs_Device *dev)
{
deleted = 0;
bi = yaffs_GetBlockInfo(dev,blk);
- bi->pageBits = 0;
+ yaffs_ClearChunkBits(dev,blk);
bi->pagesInUse = 0;
+ bi->softDeletions = 0;
state = YAFFS_BLOCK_STATE_SCANNING;
@@ -3746,7 +3979,7 @@ static int yaffs_Scan(yaffs_Device *dev)
{
int endpos;
// A data chunk.
- bi->pageBits |= (1 << c);
+ yaffs_SetChunkBit(dev,blk,c);
bi->pagesInUse++;
in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE);
@@ -3769,7 +4002,7 @@ static int yaffs_Scan(yaffs_Device *dev)
{
// chunkId == 0, so it is an ObjectHeader.
// Thus, we read in the object header and make the object
- bi->pageBits |= (1 << c);
+ yaffs_SetChunkBit(dev,blk,c);
bi->pagesInUse++;
yaffs_ReadChunkFromNAND(dev,chunk,chunkData,NULL,1);
@@ -3788,13 +4021,13 @@ static int yaffs_Scan(yaffs_Device *dev)
if(((existingSerial+1) & 3) == newSerial)
{
// Use new one - destroy the exisiting one
- yaffs_DeleteChunk(dev,in->chunkId);
+ yaffs_DeleteChunk(dev,in->chunkId,1);
in->valid = 0;
}
else
{
// Use existing - destroy this one.
- yaffs_DeleteChunk(dev,chunk);
+ yaffs_DeleteChunk(dev,chunk,1);
}
}
@@ -3868,7 +4101,7 @@ static int yaffs_Scan(yaffs_Device *dev)
// Hoosterman, another problem....
// We're trying to use a non-directory as a directory
// Todo ... handle
- T(YAFFS_TRACE_ERROR, (TSTR("yaffs tradgedy: attempting to use non-directory as a directory in scan" TENDSTR)));
+ T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan" TENDSTR)));
}
@@ -3896,7 +4129,7 @@ static int yaffs_Scan(yaffs_Device *dev)
break;
case YAFFS_OBJECT_TYPE_HARDLINK:
in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId;
- (yaffs_Object *)(in->hardLinks.next) = hardList;
+ in->hardLinks.next = (struct list_head *)hardList;
hardList = in;
break;
case YAFFS_OBJECT_TYPE_DIRECTORY: // Do nothing
@@ -3956,6 +4189,19 @@ static int yaffs_Scan(yaffs_Device *dev)
}
+ {
+ struct list_head *i;
+ yaffs_Object *l;
+ // Soft delete all the unlinked files
+ list_for_each(i,&dev->unlinkedDir->variant.directoryVariant.children)
+ {
+ l = list_entry(i, yaffs_Object,siblings);
+ if(l->deleted)
+ {
+ yaffs_SoftDeleteFile(l);
+ }
+ }
+ }
return YAFFS_OK;
@@ -4291,6 +4537,14 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs_CheckStructures failed\n" TENDSTR)));
return YAFFS_FAIL;
}
+
+ if(dev->isMounted)
+ {
+ T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: device already mounted\n" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ dev->isMounted = 1;
if(dev->startBlock <= 0 ||
(dev->endBlock - dev->startBlock) < 10)
@@ -4332,6 +4586,10 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
}
dev->chunkGroupSize = 1 << dev->chunkGroupBits;
+ // Stuff to be taken out later
+ dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+ dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+
// More device initialisation
dev->garbageCollectionRequired = 0;
@@ -4348,7 +4606,10 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
dev->tagsEccFixed=0;
dev->tagsEccUnfixed=0;
- dev->localBuffer = YMALLOC(YAFFS_BYTES_PER_CHUNK);
+ dev->localBuffer = YMALLOC(dev->nBytesPerChunk);
+
+
+
yaffs_InitialiseBlocks(dev,nBlocks);
@@ -4356,10 +4617,18 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
yaffs_InitialiseObjects(dev);
-#ifdef CONFIG_YAFFS_SHORT_OP_CACHE
+ if(dev->nShortOpCaches > 0)
{
int i;
- for(i=0; i < YAFFS_N_CACHE_CHUNKS; i++)
+
+ if(dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES)
+ {
+ dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
+ }
+
+ dev->srCache = YMALLOC( dev->nShortOpCaches * sizeof(yaffs_ChunkCache));
+
+ for(i=0; i < dev->nShortOpCaches; i++)
{
dev->srCache[i].object = NULL;
dev->srCache[i].lastUse = 0;
@@ -4367,7 +4636,6 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
}
dev->srLastUse = 0;
}
-#endif
dev->cacheHits = 0;
@@ -4400,12 +4668,18 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
void yaffs_Deinitialise(yaffs_Device *dev)
{
- yaffs_DeinitialiseBlocks(dev);
- yaffs_DeinitialiseTnodes(dev);
- yaffs_DeinitialiseObjects(dev);
+ if(dev->isMounted)
+ {
+
+ yaffs_DeinitialiseBlocks(dev);
+ yaffs_DeinitialiseTnodes(dev);
+ yaffs_DeinitialiseObjects(dev);
+ }
}
+#if 0
+
int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
{
int nFree = dev->nFreeChunks - (YAFFS_CHUNKS_PER_BLOCK * YAFFS_RESERVED_BLOCKS);
@@ -4424,13 +4698,75 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
nFree += l->nDataChunks;
}
}
+
+
+ printf("___________ nFreeChunks is %d nFree is %d\n",dev->nFreeChunks,nFree);
+
+ if(nFree < 0) nFree = 0;
+
+ return nFree;
+
+}
+
+#endif
+
+int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
+{
+ int nFree;
+ int pending;
+ int b;
+
+ yaffs_BlockInfo *blk;
+
+ struct list_head *i;
+ yaffs_Object *l;
+
+ for(nFree = 0, b = dev->startBlock; b <= dev->endBlock; b++)
+ {
+ blk = yaffs_GetBlockInfo(dev,b);
+
+ switch(blk->blockState)
+ {
+ case YAFFS_BLOCK_STATE_EMPTY:
+ case YAFFS_BLOCK_STATE_ALLOCATING:
+ case YAFFS_BLOCK_STATE_FULL: nFree += (dev->nChunksPerBlock - blk->pagesInUse); break;
+ default: break;
+ }
+ }
+
+
+ pending = 0;
+
+ // To the free chunks add the chunks that are in the deleted unlinked files.
+ list_for_each(i,&dev->unlinkedDir->variant.directoryVariant.children)
+ {
+ l = list_entry(i, yaffs_Object,siblings);
+ if(l->deleted)
+ {
+ pending++;
+ pending += l->nDataChunks;
+ }
+ }
+
+
+
+ //printf("___________ really free is %d, pending %d, nFree is %d\n",nFree,pending, nFree+pending);
+
+ if(nFree != dev->nFreeChunks)
+ {
+ // printf("___________Different! really free is %d, nFreeChunks %d\n",nFree dev->nFreeChunks);
+ }
+ nFree += pending;
+
+ if(nFree < 0) nFree = 0;
- return (nFree < 0) ? 0 : nFree;
+ return nFree;
}
+
/////////////////// YAFFS test code //////////////////////////////////
#define yaffs_CheckStruct(structure,syze, name) \
@@ -4446,7 +4782,9 @@ static int yaffs_CheckStructures(void)
yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags")
yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion")
yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare")
+#ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
yaffs_CheckStruct(yaffs_Tnode,2* YAFFS_NTNODES_LEVEL0,"yaffs_Tnode")
+#endif
yaffs_CheckStruct(yaffs_ObjectHeader,512,"yaffs_ObjectHeader")
diff --git a/yaffs_guts.h b/yaffs_guts.h
index 3ab41f7..0fe8f74 100644
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -14,7 +14,7 @@
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*
- * $Id: yaffs_guts.h,v 1.13 2002-12-13 00:13:06 charles Exp $
+ * $Id: yaffs_guts.h,v 1.14 2003-01-14 23:15:32 charles Exp $
*/
#ifndef __YAFFS_GUTS_H__
@@ -42,10 +42,11 @@
#define YAFFS_TNODES_INTERNAL_MASK 0x7
#define YAFFS_TNODES_MAX_LEVEL 6
+#define YAFFS_BYTES_PER_SPARE 16
+
#define YAFFS_BYTES_PER_CHUNK 512
-#define YAFFS_CHUNK_SIZE_SHIFT 9
+//#define YAFFS_CHUNK_SIZE_SHIFT 9
-#define YAFFS_BYTES_PER_SPARE 16
#define YAFFS_CHUNKS_PER_BLOCK 32
#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
@@ -73,14 +74,7 @@
#define YAFFS_OBJECTID_LOSTNFOUND 2
#define YAFFS_OBJECTID_UNLINKED 3
-#define YAFFS_N_CACHE_CHUNKS 10
-
-#ifdef CONFIG_YAFFS_WINCE
-
-// Force the short operation cache on for WinCE
-
-#define CONFIG_YAFFS_SHORT_OP_CACHE
-#endif
+#define YAFFS_MAX_SHORT_OP_CACHES 20
// ChunkCache is used for short read/write operations.
@@ -90,11 +84,12 @@ typedef struct
int chunkId;
int lastUse;
int dirty;
+ int nBytes; // Only valid if the cache is dirty
__u8 data[YAFFS_BYTES_PER_CHUNK];
} yaffs_ChunkCache;
// Tags structures in RAM
-// NB This uses bitfield. Bitfields should not stradle a u32 boundary otherwise
+// NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise
// the structure size will get blown out.
typedef struct
@@ -131,10 +126,17 @@ typedef struct
__u8 ecc2[3];
} yaffs_Spare;
+//Special structure for passing through to mtd
+struct yaffs_NANDSpare {
+ yaffs_Spare spare;
+ int eccres1;
+ int eccres2;
+};
+
// Block data in RAM
typedef enum {
- YAFFS_BLOCK_STATE_UddNKNOWN = 0,
+ YAFFS_BLOCK_STATE_UNKNOWN = 0,
YAFFS_BLOCK_STATE_SCANNING, // Used while the block is being scanned.
// NB Don't erase blocks while they're being scanned
@@ -151,7 +153,7 @@ typedef enum {
YAFFS_BLOCK_STATE_DIRTY, // All pages have been allocated and deleted.
// Erase me, reuse me.
- YAFFS_BLOCK_STATE_DEAD = 0x77 // This block has failed and is not in use
+ YAFFS_BLOCK_STATE_DEAD // This block has failed and is not in use
} yaffs_BlockState;
@@ -160,10 +162,13 @@ typedef enum {
typedef struct
{
- __u32 pageBits; // bitmap of pages in use
- __u8 blockState; // One of the above block states
- __u8 pagesInUse; // number of pages in use
- __u8 needsRetiring:1; // Data has failed on this block, need to get valid data off
+#ifndef CONFIG_YAFFS_NO_YAFFS2
+ __u32 sequenceNumber; // block sequence number for yaffs2
+#endif
+ int softDeletions:8; // number of soft deleted pages
+ int pagesInUse:8; // number of pages in use
+ __u32 blockState:4; // One of the above block states
+ __u32 needsRetiring:1; // Data has failed on this block, need to get valid data off
// and retire the block.
} yaffs_BlockInfo;
@@ -231,7 +236,11 @@ typedef struct
union yaffs_Tnode_union
{
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL+1];
+#else
union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];
+#endif
__u16 level0[YAFFS_NTNODES_LEVEL0];
};
@@ -292,6 +301,7 @@ typedef union
struct yaffs_ObjectStruct
{
__u8 deleted: 1; // This should only apply to unlinked files.
+ __u8 softDeleted: 1; // it has also been soft deleted
__u8 unlinked: 1; // An unlinked file. The file should be in the unlinked pseudo directory.
__u8 fake:1; // A fake object has no presence on NAND.
__u8 renameAllowed:1;
@@ -331,9 +341,11 @@ struct yaffs_ObjectStruct
char shortName[YAFFS_SHORT_NAME_LENGTH+1];
#endif
-#ifdef CONFIG_YAFFS_WINCE
+#ifndef __KERNEL__
__u32 inUse;
+#endif
+#ifdef CONFIG_YAFFS_WINCE
__u32 win_ctime[2];
__u32 win_mtime[2];
__u32 win_atime[2];
@@ -343,9 +355,9 @@ struct yaffs_ObjectStruct
__u32 st_atime; // time of last access
__u32 st_mtime; // time of last modification
__u32 st_ctime; // time of last change
- __u32 st_rdev; // device stuff for block and char devices
#endif
+ __u32 st_rdev; // device stuff for block and char devices
@@ -386,23 +398,19 @@ typedef struct
struct yaffs_DeviceStruct
{
// Entry parameters set up way early. Yaffs sets up the rest.
+ int nBytesPerChunk; // Should be a power of 2 >= 512
+ int nChunksPerBlock;
int startBlock; // Start block we're allowed to use
int endBlock; // End block we're allowed to use
- __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16
- __u16 chunkGroupSize; // == 2^^chunkGroupBits
+
+ int useNANDECC; // Flag to decide whether or not to use NANDECC
+ int nShortOpCaches; // If <= 0, then short op caching is disabled, else
+ // the number of short op caches (don't use too many).
void *genericDevice; // Pointer to device context
// On an mtd this holds the mtd pointer.
-
-#ifdef __KERNEL__
-
- struct semaphore sem;// Semaphore for waiting on erasure.
- struct semaphore grossLock; // Gross locking semaphore
-#endif
-
-
// NAND access functions (Must be set before calling YAFFS)
int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare);
@@ -410,16 +418,34 @@ struct yaffs_DeviceStruct
int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND);
int (*initialiseNAND)(struct yaffs_DeviceStruct *dev);
+ // Runtime parameters. Set up by YAFFS.
+
+ __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16
+ __u16 chunkGroupSize; // == 2^^chunkGroupBits
+
+#ifdef __KERNEL__
+
+ struct semaphore sem;// Semaphore for waiting on erasure.
+ struct semaphore grossLock; // Gross locking semaphore
+
+#endif
#ifdef __KERNEL__
void (*putSuperFunc)(struct super_block *sb);
#endif
- // Runtime parameters.
+ int isMounted;
+
+ // Block Info
yaffs_BlockInfo *blockInfo;
+ __u8 *chunkBits; // bitmap of chunks in use
+ int chunkBitmapStride; // Number of bytes of chunkBits per block.
+ // Must be consistent with nChunksPerBlock.
+
+
int nErasedBlocks;
- int allocationBlock;
+ int allocationBlock; // Current block being allocated off
__u32 allocationPage;
- int allocationBlockFinder;
+ int allocationBlockFinder; // Used to search for next allocation block
// Runtime state
int nTnodesCreated;
@@ -454,22 +480,23 @@ struct yaffs_DeviceStruct
int eccUnfixed;
int tagsEccFixed;
int tagsEccUnfixed;
+ int nDeletions;
+ int nUnmarkedDeletions;
yaffs_Object *rootDir;
yaffs_Object *lostNFoundDir;
// Buffer areas for storing data to recover from write failures
- __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
- yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
+// __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
+// yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
int bufferedBlock; // Which block is buffered here?
int doingBufferedBlockRewrite;
int blockSelectedForGC;
-#ifdef CONFIG_YAFFS_SHORT_OP_CACHE
- yaffs_ChunkCache srCache[YAFFS_N_CACHE_CHUNKS];
+ yaffs_ChunkCache *srCache;
int srLastUse;
-#endif
+
int cacheHits;
// Stuff for background deletion and unlinked files.
@@ -519,7 +546,7 @@ int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, __u32 offset, i
int yaffs_ResizeFile(yaffs_Object *obj, int newSize);
yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid);
-int yaffs_FlushFile(yaffs_Object *obj);
+int yaffs_FlushFile(yaffs_Object *obj,int updateTime);
// Directory operations
@@ -560,3 +587,4 @@ void yaffs_GutsTest(yaffs_Device *dev);
#endif
+
diff --git a/yaffs_mtdif.c b/yaffs_mtdif.c
index 5505d55..14876c8 100644
--- a/yaffs_mtdif.c
+++ b/yaffs_mtdif.c
@@ -13,7 +13,7 @@
*
*/
-const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.5 2002-12-13 00:13:06 charles Exp $";
+const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.6 2003-01-14 23:15:32 charles Exp $";
#ifdef CONFIG_YAFFS_MTD_ENABLED
@@ -42,11 +42,10 @@ int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data,
#ifndef CONFIG_YAFFS_USE_OLD_MTD
if(data && spare)
{
-#ifdef CONFIG_YAFFS_USE_NANDECC
- retval = mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_YAFFS_OOB);
-#else
- retval = mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB);
-#endif
+ if(dev->useNANDECC)
+ mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_YAFFS_OOB);
+ else
+ mtd->write_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB);
}
else
{
@@ -78,13 +77,16 @@ int nandmtd_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaf
#ifndef CONFIG_YAFFS_USE_OLD_MTD
if(data && spare)
{
-#ifdef CONFIG_YAFFS_USE_NANDECC
- u8 tmpSpare[ YAFFS_BYTES_PER_SPARE + (2*sizeof(int)) ];
- retval = mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,tmpSpare,NAND_YAFFS_OOB);
- memcpy(spareAsBytes, tmpSpare, YAFFS_BYTES_PER_SPARE);
-#else
- retval = mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB);
-#endif
+ if(dev->useNANDECC)
+ {
+ u8 tmpSpare[ YAFFS_BYTES_PER_SPARE + (2*sizeof(int)) ];
+ retval = mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,tmpSpare,NAND_YAFFS_OOB);
+ memcpy(spareAsBytes, tmpSpare, YAFFS_BYTES_PER_SPARE);
+ }
+ else
+ {
+ retval = mtd->read_ecc(mtd,addr,YAFFS_BYTES_PER_CHUNK,&dummy,data,spareAsBytes,NAND_NONE_OOB);
+ }
}
else
{
diff --git a/yaffsdev.c b/yaffsdev.c
index c44715b..f325b78 100644
--- a/yaffsdev.c
+++ b/yaffsdev.c
@@ -111,7 +111,7 @@ void TestTimeasasas(yaffs_Device *dev)
printf("Flush\n");
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
@@ -129,7 +129,7 @@ void TestTimeasasas(yaffs_Device *dev)
yaffs_DumpObject(f);
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
@@ -187,7 +187,7 @@ void TestTimeBigDeletes(yaffs_Device *dev)
written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
}
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
yaffs_DeleteFile(f);
f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
@@ -211,7 +211,7 @@ void TestTimeBigDeletes(yaffs_Device *dev)
written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
}
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
yaffs_DeleteFile(f);
f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
@@ -235,7 +235,7 @@ void TestTimeBigDeletes(yaffs_Device *dev)
written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
}
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
yaffs_DeleteFile(f);
}
@@ -392,7 +392,7 @@ void TestTime(yaffs_Device *dev)
printf("Flush\n");
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
yaffs_ReadDataFromFile(f,data,1000,50);
data[50] = 0;
@@ -443,7 +443,7 @@ void TestTime(yaffs_Device *dev)
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename"));
@@ -573,7 +573,7 @@ void TestTimeDeleteFocussed(yaffs_Device *dev)
- yaffs_FlushFile(f);
+ yaffs_FlushFile(f,1);
printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename"));
@@ -629,6 +629,56 @@ void TestTimeTnodeFocussed(yaffs_Device *dev)
written = yaffs_WriteDataToFile(f,testStr2,0,strlen(testStr2));
}
+}
+void TestTimeBackgroundDeleteFocussed(yaffs_Device *dev)
+{
+ yaffs_Object *f;
+ yaffs_Object *lnf;
+
+
+ int x;
+ int i,j;
+ int b;
+ int written;
+
+
+ printf("Exisiting objects\n");
+ yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
+ printf("Exisiting objects in lost+found\n");
+ lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
+ yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject);
+
+ printf("Start\n");
+
+
+ for(j = 0; j < 20; j++)
+ {
+ printf("Run %d\n",j);
+
+ f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
+ if(f)
+ {
+ printf("Found\n");
+ }
+ else
+ {
+ f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
+ printf("Created\n");
+ }
+
+ printf("@@@@@@@ Run %d, object %d\n",j,f->objectId);
+
+ for(i = 0; i < 1000000; i+=20)
+ {
+
+ written = yaffs_WriteDataToFile(f,testStr,i,100);
+ }
+
+ yaffs_FlushFile(f,1);
+
+ yaffs_DeleteFile(f);
+ }
+
}
int main(int argc,char *argv[])
@@ -637,7 +687,7 @@ int main(int argc,char *argv[])
int nBlocks;
#if YAFFS_FILEEM
- nBlocks =(4 * 1024 * 1024) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK) ;
+ nBlocks =(2 * 1024 * 1024) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK) ;
device.writeChunkToNAND = yaffs_FEWriteChunkToNAND;
device.readChunkFromNAND = yaffs_FEReadChunkFromNAND;
device.eraseBlockInNAND = yaffs_FEEraseBlockInNAND;
@@ -662,14 +712,20 @@ int main(int argc,char *argv[])
device.endBlock = nBlocks;
#endif
+ device.nShortOpCaches = 10;
+
+
yaffs_GutsInitialise(&device);
// yaffs_GutsTest();
- TestTime(&device);
+ TestTimeBackgroundDeleteFocussed(&device);
printf("Cache hits %d\n",device.cacheHits);
printf("Retired blocks %d\n",device.nRetiredBlocks);
+ printf("Deletions %d\n",device.nDeletions);
+ printf("Unmarked deletions %d\n",device.nUnmarkedDeletions);
+
exit(0);
}
diff --git a/yaffsdev.proj b/yaffsdev.proj
index 770d67c5c763dffc2423e8bee0a725bda635b61e..fa40e294daa7c7730fda1cf8e35ce49bf0e8c1f3 100644
GIT binary patch
delta 2201
zcmb7FUu;uV7;o2eJLmxS2iRbYovpw+y0Lq2*Ork<*w$@;Fpw3R@?g2`y?49r_FldB
zc5K!nBPKqG3GkU{G?AeaBZ)J$JQ#g2L?yl$<;fQk+?zr|NYrQ~QO~(;*(QT%n%?uB
z?>pbW-}jyKot|}_o^_quRdM@7zSp%0W-c}|qGC=s3W-f$dzm}VYtB1`_C2SZp6rw%
z$vB&pGw@lw3Eqv=d3i1r-obJlRu+VKT99QkF=R+mRMSP6A6$#ra3}!Jzqrv?lu^Ef
zx94y;+_Qtr<#17Zks{1bcfrR8ni0pcVYs)q8QwU!0dXAL4XY3CUGX1{haPQwO+-Jc
zsfsosi9?Di!CR3=#Pgw@B+3n)Im`!G?jhx+DiKMQEJfEqc%h?mX|h3f*<^#khfLau
z*vY;c@wC~jeJ?t&$?UPQ;f}7_SU5t;}$kZ~G48#16
z?x9=gCc2KkLRZlz=n}e!&ZD#FWpoBP8yt>%t~01`;Y4o*oKMyJMP7iu_yE{U_`A9r{4Fjl&gO7$W-v7$@@w`VHMh
zdr$!RP(50QT*!%jb^YS1SmAJ7CTsr2&5A(wq@s!XNgN=?gB%X_usGBmpz9P_{eDXtXann7~IxQN$VgF)c$7
zRS65Ks;30{{`C`L0?WE#vozg78$;LBX@?iI(T(6fvWYr)$r6k)$-9el$1*0
zEZlg1+}Q>B%U$F2_Ir?{a(F
zF=}Nb{xG2O@y29CLq_;8LLib76JtU$jX#W)va1SyT3??DHGI;vY+fhp<}=oP(KPFU42>Ejq(7>oPM#l9DWO1;na8?oQ>AOEjrf;
zy_uWhVIBN!HNXdhD`3*n0yhVZ@J^&*l`P0&OcO%`vZPT@NO1!5Q=5$cE`#1+ADoLk
zZ7wi(6G8M(CTMQZ$S`tk36keqVD&^ZoR73r#%E(JlfZs({nGqg#A5KPM9|0xjRJ|o
zqt*?j0A;M$p3ve;hCr=t<70^Kpw+<6?h`a2Ys`YR5xQ&!#IlwO;l{PqOmlXm3M+P#
zxOA8RrB&yq1>%F|VK7cqfn~cH>TC^kG$Bhw1ba)feoU1#!j2eG*iK{7I=8(MPDquo
zQsUwL=I7e{lO#OFtj2u4I3iM%kXUD!mJAUozQmwz#o4_FHuadqJUbxC;?Vd(64rdP
zfLl$lUs`D{27`&%I8k%fS!;q)nB?h+@D$PLeH)(yPfc3&rFxqT#X8~n)@HcYQmrpi
z1&b{k4Ml4W6lqN+9evPLJ+EJ2|a^9XRXo)U+@`^3Hd8+?f3-
z7L~lqY5q%*&M=-<;@HJ^I&fU0nTcgZjWr5UtR&SL7EMhUXX%5xu|j(up-`HBpbW1C
z!-ei6BNjZvQYFl4LsM|JC3bY+RK5UkSS4w^Z>M)~aLAuOxsN1i{BTqW3sD~)CR)zl
zK_N!4(_wevT##_CR)S=P%5hjp$Qt&F;*iS3SW~8>IKD*_RLzHJtMg%Rlxft69}}8P
zk!;4|_@tt0A!VA`L1iLNQAJUaUQ>g67bY`zFF!;O8Z*M2*90G3X@?R+jzN*Dt#MTR?X}*Si&r05Tov`iXYFc%_4#Q1e)CCX8I#
zoKNg?lme7tjLTHk79@@&r=kXg;=Y_BwypjpeI<7zd$VX3Of1rlb*wivPo
n(8t7sZB__fUB~3`#a=5HPziz8_Ih#?ion~WcQQX*Yi#@nD=N4K
diff --git a/yportenv.h b/yportenv.h
index 943cffe..b330375 100644
--- a/yportenv.h
+++ b/yportenv.h
@@ -15,7 +15,7 @@
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*
- * $Id: yportenv.h,v 1.7 2002-11-26 01:15:37 charles Exp $
+ * $Id: yportenv.h,v 1.8 2003-01-14 23:15:41 charles Exp $
*
*/
@@ -30,6 +30,8 @@
#include "stdio.h"
#include "string.h"
+#define CONFIG_YAFFS_CASE_INSENSITIVE
+
#define YMALLOC(x) malloc(x)
#define YFREE(x) free(x)
@@ -100,9 +102,44 @@ extern unsigned yfsd_U32FileTimeNow(void);
#define TOUT(p) printk p
-#else
+#elif defined CONFIG_YAFFS_DIRECT
+
+// Directct interface
+
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+
+#define YMALLOC(x) malloc(x)
+#define YFREE(x) free(x)
+
+
+//#define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s))
+//#define YALERT(s) YINFO(s)
+
+
+#define TENDSTR "\n"
+#define TSTR(x) x
+#define TOUT(p) printf p
+
+
+#define YAFFS_LOSTNFOUND_NAME "lost+found"
+#define YAFFS_LOSTNFOUND_PREFIX "obj"
+//#define YPRINTF(x) printf x
+
+#include "yaffscfg.h"
+
+#define CURRENT_TIME yaffsfs_CurrentTime()
+#define YAFFS_ROOT_MODE 0666
+#define YAFFS_LOSTNFOUND_MODE 0666
+
+#define yaffs_SumCompare(x,y) ((x) == (y))
+#define yaffs_strcmp(a,b) strcmp(a,b)
+
+#elif defined CONFIG_YAFFS_UTIL
+
+// Stuff for YAFFS utilities
-// Linux application
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
@@ -124,6 +161,7 @@ extern unsigned yfsd_U32FileTimeNow(void);
#define YAFFS_LOSTNFOUND_PREFIX "obj"
//#define YPRINTF(x) printf x
+
#define CURRENT_TIME 0
#define YAFFS_ROOT_MODE 0666
#define YAFFS_LOSTNFOUND_MODE 0666
@@ -131,6 +169,10 @@ extern unsigned yfsd_U32FileTimeNow(void);
#define yaffs_SumCompare(x,y) ((x) == (y))
#define yaffs_strcmp(a,b) strcmp(a,b)
+#else
+// Should have specified a configuration type
+#error Unknown configuration
+
#endif
--
2.30.2