This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
fatfs patch
- From: Savin Zlobec <savin at elatec dot si>
- To: ecos-discuss at sources dot redhat dot com
- Date: Mon, 05 Jul 2004 10:22:17 +0200
- Subject: [ECOS] fatfs patch
Hi,
this patch removes kernel dependencies from fatfs and improves
performance with big files quite a bit. It was not thoroughly tested
and should not go into the CVS right away. I post it here because
there were some requests for this features on the lists.
savin
Index: fs/fat/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/fat/current/ChangeLog,v
retrieving revision 1.1
diff -u -5 -r1.1 ChangeLog
--- fs/fat/current/ChangeLog 19 Jan 2004 14:35:02 -0000 1.1
+++ fs/fat/current/ChangeLog 5 Jul 2004 07:51:32 -0000
@@ -1,5 +1,25 @@
+2003-07-05 Savin Zlobec <savin@elatec.si>
+
+ * cdl/fatfs.cdl:
+ * src/fatfs.h:
+ * src/fatfs.c:
+ * src/fatfs_supp.c:
+ * src/fatfs_ncache.c:
+ Removed FAT table cache - it added little or no speed gain to
+ the fatfs. Implemented private data for fatfs file descriptors which
+ holds the current FAT cluster position, this greatly improves
+ read/write times for big files comparing to the old implementation.
+ * src/fatfs_tcache.c: Removed.
+
+2003-06-24 Savin Zlobec <savin@elatec.si>
+
+ * src/fatfs.h:
+ * src/fatfs_supp.c:
+ Implemented fatfs_get_disk_usage function for
+ getting the number of total and free clusters.
+
2004-01-19 Nick Garnett <nickg@calivar.com>
* doc/README.txt:
* doc/fatfs.ecm:
Index: fs/fat/current/cdl/fatfs.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/fat/current/cdl/fatfs.cdl,v
retrieving revision 1.1
diff -u -5 -r1.1 fatfs.cdl
--- fs/fat/current/cdl/fatfs.cdl 19 Jan 2004 14:35:02 -0000 1.1
+++ fs/fat/current/cdl/fatfs.cdl 5 Jul 2004 07:51:32 -0000
@@ -61,12 +61,11 @@
implements CYGINT_IO_FILEIO_FS
compile -library=libextras.a fatfs.c \
fatfs_supp.c \
- fatfs_ncache.c \
- fatfs_tcache.c
+ fatfs_ncache.c
cdl_option CYGNUM_FS_FAT_NODE_HASH_TABLE_SIZE {
display "Node hash table size"
flavor data
default_value 32
@@ -84,28 +83,10 @@
description "This option controls at which point the filesystem
starts reusing dead file nodes rather then allocating
memory for new nodes."
}
- cdl_option CYGNUM_FS_FAT_FAT_TABLE_CACHE_MEMSIZE {
- display "FAT table cache memory size"
- flavor data
- default_value 10240
- legal_values 1 to 9999999999
- description "This option controls the amount of memory used
- for the FAT table cache."
- }
-
- cdl_option CYGNUM_FS_FAT_FAT_TABLE_CACHE_INCREMENT {
- display "FAT table cache size increment"
- flavor data
- default_value 10
- legal_values 1 to 9999999999
- description "This option controls the amount of memory by which
- the per-file FAT table cache will grow."
- }
-
cdl_option CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE {
display "FAT block cache memory size"
flavor data
default_value 10240
legal_values 1 to 9999999999
Index: fs/fat/current/src/fatfs.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/fat/current/src/fatfs.c,v
retrieving revision 1.1
diff -u -5 -r1.1 fatfs.c
--- fs/fat/current/src/fatfs.c 19 Jan 2004 14:35:02 -0000 1.1
+++ fs/fat/current/src/fatfs.c 5 Jul 2004 07:51:33 -0000
@@ -51,15 +51,14 @@
//
//==========================================================================
#include <pkgconf/system.h>
#include <pkgconf/hal.h>
-#include <pkgconf/kernel.h>
#include <pkgconf/io_fileio.h>
#include <pkgconf/fs_fat.h>
-#include <cyg/kernel/ktypes.h> // base kernel types
+#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <unistd.h>
#include <sys/types.h>
@@ -69,11 +68,10 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <cyg/kernel/kapi.h>
#include <cyg/infra/diag.h>
#include <cyg/fileio/fileio.h>
#include <cyg/io/io.h>
#include <blib/blib.h>
@@ -210,10 +208,23 @@
cyg_bool last; // Last name in path?
};
typedef struct fatfs_dirsearch_t fatfs_dirsearch_t;
+// -------------------------------------------------------------------------
+// FATFS file descriptor data
+
+typedef struct fatfs_fd_s
+{
+ fatfs_node_t *node;
+ fatfs_data_pos_t pos;
+} fatfs_fd_t;
+
+static fatfs_fd_t fatfs_fds_base[CYGNUM_FILEIO_NFD];
+static fatfs_fd_t *fatfs_fds_pool[CYGNUM_FILEIO_NFD];
+static cyg_uint32 fatfs_fds_free_cnt;
+
//==========================================================================
#if TFS
static void
print_disk_info(fatfs_disk_t *disk)
@@ -230,10 +241,50 @@
diag_printf("FAT: FAT data position: %u\n", disk->fat_data_pos);
}
#endif
static void
+init_fatfs_fds(void)
+{
+ static bool initialized = false;
+ int i;
+
+ if (initialized)
+ return;
+
+ initialized = true;
+
+ for (i = 0; i < CYGNUM_FILEIO_NFD; i++)
+ {
+ fatfs_fds_pool[i] = &fatfs_fds_base[i];
+ }
+ fatfs_fds_free_cnt = i;
+}
+
+static fatfs_fd_t *
+alloc_fatfs_fd(fatfs_disk_t *disk, fatfs_node_t *node)
+{
+ fatfs_fd_t *fd = NULL;
+
+ if (fatfs_fds_free_cnt > 0)
+ {
+ fd = fatfs_fds_pool[--fatfs_fds_free_cnt];
+
+ fd->node = node;
+ fatfs_initpos(disk, node, &fd->pos);
+ }
+
+ return fd;
+}
+
+static void
+free_fatfs_fd(fatfs_fd_t *fd)
+{
+ fatfs_fds_pool[fatfs_fds_free_cnt++] = fd;
+}
+
+static void
init_dirsearch(fatfs_dirsearch_t *ds,
fatfs_disk_t *disk,
fatfs_node_t *dir,
const char *name)
{
@@ -249,13 +300,13 @@
}
static int
find_direntry(fatfs_dirsearch_t *ds)
{
+ fatfs_node_t node_data;
+ fatfs_data_pos_t pos;
int err;
- cyg_uint32 pos = 0;
- fatfs_node_t node_data;
CYG_TRACE1(TFS, "Finding dir entry '%s'", ds->name);
ds->node = fatfs_node_find(ds->disk, ds->name,
ds->namelen, ds->dir->cluster);
@@ -264,11 +315,13 @@
{
CYG_TRACE1(TFS, "Found dir entry '%s' in cache", ds->name);
fatfs_node_touch(ds->disk, ds->node);
return ENOERR;
}
-
+
+ fatfs_initpos(ds->disk, ds->dir, &pos);
+
while (true)
{
err = fatfs_get_dir_entry_node(ds->disk, ds->dir, &pos, &node_data);
if (err != ENOERR)
return (err == EEOF ? ENOERR : err);
@@ -282,11 +335,10 @@
ds->node = fatfs_node_alloc(ds->disk, &node_data);
if (NULL == ds->node)
return ENOMEM;
return ENOERR;
}
- pos++;
}
}
static int
find_entry(fatfs_dirsearch_t *ds)
@@ -379,10 +431,12 @@
Cyg_ErrNo err;
fatfs_disk_t *disk;
fatfs_node_t root_data;
CYG_TRACE2(TFS, "Mount fste=%p mte=%p", fste, mte);
+
+ init_fatfs_fds();
CYG_TRACE1(TFS, "Looking up disk device '%s'", mte->devname);
err = cyg_io_lookup(mte->devname, &dev_h);
if (err != ENOERR)
@@ -390,34 +444,23 @@
disk = (fatfs_disk_t *)malloc(sizeof(fatfs_disk_t));
if (NULL == disk)
return ENOMEM;
- CYG_TRACE0(TFS, "Initializing FAT table cache");
-
- if (ENOERR != fatfs_tcache_create(disk,
- CYGNUM_FS_FAT_FAT_TABLE_CACHE_MEMSIZE))
- {
- free(disk);
- return ENOMEM;
- }
-
CYG_TRACE0(TFS, "Initializing block cache");
disk->bcache_mem = (cyg_uint8 *)malloc(CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE);
if (NULL == disk->bcache_mem)
{
- fatfs_tcache_delete(disk);
free(disk);
return ENOMEM;
}
// FIXME: get block size from disk device
err = cyg_blib_io_create(dev_h, disk->bcache_mem,
CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE, 512, &disk->blib);
if (err != ENOERR)
{
- fatfs_tcache_delete(disk);
free(disk->bcache_mem);
free(disk);
return err;
}
@@ -426,11 +469,10 @@
CYG_TRACE0(TFS, "Initializing disk");
err = fatfs_get_disk_info(disk);
if (err != ENOERR)
{
- fatfs_tcache_delete(disk);
cyg_blib_delete(&disk->blib);
free(disk->bcache_mem);
free(disk);
return err;
}
@@ -478,11 +520,10 @@
if (fatfs_get_live_node_count(disk) != 1)
return EBUSY;
fatfs_node_unref(disk, root);
fatfs_node_cache_flush(disk);
- fatfs_tcache_delete(disk);
// FIXME: cache delete can fail if cache can't be synced
cyg_blib_delete(&disk->blib);
free(disk->bcache_mem);
free(disk);
@@ -503,13 +544,14 @@
cyg_dir dir,
const char *name,
int mode,
cyg_file *file)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
- fatfs_node_t *node = NULL;
- fatfs_dirsearch_t ds;
+ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
+ fatfs_node_t *node = NULL;
+ fatfs_fd_t *fd;
+ fatfs_dirsearch_t ds;
int err;
CYG_TRACE5(TFS, "Open mte=%p dir=%p name='%s' mode=%d file=%p",
mte, dir, name, mode, file);
@@ -568,20 +610,27 @@
// Check that we actually have a file here
if (S_ISDIR(node->mode))
return EISDIR;
+ fd = alloc_fatfs_fd(disk, node);
+ if (NULL == fd)
+ return EMFILE;
+
// Make a reference to this file node
fatfs_node_ref(disk, node);
// Initialize the file object
+ if (mode & O_APPEND)
+ fatfs_setpos(disk, node, &fd->pos, node->size);
+
file->f_flag |= mode & CYG_FILE_MODE_MASK;
file->f_type = CYG_FILE_TYPE_FILE;
file->f_ops = &fatfs_fileops;
file->f_offset = (mode & O_APPEND) ? node->size : 0;
- file->f_data = (CYG_ADDRWORD)node;
+ file->f_data = (CYG_ADDRWORD)fd;
file->f_xops = 0;
return ENOERR;
}
@@ -592,12 +641,12 @@
static int
fatfs_unlink(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
- fatfs_dirsearch_t ds;
+ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
+ fatfs_dirsearch_t ds;
int err;
CYG_TRACE3(TFS, "Unlink mte=%p dir=%p name='%s'", mte, dir, name);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
@@ -623,12 +672,12 @@
// Create a new directory.
static int
fatfs_mkdir(cyg_mtab_entry *mte, cyg_dir dir, const char *name)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
- fatfs_dirsearch_t ds;
+ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
+ fatfs_dirsearch_t ds;
int err;
CYG_TRACE3(TFS, "Mkdir mte=%p dir=%p name='%s'", mte, dir, name);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
@@ -667,12 +716,12 @@
// Remove a directory.
static int
fatfs_rmdir(cyg_mtab_entry *mte, cyg_dir dir, const char *name)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
- fatfs_dirsearch_t ds;
+ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
+ fatfs_dirsearch_t ds;
int err;
CYG_TRACE3(TFS, "Rmdir mte=%p dir=%p name='%s'", mte, dir, name);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
@@ -705,12 +754,12 @@
cyg_dir dir1,
const char *name1,
cyg_dir dir2,
const char *name2)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
- fatfs_dirsearch_t ds1, ds2;
+ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
+ fatfs_dirsearch_t ds1, ds2;
int err;
CYG_TRACE5(TFS, "Rename mte=%p dir1=%p name1='%s' dir2=%p name2='%s'",
mte, dir1, name1, dir2, name2);
@@ -789,12 +838,13 @@
fatfs_opendir(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
cyg_file *file)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
- fatfs_dirsearch_t ds;
+ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
+ fatfs_fd_t *fd;
+ fatfs_dirsearch_t ds;
int err;
CYG_TRACE4(TFS, "Opendir mte=%p dir=%p name='%s' file=%p",
mte, dir, name, file);
@@ -807,17 +857,22 @@
// Check it is really a directory.
if (!S_ISDIR(ds.node->mode))
return ENOTDIR;
+ fd = alloc_fatfs_fd(disk, ds.node);
+ if (NULL == fd)
+ return EMFILE;
+
// Make a reference to this dir node
fatfs_node_ref(disk, ds.node);
// Initialize the file object
+
file->f_type = CYG_FILE_TYPE_FILE;
file->f_ops = &fatfs_dirops;
- file->f_data = (CYG_ADDRWORD)ds.node;
+ file->f_data = (CYG_ADDRWORD)fd;
file->f_xops = 0;
file->f_offset = 0;
return ENOERR;
}
@@ -883,12 +938,12 @@
fatfs_stat(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
struct stat *buf)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
- fatfs_dirsearch_t ds;
+ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
+ fatfs_dirsearch_t ds;
int err;
CYG_TRACE4(TFS, "Stat mte=%p dir=%p name='%s' buf=%p",
mte, dir, name, buf);
@@ -956,14 +1011,15 @@
// Read data from the file.
static int
fatfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
- fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
- cyg_uint32 pos = fp->f_offset;
- ssize_t resid = uio->uio_resid;
+ fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ fatfs_node_t *node = fd->node;
+ cyg_uint32 pos = fp->f_offset;
+ ssize_t resid = uio->uio_resid;
int i;
CYG_TRACE3(TFO, "Read fp=%p uio=%p pos=%d", fp, uio, pos);
// Loop over the io vectors until there are none left
@@ -982,11 +1038,11 @@
// Adjust size to end of file if necessary
if (l > node->size-pos)
l = node->size-pos;
// Read data
- err = fatfs_read_data(disk, node, buf, &l, pos);
+ err = fatfs_read_data(disk, node, &fd->pos, buf, &l);
if (err != ENOERR)
return err;
// Update working vars
@@ -1012,23 +1068,27 @@
static int
fatfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
- fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ fatfs_node_t *node = fd->node;
cyg_uint32 pos = fp->f_offset;
ssize_t resid = uio->uio_resid;
int err = ENOERR;
int i;
CYG_TRACE3(TFO, "Write fp=%p uio=%p pos=%d", fp, uio, pos);
// If the APPEND mode bit was supplied, force all writes to
// the end of the file.
if (fp->f_flag & CYG_FAPPEND)
+ {
+ fatfs_setpos(disk, node, &fd->pos, node->size);
pos = fp->f_offset = node->size;
-
+ }
+
// Check that pos is within current file size, or at the very end.
if (pos < 0 || pos > node->size)
return EINVAL;
// Now loop over the iovecs until they are all done, or
@@ -1044,11 +1104,11 @@
while (len > 0)
{
cyg_uint32 l = len;
// Write data
- err = fatfs_write_data(disk, node, buf, &l, pos);
+ err = fatfs_write_data(disk, node, &fd->pos, buf, &l);
// Update working vars
len -= l;
buf += l;
pos += l;
@@ -1083,13 +1143,15 @@
// Seek to a new file position.
static int
fatfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
{
- fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
- off_t pos = *apos;
-
+ fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ off_t pos = *apos;
+ int err;
+
CYG_TRACE3(TFO, "Lseek fp=%p pos=%d whence=%d", fp, fp->f_offset, whence);
switch (whence)
{
case SEEK_SET:
@@ -1099,27 +1161,30 @@
// Add pos to current offset.
pos += fp->f_offset;
break;
case SEEK_END:
// Add pos to file size.
- pos += node->size;
+ pos += fd->node->size;
break;
default:
return EINVAL;
}
// Check that pos is still within current file size, or at the
// very end.
- if (pos < 0 || pos > node->size)
+ if (pos < 0 || pos > fd->node->size)
return EINVAL;
// All OK, set fp offset and return new position.
- *apos = fp->f_offset = pos;
-
+
+ err = fatfs_setpos(disk, fd->node, &fd->pos, pos);
+ if (ENOERR == err)
+ *apos = fp->f_offset = pos;
+
CYG_TRACE2(TFO, "Lseek fp=%p new pos=%d", fp, *apos);
- return ENOERR;
+ return err;
}
// -------------------------------------------------------------------------
// fatfs_fo_ioctl()
// Handle ioctls. Currently none are defined.
@@ -1137,11 +1202,12 @@
static int
fatfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
- fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ fatfs_node_t *node = fd->node;
int err;
CYG_TRACE2(TFO, "Fsync fp=%p mode=%d", fp, mode);
err = fatfs_write_file_attr(disk, node);
@@ -1156,30 +1222,34 @@
static int
fatfs_fo_close(struct CYG_FILE_TAG *fp)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
- fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ fatfs_node_t *node = fd->node;
int err = ENOERR;
CYG_TRACE1(TFO, "Close fp=%p", fp);
if (node != disk->root)
err = fatfs_write_file_attr(disk, node);
fatfs_node_unref(disk, node);
+ free_fatfs_fd(fd);
+
return err;
}
// -------------------------------------------------------------------------
// fatfs_fo_fstat()
// Get file status.
static int
fatfs_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf)
{
- fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ fatfs_node_t *node = fd->node;
CYG_TRACE2(TFO, "Fstat fp=%p buf=%p", fp, buf);
// Fill in the status
buf->st_mode = node->mode;
@@ -1226,34 +1296,33 @@
// Read a single directory entry from a file.
static int
fatfs_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
- fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
- fatfs_node_t *dir = (fatfs_node_t *)fp->f_data;
- struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
- cyg_uint32 pos = fp->f_offset;
- char *nbuf = ent->d_name;
- off_t len = uio->uio_iov[0].iov_len;
- fatfs_node_t node;
+ fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
+ char *nbuf = ent->d_name;
+ off_t len = uio->uio_iov[0].iov_len;
+ fatfs_node_t node;
int err;
CYG_TRACE3(TFO, "Dirread fp=%p uio=%p pos=%d", fp, uio, pos);
if (len < sizeof(struct dirent))
return EINVAL;
- err = fatfs_get_dir_entry_node(disk, dir, &pos, &node);
+ err = fatfs_get_dir_entry_node(disk, fd->node, &fd->pos, &node);
if (err != ENOERR)
return (err == EEOF ? ENOERR : err);
strcpy(nbuf, node.filename);
- dir->atime = cyg_timestamp();
+ fd->node->atime = cyg_timestamp();
uio->uio_resid -= sizeof(struct dirent);
- fp->f_offset = (off_t)(pos + 1);
+ fp->f_offset++;
return ENOERR;
}
// -------------------------------------------------------------------------
@@ -1261,18 +1330,25 @@
// Seek directory to start.
static int
fatfs_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence)
{
+ fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
+ fatfs_fd_t *fd = (fatfs_fd_t *)fp->f_data;
+ int err;
+
CYG_TRACE2(TFO, "Dirlseek fp=%p whence=%d", fp, whence);
// Only allow SEEK_SET to zero
if (whence != SEEK_SET || *pos != 0)
return EINVAL;
+
+ err = fatfs_setpos(disk, fd->node, &fd->pos, 0);
+ if (ENOERR == err)
+ *pos = fp->f_offset = 0;
- *pos = fp->f_offset = 0;
- return ENOERR;
+ return err;
}
// -------------------------------------------------------------------------
// EOF fatfs.c
Index: fs/fat/current/src/fatfs.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/fat/current/src/fatfs.h,v
retrieving revision 1.1
diff -u -5 -r1.1 fatfs.h
--- fs/fat/current/src/fatfs.h 19 Jan 2004 14:35:02 -0000 1.1
+++ fs/fat/current/src/fatfs.h 5 Jul 2004 07:51:34 -0000
@@ -46,11 +46,10 @@
//####DESCRIPTIONEND####
//
//==========================================================================
#include <pkgconf/fs_fat.h>
-#include <cyg/kernel/kapi.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/io/io.h>
#include <blib/blib.h>
#include <unistd.h>
@@ -69,24 +68,19 @@
#define FATFS_HASH_TABLE_SIZE CYGNUM_FS_FAT_NODE_HASH_TABLE_SIZE
#define FATFS_NODE_ALLOC_THRESHOLD CYGNUM_FS_FAT_NODE_ALLOC_THRESHOLD
-#define FATFS_FAT_TABLE_CACHE_INCREMENT CYGNUM_FS_FAT_FAT_TABLE_CACHE_INCREMENT
-
#ifdef CYGDBG_FS_FAT_NODE_CACHE_EXTRA_CHECKS
# define FATFS_NODE_CACHE_EXTRA_CHECKS 1
#endif
// --------------------------------------------------------------------------
// Node cache tracing support
//#define FATFS_TRACE_NODE_CACHE 1
-// FAT table cache tracing support
-//#define FATFS_TRACE_FAT_TABLE_CACHE 1
-
// FAT table operations tracing support
//#define FATFS_TRACE_FAT_TABLE 1
// FAT dir entry operations tracing support
//#define FATFS_TRACE_DIR_ENTRY 1
@@ -118,17 +112,10 @@
// (0 - first cluster of file,
// 1 - second cluster of file, ...)
cyg_uint32 cluster_pos; // Position inside cluster
} fatfs_data_pos_t;
-typedef struct fatfs_tcache_s
-{
- cyg_uint32 *clusters; // Cached clusters array
- cyg_uint32 size; // Number of cached clusters in array
- cyg_uint32 max_size; // Size of array (allocated space)
-} fatfs_tcache_t;
-
typedef struct fatfs_node_s
{
char filename[12+1]; // File name
mode_t mode; // Node type
cyg_ucount32 refcnt; // Open file/current dir references
@@ -142,12 +129,10 @@
fatfs_data_pos_t dentry_pos; // Position of node's dir entry on disk
struct fatfs_node_s *list_prev; // Next node in list
struct fatfs_node_s *list_next; // Prev node in list
struct fatfs_node_s *hash_next; // Next node in hash
-
- fatfs_tcache_t tcache; // Node FAT table clusters cache
} fatfs_node_t;
typedef struct fatfs_hash_table_s
{
cyg_uint32 size; // Number of slots
@@ -179,14 +164,10 @@
fatfs_type_t fat_type; // Type of FAT - 12 or 16
cyg_io_handle_t dev_h; // Disk device handle
fatfs_node_t *root; // Root dir node
- cyg_uint8 *tcache_mem; // FAT table cache memory base
- cyg_handle_t tcache_mpool_h; // FAT table cache memory pool handle
- cyg_mempool_var tcache_mpool; // FAT table cache memory pool struct
-
cyg_uint8 *bcache_mem; // Block cache memory base
cyg_blib_t blib; // Block cache and access library instance
fatfs_node_list_t live_nlist; // List of nodes with refcnt > 0
fatfs_node_list_t dead_nlist; // List of nodes with refcnt == 0
@@ -195,18 +176,35 @@
// --------------------------------------------------------------------------
int fatfs_get_disk_info(fatfs_disk_t *disk);
+int fatfs_get_disk_usage(fatfs_disk_t *disk,
+ cyg_uint32 *total_clu,
+ cyg_uint32 *free_clu);
+
void fatfs_get_root_node(fatfs_disk_t *disk, fatfs_node_t *root);
bool fatfs_is_node_root_node(fatfs_node_t *node);
-int fatfs_get_dir_entry_node(fatfs_disk_t *disk,
- fatfs_node_t *dir,
- cyg_uint32 *pos,
- fatfs_node_t *node);
+int fatfs_initpos(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos);
+
+int fatfs_setpos(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos,
+ cyg_uint32 offset);
+
+cyg_uint32 fatfs_getpos(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos);
+
+int fatfs_get_dir_entry_node(fatfs_disk_t *disk,
+ fatfs_node_t *dir,
+ fatfs_data_pos_t *pos,
+ fatfs_node_t *node);
int fatfs_write_file_attr(fatfs_disk_t *disk, fatfs_node_t *node);
int fatfs_delete_file(fatfs_disk_t *disk, fatfs_node_t *node);
@@ -229,21 +227,21 @@
fatfs_node_t *node,
fatfs_node_t *dir2,
const char *name,
int namelen);
-int fatfs_read_data(fatfs_disk_t *disk,
- fatfs_node_t *node,
- void *data,
- cyg_uint32 *len,
- cyg_uint32 off);
-
-int fatfs_write_data(fatfs_disk_t *disk,
- fatfs_node_t *node,
- void *data,
- cyg_uint32 *len,
- cyg_uint32 off);
+int fatfs_read_data(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos,
+ void *data,
+ cyg_uint32 *len);
+
+int fatfs_write_data(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos,
+ void *data,
+ cyg_uint32 *len);
// --------------------------------------------------------------------------
void fatfs_node_cache_init(fatfs_disk_t *disk);
@@ -268,37 +266,10 @@
int fatfs_get_live_node_count(fatfs_disk_t *disk);
int fatfs_get_dead_node_count(fatfs_disk_t *disk);
-void fatfs_node_flush_dead_tcache(fatfs_disk_t *disk);
-
-// --------------------------------------------------------------------------
-
-int fatfs_tcache_create(fatfs_disk_t *disk, cyg_uint32 mem_size);
-
-void fatfs_tcache_delete(fatfs_disk_t *disk);
-
-void fatfs_tcache_init(fatfs_disk_t *disk, fatfs_tcache_t *tcache);
-
-void fatfs_tcache_flush(fatfs_disk_t *disk, fatfs_tcache_t *tcache);
-
-bool fatfs_tcache_get(fatfs_disk_t *disk,
- fatfs_tcache_t *tcache,
- cyg_uint32 num,
- cyg_uint32 *cluster);
-
-bool fatfs_tcache_get_last(fatfs_disk_t *disk,
- fatfs_tcache_t *tcache,
- cyg_uint32 *num,
- cyg_uint32 *cluster);
-
-bool fatfs_tcache_set(fatfs_disk_t *disk,
- fatfs_tcache_t *tcache,
- cyg_uint32 num,
- cyg_uint32 cluster);
-
// --------------------------------------------------------------------------
// Support routines
// These enable the definition of local versions of certain routines
// if the given packages are not present.
Index: fs/fat/current/src/fatfs_ncache.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/fat/current/src/fatfs_ncache.c,v
retrieving revision 1.1
diff -u -5 -r1.1 fatfs_ncache.c
--- fs/fat/current/src/fatfs_ncache.c 19 Jan 2004 14:35:02 -0000 1.1
+++ fs/fat/current/src/fatfs_ncache.c 5 Jul 2004 07:51:34 -0000
@@ -626,11 +626,10 @@
{
next_node = node_list_get_next(node);
node_list_remove(&disk->live_nlist, node);
if (!node_hash_remove(&disk->node_hash, node))
CYG_ASSERT(false, "Node not in hash");
- fatfs_tcache_flush(disk, &node->tcache);
free(node);
node = next_node;
}
node = node_list_get_head(&disk->dead_nlist);
@@ -639,11 +638,10 @@
{
next_node = node_list_get_next(node);
node_list_remove(&disk->dead_nlist, node);
if (!node_hash_remove(&disk->node_hash, node))
CYG_ASSERT(false, "Node not in hash");
- fatfs_tcache_flush(disk, &node->tcache);
free(node);
node = next_node;
}
SANITY_CHECK();
@@ -686,25 +684,19 @@
if (NULL == anode)
return NULL;
CYG_TRACE1(TNC, "recycling node='%s'", anode->filename);
- // Flush FAT table cache
- fatfs_tcache_flush(disk, &anode->tcache);
-
node_list_remove(&disk->dead_nlist, anode);
if (!node_hash_remove(&disk->node_hash, anode))
CYG_ASSERT(false, "Node not in hash");
}
// Init new node
*anode = *node_data;
anode->refcnt = 0;
- // Init FAT table cache
- fatfs_tcache_init(disk, &anode->tcache);
-
node_list_head_add(&disk->dead_nlist, anode);
if (!node_hash_add(&disk->node_hash, anode))
CYG_ASSERT(false, "Node already in hash");
SANITY_CHECK();
@@ -822,13 +814,10 @@
CYG_CHECK_DATA_PTRC(node);
CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->filename, node->refcnt);
CYG_ASSERTC(node->refcnt == 0);
CYG_ASSERTC(node != disk->root);
- // Flush FAT table cache
- fatfs_tcache_flush(disk, &node->tcache);
-
// Remove from dead list and from hash and free ptr
node_list_remove(&disk->dead_nlist, node);
if (!node_hash_remove(&disk->node_hash, node))
CYG_ASSERT(false, "node not in hash");
free(node);
@@ -899,28 +888,7 @@
fatfs_get_dead_node_count(fatfs_disk_t *disk)
{
return node_list_get_size(&disk->dead_nlist);
}
-//--------------------------------------------------------------------------
-// fatfs_node_flush_dead_tcache()
-// Flushes FAT table cache of dead nodes.
-
-void
-fatfs_node_flush_dead_tcache(fatfs_disk_t *disk)
-{
- fatfs_node_t *node;
-
- CYG_CHECK_DATA_PTRC(disk);
-
- node = node_list_get_tail(&disk->dead_nlist);
-
- while (NULL != node)
- {
- CYG_TRACE1(TNC, "node='%s'", node->filename);
- fatfs_tcache_flush(disk, &node->tcache);
- node = node_list_get_prev(node);
- }
-}
-
// -------------------------------------------------------------------------
// EOF fatfs_ncache.c
Index: fs/fat/current/src/fatfs_supp.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/fat/current/src/fatfs_supp.c,v
retrieving revision 1.1
diff -u -5 -r1.1 fatfs_supp.c
--- fs/fat/current/src/fatfs_supp.c 19 Jan 2004 14:35:02 -0000 1.1
+++ fs/fat/current/src/fatfs_supp.c 5 Jul 2004 07:51:37 -0000
@@ -931,47 +931,19 @@
// Searching from given position.
static int
find_nth_cluster0(fatfs_disk_t *disk,
fatfs_data_pos_t *dpos,
- cyg_uint32 n,
- fatfs_tcache_t *tcache)
+ cyg_uint32 n)
{
cyg_uint32 cluster, cluster_snum;
int err = ENOERR;
// Trivial case check
if (dpos->cluster_snum == n)
return ENOERR;
- // First look in cache
- if (NULL != tcache)
- {
- cyg_uint32 c, ln;
- if (fatfs_tcache_get(disk, tcache, n, &c))
- {
- // Cluster in cache
- dpos->cluster = c;
- dpos->cluster_snum = n;
- CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d in cache", c, n);
- return ENOERR;
- }
- else if (fatfs_tcache_get_last(disk, tcache, &ln, &c))
- {
- // Cluster not in cache - get last
- // in cache and search from there
- dpos->cluster = c;
- dpos->cluster_snum = ln;
- CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d last in cache", c, ln);
- }
- else
- {
- // Empty cache - put first cluster in
- fatfs_tcache_set(disk, tcache, dpos->cluster_snum, dpos->cluster);
- }
- }
-
cluster = dpos->cluster;
cluster_snum = dpos->cluster_snum;
CYG_TRACE4(TCL, "cluster=%d cluster_snum=%d n=%d n_to_search=%d",
cluster, cluster_snum, n, n-cluster_snum);
@@ -1008,12 +980,10 @@
err = EIO;
goto out;
}
cluster = get_tentry_next_cluster(disk, tentry);
cluster_snum++;
- if (NULL != tcache)
- fatfs_tcache_set(disk, tcache, cluster_snum, cluster);
n--;
}
out:
dpos->cluster = cluster;
@@ -1032,17 +1002,16 @@
static int
find_nth_cluster(fatfs_disk_t *disk,
fatfs_data_pos_t *dpos,
cyg_uint32 n,
- fatfs_tcache_t *tcache,
cluster_opts_t opts)
{
int err;
// Find nth cluster
- err = find_nth_cluster0(disk, dpos, n, tcache);
+ err = find_nth_cluster0(disk, dpos, n);
// EEOF meens that the cluster chain ended early
if ((err != EEOF) || !(opts & CO_EXTEND))
return err;
@@ -1065,14 +1034,10 @@
dpos->cluster_snum++;
dpos->cluster_pos = 0;
CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d",
dpos->cluster, dpos->cluster_snum);
-
- // Update cache
- if (NULL != tcache)
- fatfs_tcache_set(disk, tcache, dpos->cluster_snum, dpos->cluster);
}
return err;
}
@@ -1083,19 +1048,18 @@
// chain then the chain is extended by one cluster.
static int
get_next_cluster(fatfs_disk_t *disk,
fatfs_data_pos_t *dpos,
- fatfs_tcache_t *tcache,
cluster_opts_t opts)
{
int err;
CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d",
dpos->cluster, dpos->cluster_snum);
- err = find_nth_cluster(disk, dpos, dpos->cluster_snum + 1, tcache, opts);
+ err = find_nth_cluster(disk, dpos, dpos->cluster_snum + 1, opts);
if (err != ENOERR)
return err;
// Update position
@@ -1108,44 +1072,53 @@
}
// -------------------------------------------------------------------------
// get_data_position_from_off()
// Gets data position from given file offset.
-// If CO_EXTEND is specified the file is extended if
-// one cluster too short.
-
-static int
+// If CO_EXTEND is specified the file is extended if
+// one cluster too short.
+
+static int
get_data_position_from_off(fatfs_disk_t *disk,
- cyg_uint32 first_cluster,
- cyg_uint32 offset,
- fatfs_data_pos_t *dpos,
- fatfs_tcache_t *tcache,
+ cyg_uint32 first_cluster,
+ cyg_uint32 offset,
+ fatfs_data_pos_t *pos,
cluster_opts_t opts)
{
- cyg_uint32 n;
- int err;
+ fatfs_data_pos_t new_pos;
+ cyg_uint32 n;
+ int err;
// Position inside the cluster
- dpos->cluster_pos = offset & (disk->cluster_size - 1);
+ new_pos.cluster_pos = offset & (disk->cluster_size - 1);
// Cluster seq number to be searched for
n = offset >> disk->cluster_size_log2;
- // Start searching from first cluster
- dpos->cluster = first_cluster;
- dpos->cluster_snum = 0;
-
- CYG_TRACE4(TCL, "off=%d first_cluster=%d cluster_pos=%d n=%d\n",
- offset, first_cluster, dpos->cluster_pos, n);
-
- err = find_nth_cluster(disk, dpos, n, tcache, opts);
+ if (n < pos->cluster_snum)
+ {
+ // Start searching from first cluster
+ new_pos.cluster = first_cluster;
+ new_pos.cluster_snum = 0;
+ }
+ else
+ {
+ // Start searching from the current position
+ new_pos.cluster = pos->cluster;
+ new_pos.cluster_snum = pos->cluster_snum;
+ }
+ err = find_nth_cluster(disk, &new_pos, n, opts);
+
// Err could be EEOF wich means that the given
// offset if out of given file (cluster chain)
+ if (ENOERR == err)
+ *pos = new_pos;
+
return err;
-}
+}
// -------------------------------------------------------------------------
// free_cluster_chain()
// Marks all clusters FREE from given cluster to the last cluster in chain.
@@ -1444,62 +1417,45 @@
// Gets next dir entry searching from given position to the end.
// Position is expected in DENTRY_SIZE units.
// If EEOF is returned there are no more extries in given dir.
static int
-get_next_dentry(fatfs_disk_t *disk,
- fatfs_node_t *dir,
- cyg_uint32 *pos,
- fat_dir_entry_t *dentry)
+get_next_dentry(fatfs_disk_t *disk,
+ fatfs_node_t *dir,
+ fatfs_data_pos_t *pos,
+ fat_dir_entry_t *dentry)
{
- fatfs_data_pos_t dpos;
- cyg_uint32 off;
int err = ENOERR;
- // Calculate dentry offset
- off = *pos * DENTRY_SIZE;
-
CYG_TRACE4(TDE, "pos=%d off=%d dir=%p cluster=%d",
off, *pos, dir, dir->cluster);
- // Root dir check
- if (0 == dir->cluster)
- {
- dpos.cluster = 0;
- dpos.cluster_snum = 0;
- dpos.cluster_pos = off;
- }
- else
- {
- err = get_data_position_from_off(disk, dir->cluster,
- off, &dpos, &dir->tcache, false);
- if (err != ENOERR)
- return err;
- }
-
while (true)
{
// Root dir check
if (0 != dir->cluster)
{
// Change cluster if needed
- if (!is_pos_inside_cluster(disk, dpos.cluster_pos))
- err = get_next_cluster(disk, &dpos, &dir->tcache, CO_NONE);
+ if (!is_pos_inside_cluster(disk, pos->cluster_pos))
+ err = get_next_cluster(disk, pos, CO_NONE);
}
else
{
- if (*pos >= disk->fat_root_dir_nents)
+ if (pos->cluster_pos >= disk->fat_root_dir_nents)
err = EEOF;
}
if (err != ENOERR)
break;
- err = read_dentry(disk, &dpos, dentry);
+ err = read_dentry(disk, pos, dentry);
if (err != ENOERR)
return err;
+ // Increment offset and position
+ pos->cluster_pos += DENTRY_SIZE;
+
if (DENTRY_IS_ZERO(dentry))
{
// If we get a ZERO dir entry, we assume that
// there are no more entries in current dir
CYG_TRACE0(TDE, "ZERO dentry");
@@ -1511,20 +1467,15 @@
// Dir entry found
CYG_TRACE3(TDE, "dentry_pos=%d cluster=%d pos=%d",
*pos, dpos.cluster, dpos.cluster_pos);
break;
}
-
- // Increment offset and position
- dpos.cluster_pos += DENTRY_SIZE;
- (*pos)++;
}
- if (EEOF == err) CYG_TRACE0(TDE, "end of dir");
-
// EEOF could be returned if there are no more entries in this
// dir - this should be cought by the calling function
+
return err;
}
// -------------------------------------------------------------------------
// get_free_dentry()
@@ -1533,12 +1484,11 @@
// entry is reused.
// The directory is extended if needed.
static int
get_free_dentry(fatfs_disk_t *disk,
- fatfs_data_pos_t *dpos,
- fatfs_tcache_t *tcache)
+ fatfs_data_pos_t *dpos)
{
fat_dir_entry_t dentry;
fatfs_data_pos_t cdpos;
int err = ENOERR;
@@ -1551,12 +1501,11 @@
// Root dir check
if (0 != cdpos.cluster)
{
// Change cluster if needed
if (!is_pos_inside_cluster(disk, cdpos.cluster_pos))
- err = get_next_cluster(disk, &cdpos, tcache,
- CO_EXTEND | CO_ERASE_NEW);
+ err = get_next_cluster(disk, &cdpos, CO_EXTEND | CO_ERASE_NEW);
}
else
{
if (cdpos.cluster_pos >= disk->fat_root_dir_size)
err = ENOSPC;
@@ -1655,12 +1604,11 @@
static int
read_data(fatfs_disk_t *disk,
void *data,
cyg_uint32 *len,
- fatfs_data_pos_t *dpos,
- fatfs_tcache_t *tcache)
+ fatfs_data_pos_t *dpos)
{
unsigned char *buf;
cyg_uint32 apos;
cyg_uint32 size;
int err;
@@ -1681,11 +1629,11 @@
// Check if we are still inside current cluster
if (!is_pos_inside_cluster(disk, dpos->cluster_pos))
{
// Get next cluster of file and adjust absolute disk position
- err = get_next_cluster(disk, dpos, tcache, CO_NONE);
+ err = get_next_cluster(disk, dpos, CO_NONE);
if (err != ENOERR)
goto out;
apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
}
@@ -1726,12 +1674,11 @@
static int
write_data(fatfs_disk_t *disk,
void *data,
cyg_uint32 *len,
- fatfs_data_pos_t *dpos,
- fatfs_tcache_t *tcache)
+ fatfs_data_pos_t *dpos)
{
unsigned char *buf;
cyg_uint32 apos;
cyg_uint32 size;
int err;
@@ -1753,11 +1700,11 @@
// Check if we are still inside current cluster
if (!is_pos_inside_cluster(disk, dpos->cluster_pos))
{
// Get next cluster of file and adjust absolute disk position,
// if at the last cluster try to extend the cluster chain
- err = get_next_cluster(disk, dpos, tcache, CO_EXTEND);
+ err = get_next_cluster(disk, dpos, CO_EXTEND);
if (err != ENOERR)
goto out;
apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
}
@@ -1824,10 +1771,39 @@
node->parent_cluster = parent_cluster;
node->dentry_pos = *dentry_pos;
}
// -------------------------------------------------------------------------
+// fatfs_get_disk_usage()
+// Gets disk space.
+
+int
+fatfs_get_disk_usage(fatfs_disk_t *disk,
+ cyg_uint32 *total_clu,
+ cyg_uint32 *free_clu)
+{
+ cyg_uint32 c, nfree, tentry;
+ int err;
+
+ nfree = 0;
+ for (c = 2; c < disk->fat_tbl_nents; c++)
+ {
+ err = read_tentry(disk, c, &tentry);
+ if (err != ENOERR)
+ return err;
+
+ if (TENTRY_FREE == get_tentry_type(disk, tentry))
+ nfree++;
+ }
+
+ *total_clu = disk->fat_tbl_nents - 2;
+ *free_clu = nfree;
+
+ return ENOERR;
+}
+
+// -------------------------------------------------------------------------
// is_node_root_node()
// Check if the given node is the root dir node
static __inline__ bool
is_node_root_node(fatfs_node_t *node)
@@ -1953,14 +1929,14 @@
// dir entry and its position are returned.
// If EEOF error is returned, then there are no more dir
// entries in given dir.
int
-fatfs_get_dir_entry_node(fatfs_disk_t *disk,
- fatfs_node_t *dir,
- cyg_uint32 *pos,
- fatfs_node_t *node)
+fatfs_get_dir_entry_node(fatfs_disk_t *disk,
+ fatfs_node_t *dir,
+ fatfs_data_pos_t *pos,
+ fatfs_node_t *node)
{
fat_dir_entry_t dentry;
int err;
CYG_CHECK_DATA_PTRC(disk);
@@ -1978,10 +1954,60 @@
return ENOERR;
}
// -------------------------------------------------------------------------
+// fatfs_initpos()
+
+int
+fatfs_initpos(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos)
+{
+ CYG_CHECK_DATA_PTRC(disk);
+ CYG_CHECK_DATA_PTRC(node);
+ CYG_CHECK_DATA_PTRC(pos);
+
+ pos->cluster = node->cluster;
+ pos->cluster_snum = 0;
+ pos->cluster_pos = 0;
+
+ return ENOERR;
+}
+
+// -------------------------------------------------------------------------
+// fatfs_setpos()
+
+int
+fatfs_setpos(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos,
+ cyg_uint32 offset)
+{
+ int err;
+
+ CYG_CHECK_DATA_PTRC(disk);
+ CYG_CHECK_DATA_PTRC(node);
+ CYG_CHECK_DATA_PTRC(pos);
+
+ err = get_data_position_from_off(disk, node->cluster, offset, pos, CO_NONE);
+
+ return err;
+}
+
+// -------------------------------------------------------------------------
+// fatfs_getpos()
+
+cyg_uint32
+fatfs_getpos(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos)
+{
+ return (pos->cluster_snum << disk->cluster_size_log2) + pos->cluster_pos;
+}
+
+// -------------------------------------------------------------------------
// fatfs_write_node()
// Writes node attributes to its dir entry (to disk).
int
fatfs_write_file_attr(fatfs_disk_t *disk, fatfs_node_t *node)
@@ -2019,25 +2045,27 @@
node_to_dentry(node, &dentry);
// Check if we are about to delete a directory
if (DENTRY_IS_DIR(&dentry))
{
- fat_dir_entry_t cdentry;
- cyg_uint32 pos = 0;
+ fat_dir_entry_t cdentry;
+ fatfs_data_pos_t pos;
int i = 0;
+ fatfs_initpos(disk, node, &pos);
+
CYG_TRACE0(TDE, "got directory");
// Count number of entries in this dir
while (true)
{
err = get_next_dentry(disk, node, &pos, &cdentry);
if (EEOF == err)
break;
else if (err != ENOERR)
return err;
- i++; pos++;
+ i++;
}
CYG_TRACE1(TDE, "child count=%d", i);
// Check if the dir is empty (except '.' and '..')
if (i > 2)
@@ -2075,11 +2103,11 @@
dentry.pos.cluster = dir->cluster;
dentry.pos.cluster_snum = 0;
dentry.pos.cluster_pos = 0;
// Get free dir entry in parent dir
- err = get_free_dentry(disk, &dentry.pos, &dir->tcache);
+ err = get_free_dentry(disk, &dentry.pos);
if (err != ENOERR)
return err;
// Set new file attributes
init_node_fattr(node, name, namelen, __stat_mode_REG,
@@ -2126,11 +2154,11 @@
dentry.pos.cluster = dir->cluster;
dentry.pos.cluster_snum = 0;
dentry.pos.cluster_pos = 0;
// Get free dir entry in parent dir
- err = get_free_dentry(disk, &dentry.pos, &dir->tcache);
+ err = get_free_dentry(disk, &dentry.pos);
if (err != ENOERR)
return err;
// Set new dir attributes
init_node_fattr(node, name, namelen, __stat_mode_DIR,
@@ -2203,13 +2231,10 @@
// Free cluster chain
err = free_cluster_chain(disk, node->cluster);
if (err != ENOERR)
return err;
- // Flush tcache
- fatfs_tcache_flush(disk, &node->tcache);
-
// Update node attributes
node->cluster = 0;
node->size = 0;
node->mtime =
node->atime = cyg_timestamp();
@@ -2273,11 +2298,11 @@
dpos.cluster_pos = 0;
CYG_TRACE0(TDE, "writting to new dir");
// Get free dir entry in target dir
- err = get_free_dentry(disk, &dpos, &dir2->tcache);
+ err = get_free_dentry(disk, &dpos);
if (err != ENOERR)
return err;
// Write node dentry to new location
node_to_dentry(node, &dentry);
@@ -2300,13 +2325,15 @@
node->parent_cluster = dir2->cluster;
// If we moved a directory, we also have to correct the '..' entry
if (__stat_mode_DIR == node->mode)
{
- fat_dir_entry_t cdentry;
- cyg_uint32 pos = 0;
-
+ fat_dir_entry_t cdentry;
+ fatfs_data_pos_t pos;
+
+ fatfs_initpos(disk, node, &pos);
+
CYG_TRACE0(TDE, "moving directory - correcting '..' entry");
while (true)
{
err = get_next_dentry(disk, node, &pos, &cdentry);
@@ -2323,11 +2350,10 @@
err = write_dentry(disk, &cdentry.pos, &cdentry);
if (err != ENOERR)
return err;
break;
}
- pos++;
}
}
return ENOERR;
}
@@ -2335,78 +2361,64 @@
// -------------------------------------------------------------------------
// fatfs_read_data()
// Reads data from disk.
int
-fatfs_read_data(fatfs_disk_t *disk,
- fatfs_node_t *node,
- void *data,
- cyg_uint32 *len,
- cyg_uint32 off)
+fatfs_read_data(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos,
+ void *data,
+ cyg_uint32 *len)
{
- int err;
- fatfs_data_pos_t dpos;
-
CYG_CHECK_DATA_PTRC(disk);
CYG_CHECK_DATA_PTRC(node);
CYG_CHECK_DATA_PTRC(data);
CYG_CHECK_DATA_PTRC(len);
-
- err = get_data_position_from_off(disk, node->cluster, off,
- &dpos, &node->tcache, CO_NONE);
- if (err != ENOERR)
- return err;
+ CYG_CHECK_DATA_PTRC(pos);
- err = read_data(disk, data, len, &dpos, &node->tcache);
- return err;
+ return read_data(disk, data, len, pos);
}
// -------------------------------------------------------------------------
// fatfs_write_data()
// Writes data to disk.
int
-fatfs_write_data(fatfs_disk_t *disk,
- fatfs_node_t *node,
- void *data,
- cyg_uint32 *len,
- cyg_uint32 off)
+fatfs_write_data(fatfs_disk_t *disk,
+ fatfs_node_t *node,
+ fatfs_data_pos_t *pos,
+ void *data,
+ cyg_uint32 *len)
{
int err;
- fatfs_data_pos_t dpos;
CYG_CHECK_DATA_PTRC(disk);
CYG_CHECK_DATA_PTRC(node);
CYG_CHECK_DATA_PTRC(data);
CYG_CHECK_DATA_PTRC(len);
+ CYG_CHECK_DATA_PTRC(pos);
// Check if this file has a zero size and no first cluster
if (0 == node->size && 0 == node->cluster)
{
cyg_uint32 free_cluster;
CYG_TRACE0(TDO, "new cluster for zero file");
+
// Get free cluster
err = find_next_free_cluster(disk, 0, &free_cluster, CO_MARK_LAST);
if (err != ENOERR)
{
*len = 0;
return err;
}
node->cluster = free_cluster;
+ fatfs_initpos(disk, node, pos);
}
- err = get_data_position_from_off(disk, node->cluster, off,
- &dpos, &node->tcache,
- CO_MARK_LAST | CO_EXTEND);
- if (err != ENOERR)
- {
- *len = 0;
- return err;
- }
-
- err = write_data(disk, data, len, &dpos, &node->tcache);
+ err = write_data(disk, data, len, pos);
+
return err;
}
// -------------------------------------------------------------------------
// Support routines
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss