summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcharles <charles>2008-05-05 07:58:58 +0000
committercharles <charles>2008-05-05 07:58:58 +0000
commite8cfe05cf0d057f6978c37943e51b17bb14664e3 (patch)
treed01ecd0a0c1b25110e11b906f109fd27475136ef
parent02d566cf1ffdd2d91d4abbaf106ef4fb3affbdc6 (diff)
Check in inband tags, some extra yaffs direct functions and some other changes
-rw-r--r--devextras.h68
-rw-r--r--direct/Makefile12
-rw-r--r--direct/dtest.c153
-rw-r--r--direct/fsx_test/Makefile8
-rw-r--r--direct/fsx_test/yaffs_fsx.c11
-rw-r--r--direct/yaffs_fileem2k.c284
-rw-r--r--direct/yaffs_flashif.h4
-rw-r--r--direct/yaffs_ramdisk.c4
-rw-r--r--direct/yaffs_ramdisk.h2
-rw-r--r--direct/yaffs_ramem2k.c6
-rw-r--r--direct/yaffscfg2k.c25
-rw-r--r--direct/yaffsfs.c640
-rw-r--r--direct/yaffsfs.h87
-rw-r--r--direct/ydirectenv.h5
-rw-r--r--yaffs_checkptrw.c6
-rw-r--r--yaffs_fs.c100
-rw-r--r--yaffs_guts.c302
-rw-r--r--yaffs_guts.h61
-rw-r--r--yaffs_mtdif2.c132
-rw-r--r--yaffs_nand.c5
-rw-r--r--yaffs_nandemul2k.h4
-rw-r--r--yaffs_packedtags2.c130
-rw-r--r--yaffs_packedtags2.h5
-rw-r--r--yaffs_tagscompat.c9
-rw-r--r--yaffs_tagscompat.h5
-rw-r--r--yportenv.h4
26 files changed, 1381 insertions, 691 deletions
diff --git a/devextras.h b/devextras.h
index 2ba88a2..55c3121 100644
--- a/devextras.h
+++ b/devextras.h
@@ -23,31 +23,29 @@
#ifndef __EXTRAS_H__
#define __EXTRAS_H__
-#if defined WIN32
-#define __inline__ __inline
-#define new newHack
-#endif
-#if !(defined __KERNEL__) || (defined WIN32)
+#if !(defined __KERNEL__)
/* Definition of types */
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned __u32;
+#endif
+
/*
* This is a simple doubly linked list implementation that matches the
* way the Linux kernel doubly linked list implementation works.
*/
-struct list_head {
- struct list_head *next; /* next in chain */
- struct list_head *prev; /* previous in chain */
+struct ylist_head {
+ struct ylist_head *next; /* next in chain */
+ struct ylist_head *prev; /* previous in chain */
};
/* Initialise a list head to an empty list */
-#define INIT_LIST_HEAD(p) \
+#define YINIT_LIST_HEAD(p) \
do { \
(p)->next = (p);\
(p)->prev = (p); \
@@ -55,10 +53,10 @@ do { \
/* Add an element to a list */
-static __inline__ void list_add(struct list_head *newEntry,
- struct list_head *list)
+static __inline__ void ylist_add(struct ylist_head *newEntry,
+ struct ylist_head *list)
{
- struct list_head *listNext = list->next;
+ struct ylist_head *listNext = list->next;
list->next = newEntry;
newEntry->prev = list;
@@ -70,52 +68,63 @@ static __inline__ void list_add(struct list_head *newEntry,
/* Take an element out of its current list, with or without
* reinitialising the links.of the entry*/
-static __inline__ void list_del(struct list_head *entry)
+static __inline__ void ylist_del(struct ylist_head *entry)
{
- struct list_head *listNext = entry->next;
- struct list_head *listPrev = entry->prev;
+ struct ylist_head *listNext = entry->next;
+ struct ylist_head *listPrev = entry->prev;
listNext->prev = listPrev;
listPrev->next = listNext;
}
-static __inline__ void list_del_init(struct list_head *entry)
+static __inline__ void ylist_del_init(struct ylist_head *entry)
{
- list_del(entry);
+ ylist_del(entry);
entry->next = entry->prev = entry;
}
/* Test if the list is empty */
-static __inline__ int list_empty(struct list_head *entry)
+static __inline__ int ylist_empty(struct ylist_head *entry)
{
return (entry->next == entry);
}
-/* list_entry takes a pointer to a list entry and offsets it to that
+/* ylist_entry takes a pointer to a list entry and offsets it to that
* we can find a pointer to the object it is embedded in.
*/
-#define list_entry(entry, type, member) \
+#define ylist_entry(entry, type, member) \
((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
-/* list_for_each and list_for_each_safe iterate over lists.
- * list_for_each_safe uses temporary storage to make the list delete safe
+/* ylist_for_each and list_for_each_safe iterate over lists.
+ * ylist_for_each_safe uses temporary storage to make the list delete safe
*/
-#define list_for_each(itervar, list) \
+#define ylist_for_each(itervar, list) \
for (itervar = (list)->next; itervar != (list); itervar = itervar->next )
-#define list_for_each_safe(itervar,saveVar, list) \
+#define ylist_for_each_safe(itervar,saveVar, list) \
for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \
itervar = saveVar, saveVar = saveVar->next)
+
+#if !(defined __KERNEL__)
+
+
+#ifndef WIN32
+#include <sys/stat.h>
+#endif
+
+
+#ifdef CONFIG_YAFFS_PROVIDE_DEFS
/* File types */
+
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
@@ -124,7 +133,7 @@ static __inline__ int list_empty(struct list_head *entry)
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
-#define DR_WHT 14
+#define DT_WHT 14
#ifndef WIN32
@@ -155,21 +164,18 @@ struct iattr {
unsigned int ia_attr_flags;
};
+#endif
+
+
#define KERN_DEBUG
#else
-#ifndef WIN32
#include <linux/types.h>
-#include <linux/list.h>
#include <linux/fs.h>
#include <linux/stat.h>
-#endif
#endif
-#if defined WIN32
-#undef new
-#endif
#endif
diff --git a/direct/Makefile b/direct/Makefile
index dd6b61d..a65c0e6 100644
--- a/direct/Makefile
+++ b/direct/Makefile
@@ -14,12 +14,14 @@
#
# NB Warning this Makefile does not include header dependencies.
#
-# $Id: Makefile,v 1.15 2007-07-18 19:40:38 charles Exp $
+# $Id: Makefile,v 1.16 2008-05-05 07:58:58 charles Exp $
#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
-CFLAGS = -Wall -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -g $(EXTRA_COMPILE_FLAGS) -DNO_Y_INLINE
-CFLAGS+= -fstack-check -O0
+CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2
+CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE
+CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS)
+#CFLAGS+= -fstack-check -O0
#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
@@ -40,7 +42,7 @@ ALLOBJS = $(DIRECTTESTOBJS) $(BOOTTESTOBJS)
SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_nandemul2k.h \
- yaffs_nand.c yaffs_nand.h \
+ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
yaffs_qsort.c yaffs_qsort.h
@@ -49,7 +51,7 @@ SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsin
all: directtest2k
$(ALLOBJS): %.o: %.c
- gcc -c $(CFLAGS) $< -o $@
+ gcc -c $(CFLAGS) -o $@ $<
$(SYMLINKS):
ln -s ../$@ $@
diff --git a/direct/dtest.c b/direct/dtest.c
index be492b4..6f6da74 100644
--- a/direct/dtest.c
+++ b/direct/dtest.c
@@ -1,7 +1,7 @@
/*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
*
- * Copyright (C) 2002-2007 Aleph One Ltd.
+ * Copyright (C) 2002 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -9,11 +9,10 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
+ *
*/
-/*
-* Test code for the "direct" interface.
-*/
+
#include <stdio.h>
@@ -125,9 +124,7 @@ int check_pattern_file(char *fn)
int dump_file_data(char *fn)
{
int h;
- int marker;
int i = 0;
- int size;
int ok = 1;
unsigned char b;
@@ -178,6 +175,7 @@ void create_file_of_size(const char *fn,int syze)
{
int h;
int n;
+ int result;
char xx[200];
@@ -188,7 +186,10 @@ void create_file_of_size(const char *fn,int syze)
while (iterations > 0)
{
sprintf(xx,"%s %8d",fn,iterations);
- yaffs_write(h,xx,strlen(xx));
+ n = strlen(xx);
+ result = yaffs_write(h,xx,n);
+ if(result != n)
+ printf("Wrote %d, should have been %d\n",result,n);
iterations--;
}
yaffs_close (h);
@@ -197,7 +198,7 @@ void create_file_of_size(const char *fn,int syze)
void verify_file_of_size(const char *fn,int syze)
{
int h;
- int n;
+ int result;
char xx[200];
char yy[200];
@@ -212,11 +213,11 @@ void verify_file_of_size(const char *fn,int syze)
sprintf(xx,"%s %8d",fn,iterations);
l = strlen(xx);
- yaffs_read(h,yy,l);
+ result = yaffs_read(h,yy,l);
yy[l] = 0;
if(strcmp(xx,yy)){
- printf("=====>>>>> verification of file %s failed near position %d\n",fn,yaffs_lseek(h,0,SEEK_CUR));
+ printf("=====>>>>> verification of file %s failed near position %lld\n",fn,(long long)yaffs_lseek(h,0,SEEK_CUR));
}
iterations--;
}
@@ -226,8 +227,6 @@ void verify_file_of_size(const char *fn,int syze)
void create_resized_file_of_size(const char *fn,int syze1,int reSyze, int syze2)
{
int h;
- int n;
-
int iterations;
@@ -240,7 +239,7 @@ void create_resized_file_of_size(const char *fn,int syze1,int reSyze, int syze2)
iterations--;
}
- yaffs_truncate(h,reSyze);
+ yaffs_ftruncate(h,reSyze);
yaffs_lseek(h,0,SEEK_SET);
iterations = (syze2 + strlen(fn) -1)/ strlen(fn);
@@ -375,7 +374,7 @@ void scan_pattern_test(const char *path, int fsize, int niterations)
}
}
-void fill_disk(char *path,int nfiles)
+void fill_disk(const char *path,int nfiles)
{
int h;
int n;
@@ -401,7 +400,7 @@ void fill_disk(char *path,int nfiles)
}
}
-void fill_disk_and_delete(char *path, int nfiles, int ncycles)
+void fill_disk_and_delete(const char *path, int nfiles, int ncycles)
{
int i,j;
char str[50];
@@ -883,18 +882,12 @@ int huge_directory_test_on_path(char *path)
int f;
int i;
- int r;
+
int total = 0;
int lastTotal = 0;
- char buffer[20];
char str[100];
- char name[100];
- char name2[100];
-
- int h;
- mode_t temp_mode;
- struct yaffs_stat ystat;
+
yaffs_StartUp();
@@ -939,6 +932,7 @@ int huge_directory_test_on_path(char *path)
int yaffs_scan_test(const char *path)
{
+ return 0;
}
@@ -1012,7 +1006,7 @@ int resize_stress_test(const char *path)
syz -= 500;
if(syz < 0) syz = 0;
- yaffs_truncate(a,syz);
+ yaffs_ftruncate(a,syz);
}
else
@@ -1041,6 +1035,7 @@ int resize_stress_test_no_grow_complex(const char *path,int iters)
char abuffer[1000];
char bbuffer[1000];
+
yaffs_StartUp();
@@ -1079,7 +1074,7 @@ int resize_stress_test_no_grow_complex(const char *path,int iters)
syz -= 2050;
if(syz < 0) syz = 0;
- yaffs_truncate(a,syz);
+ yaffs_ftruncate(a,syz);
syz = yaffs_lseek(a,0,SEEK_END);
printf("shrink to %d\n",syz);
}
@@ -1096,7 +1091,8 @@ int resize_stress_test_no_grow_complex(const char *path,int iters)
}
- printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END));
+
+ printf("file size is %lld\n",(long long)yaffs_lseek(a,0,SEEK_END));
}
@@ -1152,7 +1148,7 @@ int resize_stress_test_no_grow(const char *path,int iters)
syz -= 2050;
if(syz < 0) syz = 0;
- yaffs_truncate(a,syz);
+ yaffs_ftruncate(a,syz);
syz = yaffs_lseek(a,0,SEEK_END);
printf("shrink to %d\n",syz);
}
@@ -1169,7 +1165,7 @@ int resize_stress_test_no_grow(const char *path,int iters)
}
- printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END));
+ printf("file size is %lld\n",(long long)yaffs_lseek(a,0,SEEK_END));
}
@@ -1253,7 +1249,6 @@ int cache_bypass_bug_test(void)
// This bug has been fixed.
int a;
- int i;
char buffer1[1000];
char buffer2[1000];
@@ -1327,7 +1322,7 @@ int truncate_test(void)
yaffs_write(a,"abcdefghijklmnopqrstuvwzyz",26);
- yaffs_truncate(a,3);
+ yaffs_ftruncate(a,3);
l= yaffs_lseek(a,0,SEEK_END);
printf("truncated length is %d\n",l);
@@ -1374,13 +1369,10 @@ void lookup_test(const char *mountpt)
int i;
int h;
char a[100];
- char b[100];
yaffs_DIR *d;
yaffs_dirent *de;
- struct yaffs_stat s;
- char str[100];
yaffs_StartUp();
@@ -1441,11 +1433,7 @@ void link_test(const char *mountpt)
char a[100];
char b[100];
char c[100];
-
- int f0;
- int f1;
- int f2;
- int f3;
+
sprintf(a,"%s/aaa",mountpt);
sprintf(b,"%s/bbb",mountpt);
sprintf(c,"%s/ccc",mountpt);
@@ -1482,7 +1470,6 @@ void freespace_test(const char *mountpt)
int i;
int h;
char a[100];
- char b[100];
int f0;
int f1;
@@ -1741,8 +1728,6 @@ void multi_mount_test(const char *mountpt,int nmounts)
{
char a[30];
- char b[30];
- char c[30];
int i;
int j;
@@ -1773,12 +1758,18 @@ void multi_mount_test(const char *mountpt,int nmounts)
sprintf(xx,"%s/1",a);
h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
-
+
+#if 0
for(j = 0; j < 200; j++){
yaffs_write(h0,xx,1000);
yaffs_write(h1,xx,1000);
}
-
+#else
+ while(yaffs_write(h0,xx,1000) > 0){
+
+ yaffs_write(h1,xx,1000);
+ }
+#endif
len0 = yaffs_lseek(h0,0,SEEK_END);
len1 = yaffs_lseek(h1,0,SEEK_END);
@@ -1791,7 +1782,7 @@ void multi_mount_test(const char *mountpt,int nmounts)
}
- yaffs_truncate(h0,0);
+ // yaffs_truncate(h0,0);
yaffs_close(h0);
yaffs_close(h1);
@@ -1808,8 +1799,6 @@ void small_mount_test(const char *mountpt,int nmounts)
{
char a[30];
- char b[30];
- char c[30];
int i;
int j;
@@ -1885,17 +1874,12 @@ void small_overwrite_test(const char *mountpt,int nmounts)
{
char a[30];
- char b[30];
- char c[30];
-
int i;
int j;
int h0;
int h1;
- int len0;
- int len1;
- int nread;
+
sprintf(a,"%s/a",mountpt);
@@ -1921,7 +1905,7 @@ void small_overwrite_test(const char *mountpt,int nmounts)
h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
for(j = 0; j < 1000000; j+=1000){
- yaffs_truncate(h0,j);
+ yaffs_ftruncate(h0,j);
yaffs_lseek(h0,j,SEEK_SET);
yaffs_write(h0,xx,7000);
yaffs_write(h1,xx,7000);
@@ -1941,6 +1925,44 @@ void small_overwrite_test(const char *mountpt,int nmounts)
}
+void seek_overwrite_test(const char *mountpt,int nmounts)
+{
+
+ char a[30];
+
+ int i;
+ int j;
+
+ int h0;
+
+
+ sprintf(a,"%s/f",mountpt);
+
+ yaffs_StartUp();
+
+ yaffs_mount(mountpt);
+
+
+ for(i = 0; i < nmounts; i++){
+
+ h0 = yaffs_open(a, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+
+ for(j = 0; j < 100000; j++){
+ yaffs_lseek(h0,0,SEEK_SET);
+ yaffs_write(h0,xx,5000);
+ yaffs_lseek(h0,0x100000,SEEK_SET);
+ yaffs_write(h0,xx,5000);
+
+ if(early_exit)
+ exit(0);
+ }
+
+ yaffs_close(h0);
+
+ }
+}
+
+
void yaffs_touch(const char *fn)
{
yaffs_chmod(fn, S_IREAD | S_IWRITE);
@@ -2014,7 +2036,7 @@ int make_file2(const char *name1, const char *name2,int syz)
}
yaffs_close(h1);
yaffs_close(h2);
-
+ return 0;
}
@@ -2027,10 +2049,8 @@ void checkpoint_upgrade_test(const char *mountpt,int nmounts)
char b[50];
char c[50];
char d[50];
-
- int i;
+
int j;
- int h;
sprintf(a,"%s/a",mountpt);
@@ -2087,8 +2107,7 @@ void huge_array_test(const char *mountpt,int n)
int i;
- int j;
- int h;
+ int space;
int fnum;
@@ -2104,10 +2123,10 @@ void huge_array_test(const char *mountpt,int n)
n--;
fnum = 0;
printf("\n\n START run\n\n");
- while(yaffs_freespace(mountpt) > 25000000){
+ while((space = yaffs_freespace(mountpt)) > 25000000){
sprintf(a,"%s/file%d",mountpt,fnum);
fnum++;
- printf("create file %s\n",a);
+ printf("create file %s, free space %d\n",a,space);
create_file_of_size(a,10000000);
printf("verifying file %s\n",a);
verify_file_of_size(a,10000000);
@@ -2153,7 +2172,7 @@ void random_truncate(int h, char * name)
flen = yaffs_lseek(h,0,SEEK_END);
if(n > flen)
n = flen / 2;
- yaffs_truncate(name,n);
+ yaffs_ftruncate(h,n);
yaffs_lseek(h,n,SEEK_SET);
}
@@ -2167,10 +2186,8 @@ void random_small_file_test(const char *mountpt,int iterations)
int i;
int n;
- int j;
int h[NSMALLFILES];
int r;
- int fnum;
yaffs_StartUp();
@@ -2189,7 +2206,7 @@ void random_small_file_test(const char *mountpt,int iterations)
if(strlen(a[i]) == 0){
sprintf(a[i],"%s/%dx%d",mountpt,n,i);
- h[i] = yaffs_open(a,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+ h[i] = yaffs_open(a[i],O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
}
if(h[i] < -1)
@@ -2249,6 +2266,10 @@ int main(int argc, char *argv[])
//short_scan_test("/flash/flash",40000,200);
//small_mount_test("/flash/flash",1000);
//small_overwrite_test("/flash/flash",1000);
+ //seek_overwrite_test("/flash/flash",1000);
+ //checkpoint_fill_test("/flash/flash",20);
+ //checkpoint_upgrade_test("/flash/flash",20);
+ //small_overwrite_test("/flash/flash",1000);
//checkpoint_fill_test("/flash/flash",20);
// random_small_file_test("/flash/flash",10000);
// huge_array_test("/flash/flash",10);
diff --git a/direct/fsx_test/Makefile b/direct/fsx_test/Makefile
index 30323ad..359a523 100644
--- a/direct/fsx_test/Makefile
+++ b/direct/fsx_test/Makefile
@@ -14,11 +14,13 @@
#
# NB Warning this Makefile does not include header dependencies.
#
-# $Id: Makefile,v 1.1 2007-10-16 00:46:33 charles Exp $
+# $Id: Makefile,v 1.2 2008-05-05 07:58:58 charles Exp $
#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
-CFLAGS = -Wall -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -g $(EXTRA_COMPILE_FLAGS) -DNO_Y_INLINE
+CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -DNO_Y_INLINE
+CFLAGS+= -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES
+CFLAGS+= -Wall -g $(EXTRA_COMPILE_FLAGS)
CFLAGS+= -fstack-check -O0
#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
@@ -42,7 +44,7 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya
yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_nandemul2k.h \
yaffs_nand.c yaffs_nand.h \
yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
- yaffs_qsort.c yaffs_qsort.h
+ yaffs_qsort.c yaffs_qsort.h yaffs_getblockinfo.h
YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h \
yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \
diff --git a/direct/fsx_test/yaffs_fsx.c b/direct/fsx_test/yaffs_fsx.c
index 1e110b9..26a8536 100644
--- a/direct/fsx_test/yaffs_fsx.c
+++ b/direct/fsx_test/yaffs_fsx.c
@@ -67,6 +67,7 @@
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>
+#include <time.h>
#include "yaffsfs.h"
@@ -421,14 +422,14 @@ check_trunc_hack(void)
{
struct yaffs_stat statbuf;
- yaffs_truncate(fd, (off_t)0);
- yaffs_truncate(fd, (off_t)100000);
+ yaffs_ftruncate(fd, (off_t)0);
+ yaffs_ftruncate(fd, (off_t)100000);
yaffs_fstat(fd, &statbuf);
if (statbuf.st_size != (off_t)100000) {
prt("no extend on truncate! not posix!\n");
exit(130);
}
- yaffs_truncate(fd, (off_t)0);
+ yaffs_ftruncate(fd, (off_t)0);
}
@@ -579,7 +580,7 @@ dotruncate(unsigned size)
(debug && (monitorstart == -1 || monitorend == -1 ||
size <= monitorend)))
prt("%lu trunc\tfrom 0x%x to 0x%x\n", testcalls, oldsize, size);
- if (yaffs_truncate(fd, (off_t)size) == -1) {
+ if (yaffs_ftruncate(fd, (off_t)size) == -1) {
prt("ftruncate1: %x\n", size);
prterr("dotruncate: ftruncate");
report_failure(160);
@@ -605,7 +606,7 @@ writefileimage()
iret, (unsigned long long)file_size);
report_failure(172);
}
- if (lite ? 0 : yaffs_truncate(fd, file_size) == -1) {
+ if (lite ? 0 : yaffs_ftruncate(fd, file_size) == -1) {
prt("ftruncate2: %llx\n", (unsigned long long)file_size);
prterr("writefileimage: ftruncate");
report_failure(173);
diff --git a/direct/yaffs_fileem2k.c b/direct/yaffs_fileem2k.c
index 1e2cd6b..cb94486 100644
--- a/direct/yaffs_fileem2k.c
+++ b/direct/yaffs_fileem2k.c
@@ -16,7 +16,7 @@
* This is only intended as test code to test persistence etc.
*/
-const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.12 2007-02-14 01:09:06 wookey Exp $";
+const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.13 2008-05-05 07:58:58 charles Exp $";
#include "yportenv.h"
@@ -103,16 +103,10 @@ static int GetBlockFileHandle(int n)
static int CheckInit(void)
{
static int initialised = 0;
- int h;
int i;
-
- off_t fSize;
- off_t requiredSize;
- int written;
int blk;
-
- yflash_Page p;
+
if(initialised)
{
@@ -144,7 +138,7 @@ int yflash_GetNumberOfBlocks(void)
return filedisk.nBlocks;
}
-int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
+int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
{
int written;
int pos;
@@ -158,90 +152,114 @@ int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8
CheckInit();
-
- if(data)
- {
- pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
- h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ if(dev->inbandTags){
- lseek(h,pos,SEEK_SET);
- nRead = read(h, localBuffer,dev->nDataBytesPerChunk);
- for(i = error = 0; i < dev->nDataBytesPerChunk && !error; i++){
- if(localBuffer[i] != 0xFF){
- printf("nand simulation: chunk %d data byte %d was %0x2\n",
- chunkInNAND,i,localBuffer[i]);
- error = 1;
- }
- }
+ yaffs_PackedTags2TagsPart * pt2tp;
+ pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
+ yaffs_PackTags2TagsPart(pt2tp,tags);
- for(i = 0; i < dev->nDataBytesPerChunk; i++)
- localBuffer[i] &= data[i];
-
- if(memcmp(localBuffer,data,dev->nDataBytesPerChunk))
- printf("nand simulator: data does not match\n");
-
+ pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+ h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+
lseek(h,pos,SEEK_SET);
- written = write(h,localBuffer,dev->nDataBytesPerChunk);
+ written = write(h,data,dev->totalBytesPerChunk);
+
if(yaffs_testPartialWrite){
close(h);
exit(1);
}
-#ifdef SIMULATE_FAILURES
- if((chunkInNAND >> 6) == 100)
- written = 0;
-
- if((chunkInNAND >> 6) == 110)
- written = 0;
-#endif
+ if(written != dev->totalBytesPerChunk) return YAFFS_FAIL;
- if(written != dev->nDataBytesPerChunk) return YAFFS_FAIL;
}
- if(tags)
- {
- pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
- h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-
- lseek(h,pos,SEEK_SET);
-
- if( 0 && dev->isYaffs2)
+ else {
+
+ if(data)
{
+ pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+ h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+
+ lseek(h,pos,SEEK_SET);
+ nRead = read(h, localBuffer,dev->nDataBytesPerChunk);
+ for(i = error = 0; i < dev->nDataBytesPerChunk && !error; i++){
+ if(localBuffer[i] != 0xFF){
+ printf("nand simulation: chunk %d data byte %d was %0x2\n",
+ chunkInNAND,i,localBuffer[i]);
+ error = 1;
+ }
+ }
+
+ for(i = 0; i < dev->nDataBytesPerChunk; i++)
+ localBuffer[i] &= data[i];
+
+ if(memcmp(localBuffer,data,dev->nDataBytesPerChunk))
+ printf("nand simulator: data does not match\n");
- written = write(h,tags,sizeof(yaffs_ExtendedTags));
- if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
+ lseek(h,pos,SEEK_SET);
+ written = write(h,localBuffer,dev->nDataBytesPerChunk);
+
+ if(yaffs_testPartialWrite){
+ close(h);
+ exit(1);
+ }
+
+#ifdef SIMULATE_FAILURES
+ if((chunkInNAND >> 6) == 100)
+ written = 0;
+
+ if((chunkInNAND >> 6) == 110)
+ written = 0;
+#endif
+
+
+ if(written != dev->nDataBytesPerChunk) return YAFFS_FAIL;
}
- else
+
+ if(tags)
{
- yaffs_PackedTags2 pt;
- yaffs_PackTags2(&pt,tags);
- __u8 * ptab = (__u8 *)&pt;
+ pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
+ h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+
+ lseek(h,pos,SEEK_SET);
- nRead = read(h,localBuffer,sizeof(pt));
- for(i = error = 0; i < sizeof(pt) && !error; i++){
- if(localBuffer[i] != 0xFF){
- printf("nand simulation: chunk %d oob byte %d was %0x2\n",
- chunkInNAND,i,localBuffer[i]);
- error = 1;
- }
+ if( 0 && dev->isYaffs2)
+ {
+
+ written = write(h,tags,sizeof(yaffs_ExtendedTags));
+ if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
}
+ else
+ {
+ yaffs_PackedTags2 pt;
+ yaffs_PackTags2(&pt,tags);
+ __u8 * ptab = (__u8 *)&pt;
+
+ nRead = read(h,localBuffer,sizeof(pt));
+ for(i = error = 0; i < sizeof(pt) && !error; i++){
+ if(localBuffer[i] != 0xFF){
+ printf("nand simulation: chunk %d oob byte %d was %0x2\n",
+ chunkInNAND,i,localBuffer[i]);
+ error = 1;
+ }
+ }
- for(i = 0; i < sizeof(pt); i++)
- localBuffer[i] &= ptab[i];
+ for(i = 0; i < sizeof(pt); i++)
+ localBuffer[i] &= ptab[i];
- if(memcmp(localBuffer,&pt,sizeof(pt)))
- printf("nand sim: tags corruption\n");
+ if(memcmp(localBuffer,&pt,sizeof(pt)))
+ printf("nand sim: tags corruption\n");
- lseek(h,pos,SEEK_SET);
+ lseek(h,pos,SEEK_SET);
- written = write(h,localBuffer,sizeof(pt));
- if(written != sizeof(pt)) return YAFFS_FAIL;
+ written = write(h,localBuffer,sizeof(pt));
+ if(written != sizeof(pt)) return YAFFS_FAIL;
+ }
}
- }
-
+ }
return YAFFS_OK;
}
@@ -268,6 +286,9 @@ int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *da
int nread;
int pos;
int h;
+ int localData = 0;
+ int retval = YAFFS_OK;
+ int nRead;
T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %x tags %x" TENDSTR),chunkInNAND,(unsigned)data, (unsigned)tags));
@@ -275,68 +296,107 @@ int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *da
- if(data)
- {
+
+ if(dev->inbandTags){
+ /* Got to suck the tags out of the data area */
+ if(!data) {
+ localData=1;
+ data = yaffs_GetTempBuffer(dev,__LINE__);
+ }
+
+ yaffs_PackedTags2TagsPart * pt2tp;
+ pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
+
+
pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
- h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
- lseek(h,pos,SEEK_SET);
- nread = read(h,data,dev->nDataBytesPerChunk);
+ h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ lseek(h,pos,SEEK_SET);
+
+ nRead = read(h, data,dev->totalBytesPerChunk);
+
+ yaffs_UnpackTags2TagsPart(tags,pt2tp);
- if(nread != dev->nDataBytesPerChunk) return YAFFS_FAIL;
+ if(nread != dev->totalBytesPerChunk)
+ retval = YAFFS_FAIL;
+
+ if(localData)
+ yaffs_ReleaseTempBuffer(dev,data,__LINE__);
+
+
+
}
- if(tags)
- {
- pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
- h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
- lseek(h,pos,SEEK_SET);
+ else {
+
+ if(data)
+ {
- if(0 && dev->isYaffs2)
+ pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+ h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ lseek(h,pos,SEEK_SET);
+ nread = read(h,data,dev->nDataBytesPerChunk);
+
+
+ if(nread != dev->nDataBytesPerChunk)
+ retval = YAFFS_FAIL;
+ }
+
+ if(tags)
{
- nread= read(h,tags,sizeof(yaffs_ExtendedTags));
- if(nread != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
- if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags)))
+ pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
+ h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ lseek(h,pos,SEEK_SET);
+
+ if(0 && dev->isYaffs2)
{
- yaffs_InitialiseTags(tags);
+ nread= read(h,tags,sizeof(yaffs_ExtendedTags));
+ if(nread != sizeof(yaffs_ExtendedTags))
+ retval = YAFFS_FAIL;
+ if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags)))
+ {
+ yaffs_InitialiseTags(tags);
+ }
+ else
+ {
+ tags->chunkUsed = 1;
+ }
}
else
{
- tags->chunkUsed = 1;
- }
- }
- else
- {
- yaffs_PackedTags2 pt;
- nread= read(h,&pt,sizeof(pt));
- yaffs_UnpackTags2(tags,&pt);
+ yaffs_PackedTags2 pt;
+ nread= read(h,&pt,sizeof(pt));
+ yaffs_UnpackTags2(tags,&pt);
#ifdef SIMULATE_FAILURES
- if((chunkInNAND >> 6) == 100) {
- if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
- tags->eccResult = YAFFS_ECC_RESULT_FIXED;
- fail300 = 0;
- }
-
- }
- if((chunkInNAND >> 6) == 110) {
- if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
- tags->eccResult = YAFFS_ECC_RESULT_FIXED;
- fail320 = 0;
- }
- }
+ if((chunkInNAND >> 6) == 100) {
+ if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+ tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+ fail300 = 0;
+ }
+ }
+
+ if((chunkInNAND >> 6) == 110) {
+ if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+ tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+ fail320 = 0;
+ }
+ }
#endif
- if(failRead10>0 && chunkInNAND == 10){
- failRead10--;
- nread = 0;
- }
+ if(failRead10>0 && chunkInNAND == 10){
+ failRead10--;
+ nread = 0;
+ }
- if(nread != sizeof(pt)) return YAFFS_FAIL;
+ if(nread != sizeof(pt))
+ retval = YAFFS_FAIL;
+ }
}
}
- return YAFFS_OK;
+
+ return retval;
}
@@ -413,7 +473,7 @@ int yflash_InitialiseNAND(yaffs_Device *dev)
-int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
+int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber)
{
yaffs_ExtendedTags tags;
int chunkNo;
diff --git a/direct/yaffs_flashif.h b/direct/yaffs_flashif.h
index f7f4e42..a6bc65d 100644
--- a/direct/yaffs_flashif.h
+++ b/direct/yaffs_flashif.h
@@ -20,12 +20,12 @@
#include "yaffs_guts.h"
int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
int yflash_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare);
-int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags);
+int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
int yflash_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);
int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
int yflash_InitialiseNAND(yaffs_Device *dev);
int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
-int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
+int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber);
#endif
diff --git a/direct/yaffs_ramdisk.c b/direct/yaffs_ramdisk.c
index 3cf054a..fa76b6c 100644
--- a/direct/yaffs_ramdisk.c
+++ b/direct/yaffs_ramdisk.c
@@ -18,7 +18,7 @@
* Use this with dev->useNANDECC enabled, then ECC overheads are not required.
*/
-const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.4 2007-02-14 01:09:06 wookey Exp $";
+const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.5 2008-05-05 07:58:58 charles Exp $";
#include "yportenv.h"
@@ -118,7 +118,7 @@ static int CheckInit(yaffs_Device *dev)
return 1;
}
-int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
+int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
{
int blk;
int pg;
diff --git a/direct/yaffs_ramdisk.h b/direct/yaffs_ramdisk.h
index 045ab42..4565998 100644
--- a/direct/yaffs_ramdisk.h
+++ b/direct/yaffs_ramdisk.h
@@ -23,7 +23,7 @@
#include "yaffs_guts.h"
int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
-int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags);
+int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
int yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
int yramdisk_InitialiseNAND(yaffs_Device *dev);
diff --git a/direct/yaffs_ramem2k.c b/direct/yaffs_ramem2k.c
index c01bc97..b496cc6 100644
--- a/direct/yaffs_ramem2k.c
+++ b/direct/yaffs_ramem2k.c
@@ -16,7 +16,7 @@
*/
-const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.3 2007-02-14 01:09:06 wookey Exp $";
+const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.4 2008-05-05 07:58:58 charles Exp $";
#ifndef __KERNEL__
#define CONFIG_YAFFS_RAM_ENABLED
@@ -190,7 +190,7 @@ static int CheckInit(void)
return 1;
}
-int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
+int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
{
int blk;
int pg;
@@ -327,7 +327,7 @@ int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
}
-int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
+int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber)
{
yaffs_ExtendedTags tags;
int chunkNo;
diff --git a/direct/yaffscfg2k.c b/direct/yaffscfg2k.c
index 2c95409..2f7442e 100644
--- a/direct/yaffscfg2k.c
+++ b/direct/yaffscfg2k.c
@@ -34,19 +34,22 @@ unsigned yaffs_traceMask =
YAFFS_TRACE_ALLOCATE |
YAFFS_TRACE_CHECKPOINT |
YAFFS_TRACE_BAD_BLOCKS |
- YAFFS_TRACE_VERIFY |
- YAFFS_TRACE_VERIFY_NAND |
- YAFFS_TRACE_VERIFY_FULL |
-// (~0) |
0;
+static int yaffsfs_lastError;
void yaffsfs_SetError(int err)
{
//Do whatever to set error
- errno = err;
+ yaffsfs_lastError = err;
+}
+
+
+int yaffsfs_GetLastError(void)
+{
+ return yaffsfs_lastError;
}
void yaffsfs_Lock(void)
@@ -69,7 +72,7 @@ static size_t malloc_limit = 0 & 6000000;
void *yaffs_malloc(size_t size)
{
- size_t this;
+ void * this;
if(yaffs_kill_alloc)
return NULL;
if(malloc_limit && malloc_limit <(total_malloced + size) )
@@ -121,6 +124,7 @@ static yaffsfs_DeviceConfiguration yaffsfs_config[] = {
{ "/flash/boot", &bootDev},
{ "/flash/flash", &flashDev},
{ "/ram2k", &ram2kDev},
+ { "/flash/bigblock", &flashDev},
{(void *)0,(void *)0} /* Null entry to terminate list */
#endif
};
@@ -135,7 +139,7 @@ int yaffs_StartUp(void)
// Set up devices
// /ram
memset(&ramDev,0,sizeof(ramDev));
- ramDev.nDataBytesPerChunk = 512;
+ ramDev.totalBytesPerChunk = 512;
ramDev.nChunksPerBlock = 32;
ramDev.nReservedBlocks = 2; // Set this smaller for RAM
ramDev.startBlock = 0; // Can use block 0
@@ -150,7 +154,7 @@ int yaffs_StartUp(void)
// /boot
memset(&bootDev,0,sizeof(bootDev));
- bootDev.nDataBytesPerChunk = 512;
+ bootDev.totalBytesPerChunk = 512;
bootDev.nChunksPerBlock = 32;
bootDev.nReservedBlocks = 5;
bootDev.startBlock = 0; // Can use block 0
@@ -173,9 +177,10 @@ int yaffs_StartUp(void)
// 2kpage/64chunk per block/128MB device
memset(&flashDev,0,sizeof(flashDev));
- flashDev.nDataBytesPerChunk = 2048;
+ flashDev.totalBytesPerChunk = 512;
flashDev.nChunksPerBlock = 64;
flashDev.nReservedBlocks = 5;
+ flashDev.inbandTags = 1;
//flashDev.checkpointStartBlock = 1;
//flashDev.checkpointEndBlock = 20;
flashDev.startBlock = 0;
@@ -198,7 +203,7 @@ int yaffs_StartUp(void)
// 2kpage/64chunk per block/128MB device
memset(&ram2kDev,0,sizeof(ram2kDev));
- ram2kDev.nDataBytesPerChunk = nandemul2k_GetBytesPerChunk();
+ ram2kDev.totalBytesPerChunk = nandemul2k_GetBytesPerChunk();
ram2kDev.nChunksPerBlock = nandemul2k_GetChunksPerBlock();
ram2kDev.nReservedBlocks = 5;
ram2kDev.startBlock = 0; // First block after /boot
diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c
index dc6dab9..2b9d0bc 100644
--- a/direct/yaffsfs.c
+++ b/direct/yaffsfs.c
@@ -24,14 +24,14 @@
#endif
-const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.18 2007-07-18 19:40:38 charles Exp $";
+const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.19 2008-05-05 07:58:58 charles Exp $";
// configurationList is the list of devices that are supported
static yaffsfs_DeviceConfiguration *yaffsfs_configurationList;
/* Some forward references */
-static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path, int symDepth);
+static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path, int symDepth);
static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj);
@@ -137,22 +137,95 @@ static int yaffsfs_PutHandle(int handle)
// Stuff to search for a directory from a path
-int yaffsfs_Match(char a, char b)
+int yaffsfs_Match(YCHAR a, YCHAR b)
{
// case sensitive
return (a == b);
}
+int yaffsfs_IsPathDivider(YCHAR ch)
+{
+ YCHAR *str = YAFFS_PATH_DIVIDERS;
+
+ while(*str){
+ if(*str == ch)
+ return 1;
+ str++;
+ }
+
+ return 0;
+}
+
// yaffsfs_FindDevice
// yaffsfs_FindRoot
// Scan the configuration list to find the root.
// Curveballs: Should match paths that end in '/' too
// Curveball2 Might have "/x/ and "/x/y". Need to return the longest match
-static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath)
+static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath)
+{
+ yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;
+ const YCHAR *leftOver;
+ const YCHAR *p;
+ yaffs_Device *retval = NULL;
+ int thisMatchLength;
+ int longestMatch = -1;
+
+ // Check all configs, choose the one that:
+ // 1) Actually matches a prefix (ie /a amd /abc will not match
+ // 2) Matches the longest.
+ while(cfg && cfg->prefix && cfg->dev)
+ {
+ leftOver = path;
+ p = cfg->prefix;
+ thisMatchLength = 0;
+
+
+ // Strip off any leading /'s
+
+ while(yaffsfs_IsPathDivider(*p))
+ p++;
+
+ while(yaffsfs_IsPathDivider(*leftOver))
+ leftOver++;
+
+ while(*p && *leftOver &&
+ yaffsfs_Match(*p,*leftOver))
+ {
+ p++;
+ leftOver++;
+ thisMatchLength++;
+
+ // Skip over any multiple /'s to treat them as one or
+ // skip over a trailling / in the prefix, but not the matching string
+ while(yaffsfs_IsPathDivider(*p) &&
+ (yaffsfs_IsPathDivider(*(p+1)) || !(*(p+1))))
+ p++;
+
+ // Only skip over multiple /'s
+ while(yaffsfs_IsPathDivider(*leftOver) &&
+ yaffsfs_IsPathDivider(*(leftOver+1)))
+ leftOver++;
+ }
+
+ if((!*p ) &&
+ (!*leftOver || yaffsfs_IsPathDivider(*leftOver)) && // no more in this path name part
+ (thisMatchLength > longestMatch))
+ {
+ // Matched prefix
+ *restOfPath = (YCHAR *)leftOver;
+ retval = cfg->dev;
+ longestMatch = thisMatchLength;
+ }
+ cfg++;
+ }
+ return retval;
+}
+#if 0
+static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath)
{
yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;
- const char *leftOver;
- const char *p;
+ const YCHAR *leftOver;
+ const YCHAR *p;
yaffs_Device *retval = NULL;
int thisMatchLength;
int longestMatch = -1;
@@ -167,7 +240,7 @@ static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath)
thisMatchLength = 0;
while(*p && //unmatched part of prefix
- strcmp(p,"/") && // the rest of the prefix is not / (to catch / at end)
+ !(yaffsfs_IsPathDivider(*p) && (p[1] == 0)) && // the rest of the prefix is not / (to catch / at end)
*leftOver &&
yaffsfs_Match(*p,*leftOver))
{
@@ -175,12 +248,14 @@ static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath)
leftOver++;
thisMatchLength++;
}
- if((!*p || strcmp(p,"/") == 0) && // end of prefix
- (!*leftOver || *leftOver == '/') && // no more in this path name part
+
+
+ if((!*p || (yaffsfs_IsPathDivider(*p) && (p[1] == 0))) && // end of prefix
+ (!*leftOver || yaffsfs_IsPathDivider(*leftOver)) && // no more in this path name part
(thisMatchLength > longestMatch))
{
// Matched prefix
- *restOfPath = (char *)leftOver;
+ *restOfPath = (YCHAR *)leftOver;
retval = cfg->dev;
longestMatch = thisMatchLength;
}
@@ -188,8 +263,9 @@ static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath)
}
return retval;
}
+#endif
-static yaffs_Object *yaffsfs_FindRoot(const char *path, char **restOfPath)
+static yaffs_Object *yaffsfs_FindRoot(const YCHAR *path, YCHAR **restOfPath)
{
yaffs_Device *dev;
@@ -207,9 +283,9 @@ static yaffs_Object *yaffsfs_FollowLink(yaffs_Object *obj,int symDepth)
while(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
{
- char *alias = obj->variant.symLinkVariant.alias;
+ YCHAR *alias = obj->variant.symLinkVariant.alias;
- if(*alias == '/')
+ if(yaffsfs_IsPathDivider(*alias))
{
// Starts with a /, need to scan from root up
obj = yaffsfs_FindObject(NULL,alias,symDepth++);
@@ -228,11 +304,11 @@ static yaffs_Object *yaffsfs_FollowLink(yaffs_Object *obj,int symDepth)
// Parse a path to determine the directory and the name within the directory.
//
// eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx"
-static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *path,char **name,int symDepth)
+static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const YCHAR *path,YCHAR **name,int symDepth)
{
yaffs_Object *dir;
- char *restOfPath;
- char str[YAFFS_MAX_NAME_LENGTH+1];
+ YCHAR *restOfPath;
+ YCHAR str[YAFFS_MAX_NAME_LENGTH+1];
int i;
if(symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES)
@@ -243,7 +319,7 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *
if(startDir)
{
dir = startDir;
- restOfPath = (char *)path;
+ restOfPath = (YCHAR *)path;
}
else
{
@@ -255,7 +331,7 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *
// parse off /.
// curve ball: also throw away surplus '/'
// eg. "/ram/x////ff" gets treated the same as "/ram/x/ff"
- while(*restOfPath == '/')
+ while(yaffsfs_IsPathDivider(*restOfPath))
{
restOfPath++; // get rid of '/'
}
@@ -263,7 +339,7 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *
*name = restOfPath;
i = 0;
- while(*restOfPath && *restOfPath != '/')
+ while(*restOfPath && !yaffsfs_IsPathDivider(*restOfPath))
{
if (i < YAFFS_MAX_NAME_LENGTH)
{
@@ -281,11 +357,11 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *
}
else
{
- if(strcmp(str,".") == 0)
+ if(yaffs_strcmp(str,_Y(".")) == 0)
{
// Do nothing
}
- else if(strcmp(str,"..") == 0)
+ else if(yaffs_strcmp(str,_Y("..")) == 0)
{
dir = dir->parent;
}
@@ -311,17 +387,17 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *
return NULL;
}
-static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const char *path,char **name,int symDepth)
+static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const YCHAR *path,YCHAR **name,int symDepth)
{
return yaffsfs_DoFindDirectory(relativeDirectory,path,name,symDepth);
}
// yaffsfs_FindObject turns a path for an existing object into the object
//
-static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path,int symDepth)
+static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path,int symDepth)
{
yaffs_Object *dir;
- char *name;
+ YCHAR *name;
dir = yaffsfs_FindDirectory(relativeDirectory,path,&name,symDepth);
@@ -334,12 +410,39 @@ static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const c
}
+int yaffs_dup(int fd)
+{
+ int newHandle = -1;
+ yaffsfs_Handle *oldPtr = NULL;
+ yaffsfs_Handle *newPtr = NULL;
+
+ yaffsfs_Lock();
+
+ oldPtr = yaffsfs_GetHandlePointer(fd);
+ if(oldPtr && oldPtr->inUse)
+ newHandle = yaffsfs_GetHandle();
+ if(newHandle >= 0)
+ newPtr = yaffsfs_GetHandlePointer(newHandle);
+
+ if(newPtr){
+ *newPtr = *oldPtr;
+ return newHandle;
+ }
+
+ if(!oldPtr)
+ yaffsfs_SetError(-EBADF);
+ else
+ yaffsfs_SetError(-ENOMEM);
+
+ return -1;
+
+}
-int yaffs_open(const char *path, int oflag, int mode)
+int yaffs_open(const YCHAR *path, int oflag, int mode)
{
yaffs_Object *obj = NULL;
yaffs_Object *dir = NULL;
- char *name;
+ YCHAR *name;
int handle = -1;
yaffsfs_Handle *h = NULL;
int alreadyOpen = 0;
@@ -373,6 +476,11 @@ int yaffs_open(const char *path, int oflag, int mode)
obj = yaffsfs_FollowLink(obj,symDepth++);
}
+ if(obj && obj->variantType != YAFFS_OBJECT_TYPE_FILE)
+ {
+ obj = NULL;
+ }
+
if(obj)
{
// Check if the object is already in use
@@ -438,6 +546,7 @@ int yaffs_open(const char *path, int oflag, int mode)
else
{
yaffsfs_SetError(-ENOTDIR);
+ errorReported = 1;
}
}
@@ -463,17 +572,43 @@ int yaffs_open(const char *path, int oflag, int mode)
yaffsfs_PutHandle(handle);
if(!errorReported)
{
- yaffsfs_SetError(-EACCESS);
+ yaffsfs_SetError(-EACCES);
errorReported = 1;
}
handle = -1;
}
-
+
}
-
+
yaffsfs_Unlock();
+
+ return handle;
+}
+
+int yaffs_flush(int fd)
+{
+ yaffsfs_Handle *h = NULL;
+ int retVal = 0;
+
+ yaffsfs_Lock();
+
+ h = yaffsfs_GetHandlePointer(fd);
+
+ if(h && h->inUse)
+ {
+ // flush the file
+ yaffs_FlushFile(h->obj,1);
+ }
+ else
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ retVal = -1;
+ }
- return handle;
+ yaffsfs_Unlock();
+
+ return retVal;
}
int yaffs_close(int fd)
@@ -515,7 +650,7 @@ int yaffs_read(int fd, void *buf, unsigned int nbyte)
yaffs_Object *obj = NULL;
int pos = 0;
int nRead = -1;
- int maxRead;
+ unsigned int maxRead;
yaffsfs_Lock();
h = yaffsfs_GetHandlePointer(fd);
@@ -570,6 +705,59 @@ int yaffs_read(int fd, void *buf, unsigned int nbyte)
}
+int yaffs_pread(int fd, void *buf, unsigned int nbyte, unsigned int offset)
+{
+ yaffsfs_Handle *h = NULL;
+ yaffs_Object *obj = NULL;
+ int pos = 0;
+ int nRead = -1;
+ unsigned int maxRead;
+
+ yaffsfs_Lock();
+ h = yaffsfs_GetHandlePointer(fd);
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(!h || !obj)
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+ else if( h && obj)
+ {
+ pos= offset;
+ if(yaffs_GetObjectFileLength(obj) > pos)
+ {
+ maxRead = yaffs_GetObjectFileLength(obj) - pos;
+ }
+ else
+ {
+ maxRead = 0;
+ }
+
+ if(nbyte > maxRead)
+ {
+ nbyte = maxRead;
+ }
+
+
+ if(nbyte > 0)
+ {
+ nRead = yaffs_ReadDataFromFile(obj,buf,pos,nbyte);
+ }
+ else
+ {
+ nRead = 0;
+ }
+
+ }
+
+ yaffsfs_Unlock();
+
+
+ return (nRead >= 0) ? nRead : -1;
+
+}
+
int yaffs_write(int fd, const void *buf, unsigned int nbyte)
{
yaffsfs_Handle *h = NULL;
@@ -622,7 +810,77 @@ int yaffs_write(int fd, const void *buf, unsigned int nbyte)
}
-int yaffs_truncate(int fd, off_t newSize)
+int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, unsigned int offset)
+{
+ yaffsfs_Handle *h = NULL;
+ yaffs_Object *obj = NULL;
+ int pos = 0;
+ int nWritten = -1;
+ int writeThrough = 0;
+
+ yaffsfs_Lock();
+ h = yaffsfs_GetHandlePointer(fd);
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(!h || !obj)
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+ else if( h && obj && h->readOnly)
+ {
+ // todo error
+ }
+ else if( h && obj)
+ {
+ pos = offset;
+
+ nWritten = yaffs_WriteDataToFile(obj,buf,pos,nbyte,writeThrough);
+
+ if(nWritten < nbyte)
+ yaffsfs_SetError(-ENOSPC);
+
+ }
+
+ yaffsfs_Unlock();
+
+
+ return (nWritten >= 0) ? nWritten : -1;
+
+}
+
+
+int yaffs_truncate(const YCHAR *path,off_t newSize)
+{
+ yaffs_Object *obj = NULL;
+ int result = YAFFS_FAIL;
+
+ yaffsfs_Lock();
+
+ obj = yaffsfs_FindObject(NULL,path,0);
+ if(obj)
+ obj = yaffs_GetEquivalentObject(obj);
+
+ if(!obj)
+ {
+ yaffsfs_SetError(-ENOENT);
+ }
+ else if(obj->variantType != YAFFS_OBJECT_TYPE_FILE)
+ {
+ yaffsfs_SetError(-EISDIR);
+ }
+ else
+ {
+ result = yaffs_ResizeFile(obj,newSize);
+ }
+
+ yaffsfs_Unlock();
+
+
+ return (result) ? 0 : -1;
+}
+
+int yaffs_ftruncate(int fd, off_t newSize)
{
yaffsfs_Handle *h = NULL;
yaffs_Object *obj = NULL;
@@ -704,11 +962,11 @@ off_t yaffs_lseek(int fd, off_t offset, int whence)
}
-int yaffsfs_DoUnlink(const char *path,int isDirectory)
+int yaffsfs_DoUnlink(const YCHAR *path,int isDirectory)
{
yaffs_Object *dir = NULL;
yaffs_Object *obj = NULL;
- char *name;
+ YCHAR *name;
int result = YAFFS_FAIL;
yaffsfs_Lock();
@@ -747,23 +1005,25 @@ int yaffsfs_DoUnlink(const char *path,int isDirectory)
return (result == YAFFS_FAIL) ? -1 : 0;
}
-int yaffs_rmdir(const char *path)
+
+
+int yaffs_rmdir(const YCHAR *path)
{
return yaffsfs_DoUnlink(path,1);
}
-int yaffs_unlink(const char *path)
+int yaffs_unlink(const YCHAR *path)
{
return yaffsfs_DoUnlink(path,0);
}
-int yaffs_rename(const char *oldPath, const char *newPath)
+int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath)
{
yaffs_Object *olddir = NULL;
yaffs_Object *newdir = NULL;
yaffs_Object *obj = NULL;
- char *oldname;
- char *newname;
+ YCHAR *oldname;
+ YCHAR *newname;
int result= YAFFS_FAIL;
int renameAllowed = 1;
@@ -802,7 +1062,7 @@ int yaffs_rename(const char *oldPath, const char *newPath)
}
xx = xx->parent;
}
- if(!renameAllowed) yaffsfs_SetError(-EACCESS);
+ if(!renameAllowed) yaffsfs_SetError(-EACCES);
}
if(renameAllowed)
@@ -851,15 +1111,24 @@ static int yaffsfs_DoStat(yaffs_Object *obj,struct yaffs_stat *buf)
buf->st_size = yaffs_GetObjectFileLength(obj);
buf->st_blksize = obj->myDev->nDataBytesPerChunk;
buf->st_blocks = (buf->st_size + buf->st_blksize -1)/buf->st_blksize;
- buf->yst_atime = obj->yst_atime;
- buf->yst_ctime = obj->yst_ctime;
- buf->yst_mtime = obj->yst_mtime;
+#if CONFIG_YAFFS_WINCE
+ buf->yst_wince_atime[0] = obj->win_atime[0];
+ buf->yst_wince_atime[1] = obj->win_atime[1];
+ buf->yst_wince_ctime[0] = obj->win_ctime[0];
+ buf->yst_wince_ctime[1] = obj->win_ctime[1];
+ buf->yst_wince_mtime[0] = obj->win_mtime[0];
+ buf->yst_wince_mtime[1] = obj->win_mtime[1];
+#else
+ buf->yst_atime = obj->yst_atime;
+ buf->yst_ctime = obj->yst_ctime;
+ buf->yst_mtime = obj->yst_mtime;
+#endif
retVal = 0;
}
return retVal;
}
-static int yaffsfs_DoStatOrLStat(const char *path, struct yaffs_stat *buf,int doLStat)
+static int yaffsfs_DoStatOrLStat(const YCHAR *path, struct yaffs_stat *buf,int doLStat)
{
yaffs_Object *obj;
@@ -889,12 +1158,12 @@ static int yaffsfs_DoStatOrLStat(const char *path, struct yaffs_stat *buf,int do
}
-int yaffs_stat(const char *path, struct yaffs_stat *buf)
+int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf)
{
return yaffsfs_DoStatOrLStat(path,buf,0);
}
-int yaffs_lstat(const char *path, struct yaffs_stat *buf)
+int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf)
{
return yaffsfs_DoStatOrLStat(path,buf,1);
}
@@ -915,6 +1184,46 @@ int yaffs_fstat(int fd, struct yaffs_stat *buf)
else
{
// bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+#ifdef CONFIG_YAFFS_WINCE
+int yaffs_get_wince_times(int fd, unsigned *wctime, unsigned *watime, unsigned *wmtime)
+{
+ yaffs_Object *obj;
+
+ int retVal = -1;
+
+ yaffsfs_Lock();
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(obj)
+ {
+
+ if(wctime){
+ wctime[0] = obj->win_ctime[0];
+ wctime[1] = obj->win_ctime[1];
+ }
+ if(watime){
+ watime[0] = obj->win_atime[0];
+ watime[1] = obj->win_atime[1];
+ }
+ if(wmtime){
+ wmtime[0] = obj->win_mtime[0];
+ wmtime[1] = obj->win_mtime[1];
+ }
+
+
+ retVal = 0;
+ }
+ else
+ {
+ // bad handle
yaffsfs_SetError(-EBADF);
}
@@ -923,6 +1232,51 @@ int yaffs_fstat(int fd, struct yaffs_stat *buf)
return retVal;
}
+
+int yaffs_set_wince_times(int fd,
+ const unsigned *wctime,
+ const unsigned *watime,
+ const unsigned *wmtime)
+{
+ yaffs_Object *obj;
+
+ int retVal = -1;
+
+ yaffsfs_Lock();
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(obj)
+ {
+
+ if(wctime){
+ obj->win_ctime[0] = wctime[0];
+ obj->win_ctime[1] = wctime[1];
+ }
+ if(watime){
+ obj->win_atime[0] = watime[0];
+ obj->win_atime[1] = watime[1];
+ }
+ if(wctime){
+ obj->win_mtime[0] = wmtime[0];
+ obj->win_mtime[1] = wmtime[1];
+ }
+
+ retVal = 0;
+ }
+ else
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+#endif
+
+
static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode)
{
int result;
@@ -943,7 +1297,46 @@ static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode)
}
-int yaffs_chmod(const char *path, mode_t mode)
+int yaffs_access(const YCHAR *path, int amode)
+{
+ yaffs_Object *obj;
+
+ int retval = 0;
+
+ yaffsfs_Lock();
+ obj = yaffsfs_FindObject(NULL,path,0);
+
+ if(obj)
+ {
+ int access_ok = 1;
+
+ if((amode & R_OK) && !(obj->yst_mode & S_IREAD))
+ access_ok = 0;
+ if((amode & W_OK) && !(obj->yst_mode & S_IWRITE))
+ access_ok = 0;
+ if((amode & X_OK) && !(obj->yst_mode & S_IEXEC))
+ access_ok = 0;
+
+ if(!access_ok) {
+ yaffsfs_SetError(-EACCES);
+ retval = -1;
+ }
+ }
+ else
+ {
+ // todo error not found
+ yaffsfs_SetError(-ENOENT);
+ retval = -1;
+ }
+
+ yaffsfs_Unlock();
+
+ return retval;
+
+}
+
+
+int yaffs_chmod(const YCHAR *path, mode_t mode)
{
yaffs_Object *obj;
@@ -994,11 +1387,11 @@ int yaffs_fchmod(int fd, mode_t mode)
}
-int yaffs_mkdir(const char *path, mode_t mode)
+int yaffs_mkdir(const YCHAR *path, mode_t mode)
{
yaffs_Object *parent = NULL;
yaffs_Object *dir = NULL;
- char *name;
+ YCHAR *name;
int retVal= -1;
yaffsfs_Lock();
@@ -1011,7 +1404,14 @@ int yaffs_mkdir(const char *path, mode_t mode)
}
else
{
- yaffsfs_SetError(-ENOSPC); // just assume no space for now
+ if(!parent){
+ yaffsfs_SetError(-ENOENT); // missing path
+ }
+ else if (yaffs_FindObjectByName(parent,name)){
+ yaffsfs_SetError(-EEXIST); // the name already exists
+ }
+ else
+ yaffsfs_SetError(-ENOSPC); // just assume no space
retVal = -1;
}
@@ -1020,14 +1420,14 @@ int yaffs_mkdir(const char *path, mode_t mode)
return retVal;
}
-int yaffs_mount(const char *path)
+int yaffs_mount(const YCHAR *path)
{
int retVal=-1;
int result=YAFFS_FAIL;
yaffs_Device *dev=NULL;
- char *dummy;
+ YCHAR *dummy;
- T(YAFFS_TRACE_ALWAYS,("yaffs: Mounting %s\n",path));
+ T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Mounting %s" TENDSTR),path));
yaffsfs_Lock();
dev = yaffsfs_FindDevice(path,&dummy);
@@ -1060,11 +1460,46 @@ int yaffs_mount(const char *path)
}
-int yaffs_unmount(const char *path)
+int yaffs_sync(const YCHAR *path)
{
int retVal=-1;
yaffs_Device *dev=NULL;
- char *dummy;
+ YCHAR *dummy;
+
+ yaffsfs_Lock();
+ dev = yaffsfs_FindDevice(path,&dummy);
+ if(dev)
+ {
+ if(dev->isMounted)
+ {
+
+ yaffs_FlushEntireDeviceCache(dev);
+ yaffs_CheckpointSave(dev);
+
+
+ }
+ else
+ {
+ //todo error - not mounted.
+ yaffsfs_SetError(-EINVAL);
+
+ }
+ }
+ else
+ {
+ // todo error - no device
+ yaffsfs_SetError(-ENODEV);
+ }
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+
+int yaffs_unmount(const YCHAR *path)
+{
+ int retVal=-1;
+ yaffs_Device *dev=NULL;
+ YCHAR *dummy;
yaffsfs_Lock();
dev = yaffsfs_FindDevice(path,&dummy);
@@ -1116,11 +1551,11 @@ int yaffs_unmount(const char *path)
}
-loff_t yaffs_freespace(const char *path)
+loff_t yaffs_freespace(const YCHAR *path)
{
loff_t retVal=-1;
yaffs_Device *dev=NULL;
- char *dummy;
+ YCHAR *dummy;
yaffsfs_Lock();
dev = yaffsfs_FindDevice(path,&dummy);
@@ -1128,7 +1563,31 @@ loff_t yaffs_freespace(const char *path)
{
retVal = yaffs_GetNumberOfFreeChunks(dev);
retVal *= dev->nDataBytesPerChunk;
-
+
+ }
+ else
+ {
+ yaffsfs_SetError(-EINVAL);
+ }
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+loff_t yaffs_totalspace(const YCHAR *path)
+{
+ loff_t retVal=-1;
+ yaffs_Device *dev=NULL;
+ YCHAR *dummy;
+
+ yaffsfs_Lock();
+ dev = yaffsfs_FindDevice(path,&dummy);
+ if(dev && dev->isMounted)
+ {
+ retVal = (dev->endBlock - dev->startBlock + 1) - dev->nReservedBlocks;
+ retVal *= dev->nChunksPerBlock;
+ retVal *= dev->nDataBytesPerChunk;
+
}
else
{
@@ -1176,16 +1635,16 @@ typedef struct
{
__u32 magic;
yaffs_dirent de; /* directory entry being used by this dsc */
- char name[NAME_MAX+1]; /* name of directory being searched */
+ YCHAR name[NAME_MAX+1]; /* name of directory being searched */
yaffs_Object *dirObj; /* ptr to directory being searched */
yaffs_Object *nextReturn; /* obj to be returned by next readddir */
int offset;
- struct list_head others;
+ struct ylist_head others;
} yaffsfs_DirectorySearchContext;
-static struct list_head search_contexts;
+static struct ylist_head search_contexts;
static void yaffsfs_SetDirRewound(yaffsfs_DirectorySearchContext *dsc)
@@ -1196,10 +1655,10 @@ static void yaffsfs_SetDirRewound(yaffsfs_DirectorySearchContext *dsc)
dsc->offset = 0;
- if( list_empty(&dsc->dirObj->variant.directoryVariant.children)){
+ if( ylist_empty(&dsc->dirObj->variant.directoryVariant.children)){
dsc->nextReturn = NULL;
} else {
- dsc->nextReturn = list_entry(dsc->dirObj->variant.directoryVariant.children.next,
+ dsc->nextReturn = ylist_entry(dsc->dirObj->variant.directoryVariant.children.next,
yaffs_Object,siblings);
}
} else {
@@ -1214,15 +1673,15 @@ static void yaffsfs_DirAdvance(yaffsfs_DirectorySearchContext *dsc)
dsc->dirObj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY){
if( dsc->nextReturn == NULL ||
- list_empty(&dsc->dirObj->variant.directoryVariant.children)){
+ ylist_empty(&dsc->dirObj->variant.directoryVariant.children)){
dsc->nextReturn = NULL;
} else {
- struct list_head *next = dsc->nextReturn->siblings.next;
+ struct ylist_head *next = dsc->nextReturn->siblings.next;
if( next == &dsc->dirObj->variant.directoryVariant.children)
dsc->nextReturn = NULL; /* end of list */
else
- dsc->nextReturn = list_entry(next,yaffs_Object,siblings);
+ dsc->nextReturn = ylist_entry(next,yaffs_Object,siblings);
}
} else {
/* Hey someone isn't playing nice! */
@@ -1232,20 +1691,20 @@ static void yaffsfs_DirAdvance(yaffsfs_DirectorySearchContext *dsc)
static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj)
{
- struct list_head *i;
+ struct ylist_head *i;
yaffsfs_DirectorySearchContext *dsc;
/* if search contexts not initilised then skip */
if(!search_contexts.next)
return;
- /* Iteratethrough the directory search contexts.
+ /* Iterate through the directory search contexts.
* If any are the one being removed, then advance the dsc to
* the next one to prevent a hanging ptr.
*/
- list_for_each(i, &search_contexts) {
+ ylist_for_each(i, &search_contexts) {
if (i) {
- dsc = list_entry(i, yaffsfs_DirectorySearchContext,others);
+ dsc = ylist_entry(i, yaffsfs_DirectorySearchContext,others);
if(dsc->nextReturn == obj)
yaffsfs_DirAdvance(dsc);
}
@@ -1253,7 +1712,7 @@ static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj)
}
-yaffs_DIR *yaffs_opendir(const char *dirname)
+yaffs_DIR *yaffs_opendir(const YCHAR *dirname)
{
yaffs_DIR *dir = NULL;
yaffs_Object *obj = NULL;
@@ -1273,13 +1732,13 @@ yaffs_DIR *yaffs_opendir(const char *dirname)
memset(dsc,0,sizeof(yaffsfs_DirectorySearchContext));
dsc->magic = YAFFS_MAGIC;
dsc->dirObj = obj;
- strncpy(dsc->name,dirname,NAME_MAX);
- INIT_LIST_HEAD(&dsc->others);
+ yaffs_strncpy(dsc->name,dirname,NAME_MAX);
+ YINIT_LIST_HEAD(&dsc->others);
if(!search_contexts.next)
- INIT_LIST_HEAD(&search_contexts);
+ YINIT_LIST_HEAD(&search_contexts);
- list_add(&dsc->others,&search_contexts);
+ ylist_add(&dsc->others,&search_contexts);
yaffsfs_SetDirRewound(dsc); }
}
@@ -1303,10 +1762,10 @@ struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp)
dsc->de.d_dont_use = (unsigned)dsc->nextReturn;
dsc->de.d_off = dsc->offset++;
yaffs_GetObjectName(dsc->nextReturn,dsc->de.d_name,NAME_MAX);
- if(strlen(dsc->de.d_name) == 0)
+ if(yaffs_strlen(dsc->de.d_name) == 0)
{
// this should not happen!
- strcpy(dsc->de.d_name,"zz");
+ yaffs_strcpy(dsc->de.d_name,_Y("zz"));
}
dsc->de.d_reclen = sizeof(struct yaffs_dirent);
retVal = &dsc->de;
@@ -1344,7 +1803,7 @@ int yaffs_closedir(yaffs_DIR *dirp)
yaffsfs_Lock();
dsc->magic = 0;
- list_del(&dsc->others); /* unhook from list */
+ ylist_del(&dsc->others); /* unhook from list */
YFREE(dsc);
yaffsfs_Unlock();
return 0;
@@ -1353,11 +1812,11 @@ int yaffs_closedir(yaffs_DIR *dirp)
// end of directory stuff
-int yaffs_symlink(const char *oldpath, const char *newpath)
+int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath)
{
yaffs_Object *parent = NULL;
yaffs_Object *obj;
- char *name;
+ YCHAR *name;
int retVal= -1;
int mode = 0; // ignore for now
@@ -1380,7 +1839,7 @@ int yaffs_symlink(const char *oldpath, const char *newpath)
}
-int yaffs_readlink(const char *path, char *buf, int bufsiz)
+int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz)
{
yaffs_Object *obj = NULL;
int retVal;
@@ -1402,16 +1861,16 @@ int yaffs_readlink(const char *path, char *buf, int bufsiz)
}
else
{
- char *alias = obj->variant.symLinkVariant.alias;
+ YCHAR *alias = obj->variant.symLinkVariant.alias;
memset(buf,0,bufsiz);
- strncpy(buf,alias,bufsiz - 1);
+ yaffs_strncpy(buf,alias,bufsiz - 1);
retVal = 0;
}
yaffsfs_Unlock();
return retVal;
}
-int yaffs_link(const char *oldpath, const char *newpath)
+int yaffs_link(const YCHAR *oldpath, const YCHAR *newpath)
{
// Creates a link called newpath to existing oldpath
yaffs_Object *obj = NULL;
@@ -1439,7 +1898,7 @@ int yaffs_link(const char *oldpath, const char *newpath)
yaffs_Object *newdir = NULL;
yaffs_Object *link = NULL;
- char *newname;
+ YCHAR *newname;
newdir = yaffsfs_FindDirectory(NULL,newpath,&newname,0);
@@ -1453,7 +1912,7 @@ int yaffs_link(const char *oldpath, const char *newpath)
yaffsfs_SetError(-EXDEV);
retVal = -1;
}
- if(newdir && strlen(newname) > 0)
+ if(newdir && yaffs_strlen(newname) > 0)
{
link = yaffs_Link(newdir,newname,obj);
if(link)
@@ -1471,11 +1930,12 @@ int yaffs_link(const char *oldpath, const char *newpath)
return retVal;
}
-int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev);
+int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev);
-int yaffs_DumpDevStruct(const char *path)
+int yaffs_DumpDevStruct(const YCHAR *path)
{
- char *rest;
+#if 0
+ YCHAR *rest;
yaffs_Object *obj = yaffsfs_FindRoot(path,&rest);
@@ -1500,6 +1960,8 @@ int yaffs_DumpDevStruct(const char *path)
);
}
+
+#endif
return 0;
}
diff --git a/direct/yaffsfs.h b/direct/yaffsfs.h
index 9afe60a..fe4eff5 100644
--- a/direct/yaffsfs.h
+++ b/direct/yaffsfs.h
@@ -35,6 +35,9 @@
#define NAME_MAX 256
#endif
+
+#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES
+
#ifndef O_RDONLY
#define O_RDONLY 00
#endif
@@ -91,8 +94,8 @@
#define EBADF 9
#endif
-#ifndef EACCESS
-#define EACCESS 13
+#ifndef EACCES
+#define EACCES 13
#endif
#ifndef EXDEV
@@ -154,14 +157,30 @@
#define S_IWRITE 0000200
#endif
+#ifndef S_IEXEC
+#define S_IEXEC 0000100
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#define F_OK 0
+#endif
+#else
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
struct yaffs_dirent{
long d_ino; /* inode number */
off_t d_off; /* offset to this dirent */
unsigned short d_reclen; /* length of this d_name */
- char d_name [NAME_MAX+1]; /* file name (null-terminated) */
+ YUCHAR d_type; /* type of this record */
+ YCHAR d_name [NAME_MAX+1]; /* file name (null-terminated) */
unsigned d_dont_use; /* debug pointer, not for public consumption */
};
@@ -175,7 +194,7 @@ typedef struct __opaque yaffs_DIR;
struct yaffs_stat{
int st_dev; /* device */
int st_ino; /* inode */
- mode_t st_mode; /* protection */
+ unsigned st_mode; /* protection */
int st_nlink; /* number of hard links */
int st_uid; /* user ID of owner */
int st_gid; /* group ID of owner */
@@ -183,46 +202,68 @@ struct yaffs_stat{
off_t st_size; /* total size, in bytes */
unsigned long st_blksize; /* blocksize for filesystem I/O */
unsigned long st_blocks; /* number of blocks allocated */
- unsigned long yst_atime; /* time of last access */
+#ifdef CONFIG_YAFFS_WINCE
+ /* Special 64-bit times for WinCE */
+ unsigned long yst_wince_atime[2];
+ unsigned long yst_wince_mtime[2];
+ unsigned long yst_wince_ctime[2];
+#else
+ unsigned long yst_atime; /* time of last access */
unsigned long yst_mtime; /* time of last modification */
unsigned long yst_ctime; /* time of last change */
+#endif
};
-int yaffs_open(const char *path, int oflag, int mode) ;
+int yaffs_open(const YCHAR *path, int oflag, int mode) ;
+int yaffs_close(int fd) ;
+int yaffs_flush(int fd) ;
+
+int yaffs_access(const YCHAR *path, int amode);
+
+int yaffs_dup(int fd);
+
int yaffs_read(int fd, void *buf, unsigned int nbyte) ;
int yaffs_write(int fd, const void *buf, unsigned int nbyte) ;
-int yaffs_close(int fd) ;
+
+int yaffs_pread(int fd, void *buf, unsigned int nbyte, unsigned int offset);
+int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, unsigned int offset);
+
off_t yaffs_lseek(int fd, off_t offset, int whence) ;
-int yaffs_truncate(int fd, off_t newSize);
-int yaffs_unlink(const char *path) ;
-int yaffs_rename(const char *oldPath, const char *newPath) ;
+int yaffs_truncate(const YCHAR *path, off_t newSize);
+int yaffs_ftruncate(int fd, off_t newSize);
-int yaffs_stat(const char *path, struct yaffs_stat *buf) ;
-int yaffs_lstat(const char *path, struct yaffs_stat *buf) ;
+int yaffs_unlink(const YCHAR *path) ;
+int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath) ;
+
+int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf) ;
+int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf) ;
int yaffs_fstat(int fd, struct yaffs_stat *buf) ;
-int yaffs_chmod(const char *path, mode_t mode);
+int yaffs_chmod(const YCHAR *path, mode_t mode);
int yaffs_fchmod(int fd, mode_t mode);
-int yaffs_mkdir(const char *path, mode_t mode) ;
-int yaffs_rmdir(const char *path) ;
+int yaffs_mkdir(const YCHAR *path, mode_t mode) ;
+int yaffs_rmdir(const YCHAR *path) ;
-yaffs_DIR *yaffs_opendir(const char *dirname) ;
+yaffs_DIR *yaffs_opendir(const YCHAR *dirname) ;
struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp) ;
void yaffs_rewinddir(yaffs_DIR *dirp) ;
int yaffs_closedir(yaffs_DIR *dirp) ;
-int yaffs_mount(const char *path) ;
-int yaffs_unmount(const char *path) ;
+int yaffs_mount(const YCHAR *path) ;
+int yaffs_unmount(const YCHAR *path) ;
+
+int yaffs_sync(const YCHAR *path) ;
-int yaffs_symlink(const char *oldpath, const char *newpath);
-int yaffs_readlink(const char *path, char *buf, int bufsiz);
+int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath);
+int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz);
-int yaffs_link(const char *oldpath, const char *newpath);
-int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev);
+int yaffs_link(const YCHAR *oldpath, const YCHAR *newpath);
+int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev);
-loff_t yaffs_freespace(const char *path);
+loff_t yaffs_freespace(const YCHAR *path);
+loff_t yaffs_totalspace(const YCHAR *path);
void yaffs_initialise(yaffsfs_DeviceConfiguration *configList);
diff --git a/direct/ydirectenv.h b/direct/ydirectenv.h
index 0c28205..6a2bb18 100644
--- a/direct/ydirectenv.h
+++ b/direct/ydirectenv.h
@@ -30,7 +30,8 @@
#include "yaffs_malloc.h"
#include "assert.h"
-#define YBUG() assert(1)
+#define YBUG() assert(0)
+
#define YCHAR char
#define YUCHAR unsigned char
@@ -42,6 +43,8 @@
#define yaffs_sprintf sprintf
#define yaffs_toupper(a) toupper(a)
+#define YAFFS_PATH_DIVIDERS "/"
+
#ifdef NO_Y_INLINE
#define Y_INLINE
#else
diff --git a/yaffs_checkptrw.c b/yaffs_checkptrw.c
index d1ecdf5..68e6d0c 100644
--- a/yaffs_checkptrw.c
+++ b/yaffs_checkptrw.c
@@ -12,11 +12,11 @@
*/
const char *yaffs_checkptrw_c_version =
- "$Id: yaffs_checkptrw.c,v 1.15 2007-12-13 15:35:17 wookey Exp $";
+ "$Id: yaffs_checkptrw.c,v 1.16 2008-05-05 07:58:58 charles Exp $";
#include "yaffs_checkptrw.h"
-
+#include "yaffs_getblockinfo.h"
static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
{
@@ -142,7 +142,7 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
return 0;
if(!dev->checkpointBuffer)
- dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
+ dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
if(!dev->checkpointBuffer)
return 0;
diff --git a/yaffs_fs.c b/yaffs_fs.c
index eceb34f..ab6a3a7 100644
--- a/yaffs_fs.c
+++ b/yaffs_fs.c
@@ -32,7 +32,7 @@
*/
const char *yaffs_fs_c_version =
- "$Id: yaffs_fs.c,v 1.65 2007-12-13 15:35:17 wookey Exp $";
+ "$Id: yaffs_fs.c,v 1.66 2008-05-05 07:58:58 charles Exp $";
extern const char *yaffs_guts_c_version;
#include <linux/version.h>
@@ -53,6 +53,8 @@ extern const char *yaffs_guts_c_version;
#include <linux/string.h>
#include <linux/ctype.h>
+#include "asm/div64.h"
+
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
#include <linux/statfs.h> /* Added NCB 15-8-2003 */
@@ -753,6 +755,8 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
break;
}
+ inode->i_flags |= S_NOATIME;
+
inode->i_ino = obj->objectId;
inode->i_mode = obj->yst_mode;
inode->i_uid = obj->yst_uid;
@@ -1350,25 +1354,47 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
buf->f_type = YAFFS_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_namelen = 255;
- if (sb->s_blocksize > dev->nDataBytesPerChunk) {
-
+
+ if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){
+ /* Do this if chunk size is not a power of 2 */
+
+ uint64_t bytesInDev;
+ uint64_t bytesFree;
+
+ bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) *
+ ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
+
+ do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */
+ buf->f_blocks = bytesInDev;
+
+ bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
+ ((uint64_t)(dev->nDataBytesPerChunk));
+
+ do_div(bytesFree,sb->s_blocksize);
+
+ buf->f_bfree = bytesFree;
+
+ } else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
+
buf->f_blocks =
- (dev->endBlock - dev->startBlock +
- 1) * dev->nChunksPerBlock / (sb->s_blocksize /
- dev->nDataBytesPerChunk);
- buf->f_bfree =
- yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
- dev->nDataBytesPerChunk);
+ (dev->endBlock - dev->startBlock + 1) *
+ dev->nChunksPerBlock /
+ (sb->s_blocksize / dev->nDataBytesPerChunk);
+ buf->f_bfree =
+ yaffs_GetNumberOfFreeChunks(dev) /
+ (sb->s_blocksize / dev->nDataBytesPerChunk);
} else {
-
- buf->f_blocks =
- (dev->endBlock - dev->startBlock +
- 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
- sb->s_blocksize);
- buf->f_bfree =
- yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
- sb->s_blocksize);
+ buf->f_blocks =
+ (dev->endBlock - dev->startBlock + 1) *
+ dev->nChunksPerBlock *
+ (dev->nDataBytesPerChunk / sb->s_blocksize);
+
+ buf->f_bfree =
+ yaffs_GetNumberOfFreeChunks(dev) *
+ (dev->nDataBytesPerChunk / sb->s_blocksize);
}
+
+
buf->f_files = 0;
buf->f_ffree = 0;
buf->f_bavail = buf->f_bfree;
@@ -1602,6 +1628,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
sb->s_magic = YAFFS_MAGIC;
sb->s_op = &yaffs_super_ops;
+ sb->s_flags |= MS_NOATIME;
if (!sb)
printk(KERN_INFO "yaffs: sb is NULL\n");
@@ -1678,22 +1705,15 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
#ifdef CONFIG_YAFFS_AUTO_YAFFS2
if (yaffsVersion == 1 &&
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
- mtd->writesize >= 2048) {
-#else
- mtd->oobblock >= 2048) {
-#endif
+ WRITE_SIZE(mtd) >= 2048) {
T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
yaffsVersion = 2;
}
/* Added NCB 26/5/2006 for completeness */
- if (yaffsVersion == 2 &&
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
- mtd->writesize == 512) {
-#else
- mtd->oobblock == 512) {
-#endif
+ if (yaffsVersion == 2 &&
+ !options.inband_tags &&
+ WRITE_SIZE(mtd) == 512){
T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
yaffsVersion = 1;
}
@@ -1719,12 +1739,9 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
return NULL;
}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
- if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
-#else
- if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
-#endif
- mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
+ if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+ mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
+ !options.inband_tags) {
T(YAFFS_TRACE_ALWAYS,
("yaffs: MTD device does not have the "
"right page sizes\n"));
@@ -1784,9 +1801,10 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
dev->startBlock = 0;
dev->endBlock = nBlocks - 1;
dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
- dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+ dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
dev->nReservedBlocks = 5;
dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
+ dev->inbandTags = options.inband_tags;
/* ... and the functions. */
if (yaffsVersion == 2) {
@@ -1799,10 +1817,10 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
dev->spareBuffer = YMALLOC(mtd->oobsize);
dev->isYaffs2 = 1;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
- dev->nDataBytesPerChunk = mtd->writesize;
+ dev->totalBytesPerChunk = mtd->writesize;
dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
#else
- dev->nDataBytesPerChunk = mtd->oobblock;
+ dev->totalBytesPerChunk = mtd->oobblock;
dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
#endif
nBlocks = mtd->size / mtd->erasesize;
@@ -1989,6 +2007,7 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)
{
buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);
buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock);
+ buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk);
buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk);
buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);
buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
@@ -2004,10 +2023,8 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)
buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);
buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);
buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies);
- buf +=
- sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
- buf +=
- sprintf(buf, "passiveGCs......... %d\n",
+ buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
+ buf += sprintf(buf, "passiveGCs......... %d\n",
dev->passiveGarbageCollections);
buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);
buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches);
@@ -2023,6 +2040,7 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)
sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
+ buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
return buf;
}
diff --git a/yaffs_guts.c b/yaffs_guts.c
index 097b525..c1a5b0c 100644
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -12,13 +12,14 @@
*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.54 2007-12-13 15:35:17 wookey Exp $";
+ "$Id: yaffs_guts.c,v 1.55 2008-05-05 07:58:58 charles Exp $";
#include "yportenv.h"
#include "yaffsinterface.h"
#include "yaffs_guts.h"
#include "yaffs_tagsvalidity.h"
+#include "yaffs_getblockinfo.h"
#include "yaffs_tagscompat.h"
#ifndef CONFIG_YAFFS_USE_OWN_SORT
@@ -78,9 +79,6 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in);
static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
- int lineNo);
static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
int chunkInNAND);
@@ -121,23 +119,32 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,
/* Function to calculate chunk and offset */
-static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
+static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut)
{
- if(dev->chunkShift){
- /* Easy-peasy power of 2 case */
- *chunk = (__u32)(addr >> dev->chunkShift);
- *offset = (__u32)(addr & dev->chunkMask);
- }
- else if(dev->crumbsPerChunk)
+ int chunk;
+ __u32 offset;
+
+ chunk = (__u32)(addr >> dev->chunkShift);
+
+ if(dev->chunkDiv == 1)
{
- /* Case where we're using "crumbs" */
- *offset = (__u32)(addr & dev->crumbMask);
- addr >>= dev->crumbShift;
- *chunk = ((__u32)addr)/dev->crumbsPerChunk;
- *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
+ /* easy power of 2 case */
+ offset = (__u32)(addr & dev->chunkMask);
}
else
- YBUG();
+ {
+ /* Non power-of-2 case */
+
+ loff_t chunkBase;
+
+ chunk /= dev->chunkDiv;
+
+ chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
+ offset = (__u32)(addr - chunkBase);
+ }
+
+ *chunkOut = chunk;
+ *offsetOut = offset;
}
/* Function to return the number of shifts for a power of 2 greater than or equal
@@ -168,7 +175,7 @@ static __u32 ShiftsGE(__u32 x)
/* Function to return the number of shifts to get a 1 in bit 0
*/
-static __u32 ShiftDiv(__u32 x)
+static __u32 Shifts(__u32 x)
{
int nShifts;
@@ -200,16 +207,21 @@ static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
dev->tempBuffer[i].line = 0; /* not in use */
dev->tempBuffer[i].buffer = buf =
- YMALLOC_DMA(dev->nDataBytesPerChunk);
+ YMALLOC_DMA(dev->totalBytesPerChunk);
}
return buf ? YAFFS_OK : YAFFS_FAIL;
}
-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
+__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
{
int i, j;
+
+ dev->tempInUse++;
+ if(dev->tempInUse > dev->maxTemp)
+ dev->maxTemp = dev->tempInUse;
+
for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
if (dev->tempBuffer[i].line == 0) {
dev->tempBuffer[i].line = lineNo;
@@ -242,10 +254,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
}
-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
+void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
int lineNo)
{
int i;
+
+ dev->tempInUse--;
+
for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
if (dev->tempBuffer[i].buffer == buffer) {
dev->tempBuffer[i].line = 0;
@@ -390,11 +405,14 @@ static int yaffs_SkipVerification(yaffs_Device *dev)
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
}
+#if 0
static int yaffs_SkipFullVerification(yaffs_Device *dev)
{
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL));
}
+#endif
+
static int yaffs_SkipNANDVerification(yaffs_Device *dev)
{
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND));
@@ -597,7 +615,6 @@ static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn,
int i;
yaffs_Device *dev = obj->myDev;
int ok = 1;
- int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
if (tn) {
if (level > 0) {
@@ -646,7 +663,6 @@ static void yaffs_VerifyFile(yaffs_Object *obj)
__u32 lastChunk;
__u32 x;
__u32 i;
- int ok;
yaffs_Device *dev;
yaffs_ExtendedTags tags;
yaffs_Tnode *tn;
@@ -829,7 +845,7 @@ static void yaffs_VerifyObjects(yaffs_Device *dev)
{
yaffs_Object *obj;
int i;
- struct list_head *lh;
+ struct ylist_head *lh;
if(yaffs_SkipVerification(dev))
return;
@@ -837,9 +853,9 @@ static void yaffs_VerifyObjects(yaffs_Device *dev)
/* Iterate through the objects in each hash entry */
for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
- list_for_each(lh, &dev->objectBucket[i].list) {
+ ylist_for_each(lh, &dev->objectBucket[i].list) {
if (lh) {
- obj = list_entry(lh, yaffs_Object, hashLink);
+ obj = ylist_entry(lh, yaffs_Object, hashLink);
yaffs_VerifyObject(obj);
}
}
@@ -1869,7 +1885,7 @@ static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects)
/* Hook them into the free list */
for (i = 0; i < nObjects - 1; i++) {
newObjects[i].siblings.next =
- (struct list_head *)(&newObjects[i + 1]);
+ (struct ylist_head *)(&newObjects[i + 1]);
}
newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
@@ -1909,9 +1925,9 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
tn->myDev = dev;
tn->chunkId = -1;
tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
- INIT_LIST_HEAD(&(tn->hardLinks));
- INIT_LIST_HEAD(&(tn->hashLink));
- INIT_LIST_HEAD(&tn->siblings);
+ YINIT_LIST_HEAD(&(tn->hardLinks));
+ YINIT_LIST_HEAD(&(tn->hashLink));
+ YINIT_LIST_HEAD(&tn->siblings);
/* Add it to the lost and found directory.
* NB Can't put root or lostNFound in lostNFound so
@@ -1954,8 +1970,8 @@ static void yaffs_UnhashObject(yaffs_Object * tn)
yaffs_Device *dev = tn->myDev;
/* If it is still linked into the bucket list, free from the list */
- if (!list_empty(&tn->hashLink)) {
- list_del_init(&tn->hashLink);
+ if (!ylist_empty(&tn->hashLink)) {
+ ylist_del_init(&tn->hashLink);
bucket = yaffs_HashFunction(tn->objectId);
dev->objectBucket[bucket].count--;
}
@@ -1981,7 +1997,7 @@ static void yaffs_FreeObject(yaffs_Object * tn)
yaffs_UnhashObject(tn);
/* Link into the free list. */
- tn->siblings.next = (struct list_head *)(dev->freeObjects);
+ tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
dev->freeObjects = tn;
dev->nFreeObjects++;
@@ -2027,7 +2043,7 @@ static void yaffs_InitialiseObjects(yaffs_Device * dev)
dev->nFreeObjects = 0;
for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
- INIT_LIST_HEAD(&dev->objectBucket[i].list);
+ YINIT_LIST_HEAD(&dev->objectBucket[i].list);
dev->objectBucket[i].count = 0;
}
@@ -2078,7 +2094,7 @@ static int yaffs_CreateNewObjectNumber(yaffs_Device * dev)
*/
int found = 0;
- struct list_head *i;
+ struct ylist_head *i;
__u32 n = (__u32) bucket;
@@ -2088,10 +2104,10 @@ static int yaffs_CreateNewObjectNumber(yaffs_Device * dev)
found = 1;
n += YAFFS_NOBJECT_BUCKETS;
if (1 || dev->objectBucket[bucket].count > 0) {
- list_for_each(i, &dev->objectBucket[bucket].list) {
+ ylist_for_each(i, &dev->objectBucket[bucket].list) {
/* If there is already one in the list */
if (i
- && list_entry(i, yaffs_Object,
+ && ylist_entry(i, yaffs_Object,
hashLink)->objectId == n) {
found = 0;
}
@@ -2108,7 +2124,7 @@ static void yaffs_HashObject(yaffs_Object * in)
int bucket = yaffs_HashFunction(in->objectId);
yaffs_Device *dev = in->myDev;
- list_add(&in->hashLink, &dev->objectBucket[bucket].list);
+ ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);
dev->objectBucket[bucket].count++;
}
@@ -2116,13 +2132,13 @@ static void yaffs_HashObject(yaffs_Object * in)
yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
{
int bucket = yaffs_HashFunction(number);
- struct list_head *i;
+ struct ylist_head *i;
yaffs_Object *in;
- list_for_each(i, &dev->objectBucket[bucket].list) {
+ ylist_for_each(i, &dev->objectBucket[bucket].list) {
/* Look if it is in the list */
if (i) {
- in = list_entry(i, yaffs_Object, hashLink);
+ in = ylist_entry(i, yaffs_Object, hashLink);
if (in->objectId == number) {
#ifdef __KERNEL__
/* Don't tell the VFS about this one if it is defered free */
@@ -2143,7 +2159,7 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
{
yaffs_Object *theObject;
- yaffs_Tnode *tn;
+ yaffs_Tnode *tn = NULL;
if (number < 0) {
number = yaffs_CreateNewObjectNumber(dev);
@@ -2191,7 +2207,7 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
theObject->variant.fileVariant.top = tn;
break;
case YAFFS_OBJECT_TYPE_DIRECTORY:
- INIT_LIST_HEAD(&theObject->variant.directoryVariant.
+ YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
children);
break;
case YAFFS_OBJECT_TYPE_SYMLINK:
@@ -2258,7 +2274,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
const YCHAR * aliasString, __u32 rdev)
{
yaffs_Object *in;
- YCHAR *str;
+ YCHAR *str = NULL;
yaffs_Device *dev = parent->myDev;
@@ -2316,7 +2332,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
equivalentObject;
in->variant.hardLinkVariant.equivalentObjectId =
equivalentObject->objectId;
- list_add(&in->hardLinks, &equivalentObject->hardLinks);
+ ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
break;
case YAFFS_OBJECT_TYPE_FILE:
case YAFFS_OBJECT_TYPE_DIRECTORY:
@@ -2477,7 +2493,7 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
existingTarget = yaffs_FindObjectByName(newDir, newName);
if (existingTarget &&
existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
- !list_empty(&existingTarget->variant.directoryVariant.children)) {
+ !ylist_empty(&existingTarget->variant.directoryVariant.children)) {
/* There is a target that is a non-empty directory, so we fail */
return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */
} else if (existingTarget && existingTarget != obj) {
@@ -3091,7 +3107,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
yaffs_ObjectHeader *oh;
oh = (yaffs_ObjectHeader *)buffer;
oh->isShrink = 0;
- oh->shadowsObject = -1;
+ oh->shadowsObject = oh->inbandShadowsObject = -1;
tags.extraShadows = 0;
tags.extraIsShrinkHeader = 0;
@@ -3682,7 +3698,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,
oh->type = in->variantType;
oh->yst_mode = in->yst_mode;
- oh->shadowsObject = shadows;
+ oh->shadowsObject = oh->inbandShadowsObject = shadows;
#ifdef CONFIG_YAFFS_WINCE
oh->win_atime[0] = in->win_atime[0];
@@ -4376,7 +4392,7 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
yaffs_CheckpointObject cp;
int i;
int ok = 1;
- struct list_head *lh;
+ struct ylist_head *lh;
/* Iterate through the objects in each hash entry,
@@ -4384,9 +4400,9 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
*/
for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){
- list_for_each(lh, &dev->objectBucket[i].list) {
+ ylist_for_each(lh, &dev->objectBucket[i].list) {
if (lh) {
- obj = list_entry(lh, yaffs_Object, hashLink);
+ obj = ylist_entry(lh, yaffs_Object, hashLink);
if (!obj->deferedFree) {
yaffs_ObjectToCheckpointObject(&cp,obj);
cp.structType = sizeof(cp);
@@ -4444,7 +4460,7 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
ok = yaffs_ReadCheckpointTnodes(obj);
} else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
obj->hardLinks.next =
- (struct list_head *)
+ (struct ylist_head *)
hardList;
hardList = obj;
}
@@ -4650,7 +4666,7 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
{
int chunk;
- int start;
+ __u32 start;
int nToCopy;
int n = nBytes;
int nDone = 0;
@@ -4678,10 +4694,10 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
cache = yaffs_FindChunkCache(in, chunk);
/* If the chunk is already in the cache or it is less than a whole chunk
- * then use the cache (if there is caching)
+ * or we're using inband tags then use the cache (if there is caching)
* else bypass the cache.
*/
- if (cache || nToCopy != dev->nDataBytesPerChunk) {
+ if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
if (dev->nShortOpCaches > 0) {
/* If we can't find the data in the cache, then load it up. */
@@ -4770,7 +4786,7 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
{
int chunk;
- int start;
+ __u32 start;
int nToCopy;
int n = nBytes;
int nDone = 0;
@@ -4818,8 +4834,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
nToWriteBack = dev->nDataBytesPerChunk;
}
- if (nToCopy != dev->nDataBytesPerChunk) {
- /* An incomplete start or end chunk (or maybe both start and end chunk) */
+ if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
+ /* An incomplete start or end chunk (or maybe both start and end chunk),
+ * or we're using inband tags, so we want to use the cache buffers.
+ */
if (dev->nShortOpCaches > 0) {
yaffs_ChunkCache *cache;
/* If we can't find the data in the cache, then load the cache */
@@ -4907,7 +4925,8 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
}
} else {
-
+ /* A full chunk. Write directly from the supplied buffer. */
+
#ifdef CONFIG_YAFFS_WINCE
/* Under WinCE can't do direct transfer. Need to use a local buffer.
* This is because we otherwise screw up WinCE's memory mapper
@@ -4926,7 +4945,7 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
0);
yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
#else
- /* A full chunk. Write directly from the supplied buffer. */
+
chunkWritten =
yaffs_WriteChunkDataToObject(in, chunk, buffer,
dev->nDataBytesPerChunk,
@@ -5004,7 +5023,7 @@ int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)
{
int oldFileSize = in->variant.fileVariant.fileSize;
- int newSizeOfPartialChunk;
+ __u32 newSizeOfPartialChunk;
int newFullChunks;
yaffs_Device *dev = in->myDev;
@@ -5017,11 +5036,11 @@ int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)
yaffs_CheckGarbageCollection(dev);
if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
- return yaffs_GetFileSize(in);
+ return YAFFS_FAIL;
}
if (newSize == oldFileSize) {
- return oldFileSize;
+ return YAFFS_OK;
}
if (newSize < oldFileSize) {
@@ -5119,7 +5138,7 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)
if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
/* Move to the unlinked directory so we have a record that it was deleted. */
- yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
+ yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0);
}
@@ -5157,7 +5176,7 @@ static int yaffs_UnlinkFile(yaffs_Object * in)
if (immediateDeletion) {
retVal =
yaffs_ChangeObjectName(in, in->myDev->deletedDir,
- "deleted", 0, 0);
+ _Y("deleted"), 0, 0);
T(YAFFS_TRACE_TRACING,
(TSTR("yaffs: immediate deletion of file %d" TENDSTR),
in->objectId));
@@ -5170,7 +5189,7 @@ static int yaffs_UnlinkFile(yaffs_Object * in)
} else {
retVal =
yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
- "unlinked", 0, 0);
+ _Y("unlinked"), 0, 0);
}
}
@@ -5205,7 +5224,7 @@ int yaffs_DeleteFile(yaffs_Object * in)
static int yaffs_DeleteDirectory(yaffs_Object * in)
{
/* First check that the directory is empty. */
- if (list_empty(&in->variant.directoryVariant.children)) {
+ if (ylist_empty(&in->variant.directoryVariant.children)) {
return yaffs_DoGenericObjectDeletion(in);
}
@@ -5225,7 +5244,7 @@ static int yaffs_DeleteHardLink(yaffs_Object * in)
/* remove this hardlink from the list assocaited with the equivalent
* object
*/
- list_del(&in->hardLinks);
+ ylist_del(&in->hardLinks);
return yaffs_DoGenericObjectDeletion(in);
}
@@ -5257,7 +5276,7 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj)
if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
return yaffs_DeleteHardLink(obj);
- } else if (!list_empty(&obj->hardLinks)) {
+ } else if (!ylist_empty(&obj->hardLinks)) {
/* Curve ball: We're unlinking an object that has a hardlink.
*
* This problem arises because we are not strictly following
@@ -5276,10 +5295,10 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj)
int retVal;
YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
- hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
+ hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
- list_del_init(&hl->hardLinks);
- list_del_init(&hl->siblings);
+ ylist_del_init(&hl->hardLinks);
+ ylist_del_init(&hl->siblings);
yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
@@ -5386,13 +5405,13 @@ static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList)
if (in) {
/* Add the hardlink pointers */
hl->variant.hardLinkVariant.equivalentObject = in;
- list_add(&hl->hardLinks, &in->hardLinks);
+ ylist_add(&hl->hardLinks, &in->hardLinks);
} else {
/* Todo Need to report/handle this better.
* Got a problem... hardlink to a non-existant object
*/
hl->variant.hardLinkVariant.equivalentObject = NULL;
- INIT_LIST_HEAD(&hl->hardLinks);
+ YINIT_LIST_HEAD(&hl->hardLinks);
}
@@ -5432,7 +5451,7 @@ static int yaffs_Scan(yaffs_Device * dev)
yaffs_BlockState state;
yaffs_Object *hardList = NULL;
yaffs_BlockInfo *bi;
- int sequenceNumber;
+ __u32 sequenceNumber;
yaffs_ObjectHeader *oh;
yaffs_Object *in;
yaffs_Object *parent;
@@ -5609,8 +5628,7 @@ static int yaffs_Scan(yaffs_Device * dev)
bi->sequenceNumber)) {
T(YAFFS_TRACE_ALWAYS,
(TSTR
- ("yaffs: Allocation block %d was not highest sequence id:"
- " block seq = %d, dev seq = %d"
+ ("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d"
TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
}
}
@@ -5784,7 +5802,7 @@ static int yaffs_Scan(yaffs_Device * dev)
/* Set up as a directory */
parent->variantType =
YAFFS_OBJECT_TYPE_DIRECTORY;
- INIT_LIST_HEAD(&parent->variant.
+ YINIT_LIST_HEAD(&parent->variant.
directoryVariant.
children);
} else if (parent->variantType !=
@@ -5796,8 +5814,7 @@ static int yaffs_Scan(yaffs_Device * dev)
T(YAFFS_TRACE_ERROR,
(TSTR
- ("yaffs tragedy: attempting to use non-directory as"
- " a directory in scan. Put in lost+found."
+ ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
TENDSTR)));
parent = dev->lostNFoundDir;
}
@@ -5842,7 +5859,7 @@ static int yaffs_Scan(yaffs_Device * dev)
equivalentObjectId =
oh->equivalentObjectId;
in->hardLinks.next =
- (struct list_head *)
+ (struct ylist_head *)
hardList;
hardList = in;
break;
@@ -5901,16 +5918,16 @@ static int yaffs_Scan(yaffs_Device * dev)
* just delete them.
*/
{
- struct list_head *i;
- struct list_head *n;
+ struct ylist_head *i;
+ struct ylist_head *n;
yaffs_Object *l;
/* Soft delete all the unlinked files */
- list_for_each_safe(i, n,
+ ylist_for_each_safe(i, n,
&dev->unlinkedDir->variant.directoryVariant.
children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_DestroyObject(l);
}
}
@@ -5999,7 +6016,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
yaffs_BlockState state;
yaffs_Object *hardList = NULL;
yaffs_BlockInfo *bi;
- int sequenceNumber;
+ __u32 sequenceNumber;
yaffs_ObjectHeader *oh;
yaffs_Object *in;
yaffs_Object *parent;
@@ -6328,6 +6345,12 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
NULL);
oh = (yaffs_ObjectHeader *) chunkData;
+
+ if(dev->inbandTags){
+ /* Fix up the header if they got corrupted by inband tags */
+ oh->shadowsObject = oh->inbandShadowsObject;
+ oh->isShrink = oh->inbandIsShrink;
+ }
if (!in)
in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
@@ -6338,8 +6361,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
/* TODO Hoosterman we have a problem! */
T(YAFFS_TRACE_ERROR,
(TSTR
- ("yaffs tragedy: Could not make object for object %d "
- "at chunk %d during scan"
+ ("yaffs tragedy: Could not make object for object %d at chunk %d during scan"
TENDSTR), tags.objectId, chunk));
}
@@ -6497,7 +6519,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
/* Set up as a directory */
parent->variantType =
YAFFS_OBJECT_TYPE_DIRECTORY;
- INIT_LIST_HEAD(&parent->variant.
+ YINIT_LIST_HEAD(&parent->variant.
directoryVariant.
children);
} else if (parent->variantType !=
@@ -6509,8 +6531,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
T(YAFFS_TRACE_ERROR,
(TSTR
- ("yaffs tragedy: attempting to use non-directory as"
- " a directory in scan. Put in lost+found."
+ ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
TENDSTR)));
parent = dev->lostNFoundDir;
}
@@ -6561,7 +6582,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
in->variant.hardLinkVariant.equivalentObjectId =
equivalentObjectId;
in->hardLinks.next =
- (struct list_head *) hardList;
+ (struct ylist_head *) hardList;
hardList = in;
}
break;
@@ -6621,27 +6642,27 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
* Sort out state of unlinked and deleted objects.
*/
{
- struct list_head *i;
- struct list_head *n;
+ struct ylist_head *i;
+ struct ylist_head *n;
yaffs_Object *l;
/* Soft delete all the unlinked files */
- list_for_each_safe(i, n,
+ ylist_for_each_safe(i, n,
&dev->unlinkedDir->variant.directoryVariant.
children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_DestroyObject(l);
}
}
/* Soft delete all the deletedDir files */
- list_for_each_safe(i, n,
+ ylist_for_each_safe(i, n,
&dev->deletedDir->variant.directoryVariant.
children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_DestroyObject(l);
}
@@ -6668,7 +6689,7 @@ static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
if(dev && dev->removeObjectCallback)
dev->removeObjectCallback(obj);
- list_del_init(&obj->siblings);
+ ylist_del_init(&obj->siblings);
obj->parent = NULL;
}
@@ -6694,14 +6715,14 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory,
if (obj->siblings.prev == NULL) {
/* Not initialised */
- INIT_LIST_HEAD(&obj->siblings);
+ YINIT_LIST_HEAD(&obj->siblings);
- } else if (!list_empty(&obj->siblings)) {
+ } else if (!ylist_empty(&obj->siblings)) {
/* If it is holed up somewhere else, un hook it */
yaffs_RemoveObjectFromDirectory(obj);
}
/* Now add it */
- list_add(&obj->siblings, &directory->variant.directoryVariant.children);
+ ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
obj->parent = directory;
if (directory == obj->myDev->unlinkedDir
@@ -6717,7 +6738,7 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
{
int sum;
- struct list_head *i;
+ struct ylist_head *i;
YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
yaffs_Object *l;
@@ -6742,9 +6763,9 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
sum = yaffs_CalcNameSum(name);
- list_for_each(i, &directory->variant.directoryVariant.children) {
+ ylist_for_each(i, &directory->variant.directoryVariant.children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_CheckObjectDetailsLoaded(l);
@@ -6776,7 +6797,7 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
int (*fn) (yaffs_Object *))
{
- struct list_head *i;
+ struct ylist_head *i;
yaffs_Object *l;
if (!theDir) {
@@ -6793,9 +6814,9 @@ int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
YBUG();
}
- list_for_each(i, &theDir->variant.directoryVariant.children) {
+ ylist_for_each(i, &theDir->variant.directoryVariant.children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
if (l && !fn(l)) {
return YAFFS_FAIL;
}
@@ -6884,12 +6905,12 @@ int yaffs_GetObjectFileLength(yaffs_Object * obj)
int yaffs_GetObjectLinkCount(yaffs_Object * obj)
{
int count = 0;
- struct list_head *i;
+ struct ylist_head *i;
if (!obj->unlinked) {
count++; /* the object itself */
}
- list_for_each(i, &obj->hardLinks) {
+ ylist_for_each(i, &obj->hardLinks) {
count++; /* add the hard links; */
}
return count;
@@ -7112,8 +7133,9 @@ int yaffs_GutsInitialise(yaffs_Device * dev)
/* Check geometry parameters. */
- if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
- (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
+ if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) ||
+ (!dev->isYaffs2 && dev->totalBytesPerChunk != 512) ||
+ (dev->inbandTags && !dev->isYaffs2 ) ||
dev->nChunksPerBlock < 2 ||
dev->nReservedBlocks < 2 ||
dev->internalStartBlock <= 0 ||
@@ -7122,8 +7144,8 @@ int yaffs_GutsInitialise(yaffs_Device * dev)
) {
T(YAFFS_TRACE_ALWAYS,
(TSTR
- ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
- TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
+ ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d "
+ TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));
return YAFFS_FAIL;
}
@@ -7132,6 +7154,12 @@ int yaffs_GutsInitialise(yaffs_Device * dev)
(TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
return YAFFS_FAIL;
}
+
+ /* Sort out space for inband tags, if required */
+ if(dev->inbandTags)
+ dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart);
+ else
+ dev->nDataBytesPerChunk = dev->totalBytesPerChunk;
/* Got the right mix of functions? */
if (!yaffs_CheckDevFunctions(dev)) {
@@ -7167,22 +7195,14 @@ int yaffs_GutsInitialise(yaffs_Device * dev)
/*
* Calculate all the chunk size manipulation numbers:
*/
- /* Start off assuming it is a power of 2 */
- dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
- dev->chunkMask = (1<<dev->chunkShift) - 1;
-
- if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
- /* Yes it is a power of 2, disable crumbs */
- dev->crumbMask = 0;
- dev->crumbShift = 0;
- dev->crumbsPerChunk = 0;
- } else {
- /* Not a power of 2, use crumbs instead */
- dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
- dev->crumbMask = (1<<dev->crumbShift)-1;
- dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
- dev->chunkShift = 0;
- dev->chunkMask = 0;
+ {
+ __u32 x = dev->nDataBytesPerChunk;
+ /* We always use dev->chunkShift and dev->chunkDiv */
+ dev->chunkShift = Shifts(x);
+ x >>= dev->chunkShift;
+ dev->chunkDiv = x;
+ /* We only use chunk mask if chunkDiv is 1 */
+ dev->chunkMask = (1<<dev->chunkShift) - 1;
}
@@ -7266,7 +7286,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev)
if (!init_failed &&
dev->nShortOpCaches > 0) {
int i;
- __u8 *buf;
+ void *buf;
int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
@@ -7282,7 +7302,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev)
dev->srCache[i].object = NULL;
dev->srCache[i].lastUse = 0;
dev->srCache[i].dirty = 0;
- dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
+ dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);
}
if(!buf)
init_failed = 1;
@@ -7408,6 +7428,7 @@ void yaffs_Deinitialise(yaffs_Device * dev)
YFREE(dev->tempBuffer[i].buffer);
}
+
dev->isMounted = 0;
}
@@ -7511,22 +7532,25 @@ static void yaffs_VerifyFreeChunks(yaffs_Device * dev)
/*---------------------------------------- YAFFS test code ----------------------*/
#define yaffs_CheckStruct(structure,syze, name) \
+ do { \
if(sizeof(structure) != syze) \
{ \
T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
name,syze,sizeof(structure))); \
return YAFFS_FAIL; \
- }
+ } \
+ } while(0)
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") */
+/* 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")
+ yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");
+#endif
+#ifndef CONFIG_YAFFS_WINCE
+ yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");
#endif
- yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
-
return YAFFS_OK;
}
diff --git a/yaffs_guts.h b/yaffs_guts.h
index cf89ef5..b9b2ea1 100644
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -90,7 +90,7 @@
#define YAFFS_MAX_SHORT_OP_CACHES 20
-#define YAFFS_N_TEMP_BUFFERS 4
+#define YAFFS_N_TEMP_BUFFERS 6
/* We limit the number attempts at sucessfully saving a chunk of data.
* Small-page devices have 32 pages per block; large-page devices have 64.
@@ -331,11 +331,14 @@ typedef struct {
__u32 win_ctime[2];
__u32 win_atime[2];
__u32 win_mtime[2];
- __u32 roomToGrow[4];
#else
- __u32 roomToGrow[10];
+ __u32 roomToGrow[6];
+
#endif
+ __u32 inbandShadowsObject;
+ __u32 inbandIsShrink;
+ __u32 reservedSpace[2];
int shadowsObject; /* This object header shadows the specified object if > 0 */
/* isShrink applies to object headers written when we shrink the file (ie resize) */
@@ -381,7 +384,7 @@ typedef struct {
} yaffs_FileStructure;
typedef struct {
- struct list_head children; /* list of child links */
+ struct ylist_head children; /* list of child links */
} yaffs_DirectoryStructure;
typedef struct {
@@ -424,14 +427,14 @@ struct yaffs_ObjectStruct {
struct yaffs_DeviceStruct *myDev; /* The device I'm on */
- struct list_head hashLink; /* list of objects in this hash bucket */
+ struct ylist_head hashLink; /* list of objects in this hash bucket */
- struct list_head hardLinks; /* all the equivalent hard linked objects */
+ struct ylist_head hardLinks; /* all the equivalent hard linked objects */
/* directory structure stuff */
/* also used for linking up the free list */
struct yaffs_ObjectStruct *parent;
- struct list_head siblings;
+ struct ylist_head siblings;
/* Where's my object header in NAND? */
int chunkId;
@@ -485,7 +488,7 @@ struct yaffs_ObjectList_struct {
typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
typedef struct {
- struct list_head list;
+ struct ylist_head list;
int count;
} yaffs_ObjectBucket;
@@ -528,7 +531,7 @@ typedef struct {
/*----------------- Device ---------------------------------*/
struct yaffs_DeviceStruct {
- struct list_head devList;
+ struct ylist_head devList;
const char *name;
/* Entry parameters set up way early. Yaffs sets up the rest.*/
@@ -583,7 +586,7 @@ struct yaffs_DeviceStruct {
yaffs_ExtendedTags * tags);
int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
- yaffs_BlockState * state, int *sequenceNumber);
+ yaffs_BlockState * state, __u32 *sequenceNumber);
#endif
int isYaffs2;
@@ -598,7 +601,8 @@ struct yaffs_DeviceStruct {
void (*markSuperBlockDirty)(void * superblock);
int wideTnodesDisabled; /* Set to disable wide tnodes */
-
+
+ YCHAR *pathDividers; /* String of legal path dividers */
/* End of stuff that must be set before initialisation. */
@@ -615,16 +619,14 @@ struct yaffs_DeviceStruct {
__u32 tnodeWidth;
__u32 tnodeMask;
- /* Stuff to support various file offses to chunk/offset translations */
- /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
- __u32 crumbMask;
- __u32 crumbShift;
- __u32 crumbsPerChunk;
-
- /* Straight shifting for nDataBytesPerChunk being a power of 2 */
- __u32 chunkShift;
- __u32 chunkMask;
+ /* Stuff for figuring out file offset to chunk conversions */
+ __u32 chunkShift; /* Shift value */
+ __u32 chunkDiv; /* Divisor after shifting: 1 for power-of-2 sizes */
+ __u32 chunkMask; /* Mask to use for power-of-2 case */
+ /* Stuff to handle inband tags */
+ int inbandTags;
+ __u32 totalBytesPerChunk;
#ifdef __KERNEL__
@@ -746,9 +748,11 @@ struct yaffs_DeviceStruct {
int nUnlinkedFiles; /* Count of unlinked files. */
int nBackgroundDeletions; /* Count of background deletions. */
-
+
+ /* Temporary buffer management */
yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
int maxTemp;
+ int tempInUse;
int unmanagedTempAllocations;
int unmanagedTempDeallocations;
@@ -799,18 +803,6 @@ typedef struct {
__u32 head;
} yaffs_CheckpointValidity;
-/* Function to manipulate block info */
-static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
-{
- if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
- T(YAFFS_TRACE_ERROR,
- (TSTR
- ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
- blk));
- YBUG();
- }
- return &dev->blockInfo[blk - dev->internalStartBlock];
-}
/*----------------------- YAFFS Functions -----------------------*/
@@ -901,4 +893,7 @@ void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn);
int yaffs_CheckFF(__u8 * buffer, int nBytes);
void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
+__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
+void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo);
+
#endif
diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c
index 125ed40..3768b9b 100644
--- a/yaffs_mtdif2.c
+++ b/yaffs_mtdif2.c
@@ -14,7 +14,7 @@
/* mtd interface for YAFFS2 */
const char *yaffs_mtdif2_c_version =
- "$Id: yaffs_mtdif2.c,v 1.19 2007-12-13 15:35:18 wookey Exp $";
+ "$Id: yaffs_mtdif2.c,v 1.20 2008-05-05 07:58:58 charles Exp $";
#include "yportenv.h"
@@ -27,6 +27,10 @@ const char *yaffs_mtdif2_c_version =
#include "yaffs_packedtags2.h"
+/* NB For use with inband tags....
+ * We assume that the data buffer is of size totalBytersPerChunk so that we can also
+ * use it to load the tags.
+ */
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
const __u8 * data,
const yaffs_ExtendedTags * tags)
@@ -39,7 +43,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
#endif
int retval = 0;
- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+ loff_t addr;
yaffs_PackedTags2 pt;
@@ -47,47 +51,42 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
(TSTR
("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
-
-#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
- if (tags)
- yaffs_PackTags2(&pt, tags);
+
+
+ addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
+
+ /* For yaffs2 writing there must be both data and tags.
+ * If we're using inband tags, then the tags are stuffed into
+ * the end of the data buffer.
+ */
+ if(!data || !tags)
+ BUG();
+ else if(dev->inbandTags){
+ yaffs_PackedTags2TagsPart *pt2tp;
+ pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
+ yaffs_PackTags2TagsPart(pt2tp,tags);
+ }
else
- BUG(); /* both tags and data should always be present */
-
- if (data) {
- ops.mode = MTD_OOB_AUTO;
- ops.ooblen = sizeof(pt);
- ops.len = dev->nDataBytesPerChunk;
- ops.ooboffs = 0;
- ops.datbuf = (__u8 *)data;
- ops.oobbuf = (void *)&pt;
- retval = mtd->write_oob(mtd, addr, &ops);
- } else
- BUG(); /* both tags and data should always be present */
-#else
- if (tags) {
yaffs_PackTags2(&pt, tags);
- }
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
+ ops.len = dev->totalBytesPerChunk;
+ ops.ooboffs = 0;
+ ops.datbuf = (__u8 *)data;
+ ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
+ retval = mtd->write_oob(mtd, addr, &ops);
- if (data && tags) {
- if (dev->useNANDECC)
- retval =
- mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
- &dummy, data, (__u8 *) & pt, NULL);
- else
- retval =
- mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
- &dummy, data, (__u8 *) & pt, NULL);
+#else
+ if (!dev->inbandTags) {
+ retval =
+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, (__u8 *) & pt, NULL);
} else {
- if (data)
- retval =
- mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
- data);
- if (tags)
- retval =
- mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
- (__u8 *) & pt);
-
+ retval =
+ mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
+ data);
}
#endif
@@ -106,6 +105,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
#endif
size_t dummy;
int retval = 0;
+ int localData = 0;
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
@@ -115,10 +115,21 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
(TSTR
("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
+
+ if(dev->inbandTags){
+
+ if(!data) {
+ localData = 1;
+ data = yaffs_GetTempBuffer(dev,__LINE__);
+ }
+
-#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
- if (data && !tags)
- retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
+ }
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ if (dev->inbandTags || (data && !tags))
+ retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
&dummy, data);
else if (tags) {
ops.mode = MTD_OOB_AUTO;
@@ -130,38 +141,43 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
retval = mtd->read_oob(mtd, addr, &ops);
}
#else
- if (data && tags) {
- if (dev->useNANDECC) {
- retval =
- mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
- &dummy, data, dev->spareBuffer,
- NULL);
- } else {
- retval =
- mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ if (!dev->inbandTags && data && tags) {
+
+ retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, dev->spareBuffer,
NULL);
- }
} else {
if (data)
retval =
mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
data);
- if (tags)
+ if (!dev->inbandTags && tags)
retval =
mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
dev->spareBuffer);
}
#endif
- memcpy(&pt, dev->spareBuffer, sizeof(pt));
- if (tags)
- yaffs_UnpackTags2(tags, &pt);
+ if(dev->inbandTags){
+ if(tags){
+ yaffs_PackedTags2TagsPart * pt2tp;
+ pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
+ yaffs_UnpackTags2TagsPart(tags,pt2tp);
+ }
+ }
+ else {
+ if (tags){
+ memcpy(&pt, dev->spareBuffer, sizeof(pt));
+ yaffs_UnpackTags2(tags, &pt);
+ }
+ }
+ if(localData)
+ yaffs_ReleaseTempBuffer(dev,data,__LINE__);
+
if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
- tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
-
+ tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
if (retval == 0)
return YAFFS_OK;
else
diff --git a/yaffs_nand.c b/yaffs_nand.c
index 3898985..af42157 100644
--- a/yaffs_nand.c
+++ b/yaffs_nand.c
@@ -12,12 +12,13 @@
*/
const char *yaffs_nand_c_version =
- "$Id: yaffs_nand.c,v 1.8 2007-12-13 15:35:18 wookey Exp $";
+ "$Id: yaffs_nand.c,v 1.9 2008-05-05 07:58:58 charles Exp $";
#include "yaffs_nand.h"
#include "yaffs_tagscompat.h"
#include "yaffs_tagsvalidity.h"
+#include "yaffs_getblockinfo.h"
int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
__u8 * buffer,
@@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)
int yaffs_QueryInitialBlockState(yaffs_Device * dev,
int blockNo,
yaffs_BlockState * state,
- unsigned *sequenceNumber)
+ __u32 *sequenceNumber)
{
blockNo -= dev->blockOffset;
diff --git a/yaffs_nandemul2k.h b/yaffs_nandemul2k.h
index cd2e96f..c8576b3 100644
--- a/yaffs_nandemul2k.h
+++ b/yaffs_nandemul2k.h
@@ -22,13 +22,13 @@
int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
int chunkInNAND, const __u8 * data,
- yaffs_ExtendedTags * tags);
+ const yaffs_ExtendedTags * tags);
int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
int chunkInNAND, __u8 * data,
yaffs_ExtendedTags * tags);
int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
- yaffs_BlockState * state, int *sequenceNumber);
+ yaffs_BlockState * state, __u32 *sequenceNumber);
int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
int blockInNAND);
int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);
diff --git a/yaffs_packedtags2.c b/yaffs_packedtags2.c
index e420f95..957ed8b 100644
--- a/yaffs_packedtags2.c
+++ b/yaffs_packedtags2.c
@@ -37,60 +37,70 @@
#define EXTRA_OBJECT_TYPE_SHIFT (28)
#define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
-static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
+
+static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt)
{
T(YAFFS_TRACE_MTD,
(TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
- pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
- pt->t.sequenceNumber));
+ ptt->objectId, ptt->chunkId, ptt->byteCount,
+ ptt->sequenceNumber));
+}
+static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
+{
+ yaffs_DumpPackedTags2TagsPart(&pt->t);
}
static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
{
T(YAFFS_TRACE_MTD,
(TSTR
- ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
- "%d del %d ser %d seq %d"
+ ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
t->sequenceNumber));
}
-void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
+void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t)
{
- pt->t.chunkId = t->chunkId;
- pt->t.sequenceNumber = t->sequenceNumber;
- pt->t.byteCount = t->byteCount;
- pt->t.objectId = t->objectId;
+ ptt->chunkId = t->chunkId;
+ ptt->sequenceNumber = t->sequenceNumber;
+ ptt->byteCount = t->byteCount;
+ ptt->objectId = t->objectId;
if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
/* Store the extra header info instead */
/* We save the parent object in the chunkId */
- pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
+ ptt->chunkId = EXTRA_HEADER_INFO_FLAG
| t->extraParentObjectId;
if (t->extraIsShrinkHeader) {
- pt->t.chunkId |= EXTRA_SHRINK_FLAG;
+ ptt->chunkId |= EXTRA_SHRINK_FLAG;
}
if (t->extraShadows) {
- pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
+ ptt->chunkId |= EXTRA_SHADOWS_FLAG;
}
- pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
- pt->t.objectId |=
+ ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+ ptt->objectId |=
(t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
- pt->t.byteCount = t->extraEquivalentObjectId;
+ ptt->byteCount = t->extraEquivalentObjectId;
} else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
- pt->t.byteCount = t->extraFileLength;
+ ptt->byteCount = t->extraFileLength;
} else {
- pt->t.byteCount = 0;
+ ptt->byteCount = 0;
}
}
- yaffs_DumpPackedTags2(pt);
+ yaffs_DumpPackedTags2TagsPart(ptt);
yaffs_DumpTags2(t);
+}
+
+
+void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
+{
+ yaffs_PackTags2TagsPart(&pt->t,t);
#ifndef YAFFS_IGNORE_TAGS_ECC
{
@@ -101,13 +111,60 @@ void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
#endif
}
-void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
+
+void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt)
{
memset(t, 0, sizeof(yaffs_ExtendedTags));
yaffs_InitialiseTags(t);
+ if (ptt->sequenceNumber != 0xFFFFFFFF) {
+ t->blockBad = 0;
+ t->chunkUsed = 1;
+ t->objectId = ptt->objectId;
+ t->chunkId = ptt->chunkId;
+ t->byteCount = ptt->byteCount;
+ t->chunkDeleted = 0;
+ t->serialNumber = 0;
+ t->sequenceNumber = ptt->sequenceNumber;
+
+ /* Do extra header info stuff */
+
+ if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
+ t->chunkId = 0;
+ t->byteCount = 0;
+
+ t->extraHeaderInfoAvailable = 1;
+ t->extraParentObjectId =
+ ptt->chunkId & (~(ALL_EXTRA_FLAGS));
+ t->extraIsShrinkHeader =
+ (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
+ t->extraShadows =
+ (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
+ t->extraObjectType =
+ ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
+ t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+
+ if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
+ t->extraEquivalentObjectId = ptt->byteCount;
+ } else {
+ t->extraFileLength = ptt->byteCount;
+ }
+ }
+ }
+
+ yaffs_DumpPackedTags2TagsPart(ptt);
+ yaffs_DumpTags2(t);
+
+}
+
+
+void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
+{
+
+ yaffs_UnpackTags2TagsPart(t,&pt->t);
+
if (pt->t.sequenceNumber != 0xFFFFFFFF) {
/* Page is in use */
#ifdef YAFFS_IGNORE_TAGS_ECC
@@ -142,41 +199,10 @@ void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
}
}
#endif
- t->blockBad = 0;
- t->chunkUsed = 1;
- t->objectId = pt->t.objectId;
- t->chunkId = pt->t.chunkId;
- t->byteCount = pt->t.byteCount;
- t->chunkDeleted = 0;
- t->serialNumber = 0;
- t->sequenceNumber = pt->t.sequenceNumber;
-
- /* Do extra header info stuff */
-
- if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
- t->chunkId = 0;
- t->byteCount = 0;
-
- t->extraHeaderInfoAvailable = 1;
- t->extraParentObjectId =
- pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
- t->extraIsShrinkHeader =
- (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
- t->extraShadows =
- (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
- t->extraObjectType =
- pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
- t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
-
- if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
- t->extraEquivalentObjectId = pt->t.byteCount;
- } else {
- t->extraFileLength = pt->t.byteCount;
- }
- }
}
yaffs_DumpPackedTags2(pt);
yaffs_DumpTags2(t);
}
+
diff --git a/yaffs_packedtags2.h b/yaffs_packedtags2.h
index c2242ff..75761d3 100644
--- a/yaffs_packedtags2.h
+++ b/yaffs_packedtags2.h
@@ -33,6 +33,11 @@ typedef struct {
yaffs_ECCOther ecc;
} yaffs_PackedTags2;
+/* Full packed tags with ECC, used for oob tags */
void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
+
+/* Only the tags part (no ECC for use with inband tags */
+void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * pt, const yaffs_ExtendedTags * t);
+void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * pt);
#endif
diff --git a/yaffs_tagscompat.c b/yaffs_tagscompat.c
index 7622b1a..ab756d0 100644
--- a/yaffs_tagscompat.c
+++ b/yaffs_tagscompat.c
@@ -14,6 +14,7 @@
#include "yaffs_guts.h"
#include "yaffs_tagscompat.h"
#include "yaffs_ecc.h"
+#include "yaffs_getblockinfo.h"
static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
#ifdef NOTYET
@@ -438,7 +439,7 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
yaffs_ECCResult eccResult;
static yaffs_Spare spareFF;
- static int init;
+ static int init = 0;
if (!init) {
memset(&spareFF, 0xFF, sizeof(spareFF));
@@ -497,9 +498,9 @@ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
}
int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
- int blockNo, yaffs_BlockState *
- state,
- int *sequenceNumber)
+ int blockNo,
+ yaffs_BlockState *state,
+ __u32 *sequenceNumber)
{
yaffs_Spare spare0, spare1;
diff --git a/yaffs_tagscompat.h b/yaffs_tagscompat.h
index a61e3ba..6549398 100644
--- a/yaffs_tagscompat.h
+++ b/yaffs_tagscompat.h
@@ -30,8 +30,9 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
int blockNo);
int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
- int blockNo, yaffs_BlockState *
- state, int *sequenceNumber);
+ int blockNo,
+ yaffs_BlockState *state,
+ __u32 *sequenceNumber);
void yaffs_CalcTagsECC(yaffs_Tags * tags);
int yaffs_CheckECCOnTags(yaffs_Tags * tags);
diff --git a/yportenv.h b/yportenv.h
index 6cd90da..097b2a6 100644
--- a/yportenv.h
+++ b/yportenv.h
@@ -193,8 +193,8 @@ extern unsigned int yaffs_wr_attempts;
#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
-#ifndef CONFIG_YAFFS_WINCE
-#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
+#ifndef YBUG
+#define YBUG() do {T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__));} while(0)
#endif
#endif