This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]