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 + + * 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 + + * 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 * 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 #include -#include #include #include -#include // base kernel types +#include #include // tracing macros #include // assertion macros #include #include @@ -69,11 +68,10 @@ #include #include #include -#include #include #include #include #include @@ -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 -#include #include #include #include #include @@ -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