diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-05-20 19:25:58 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-05-20 19:25:58 +0000 |
commit | a0fa0517d8641ebf91ef0ece1dcefb1c093be3d4 (patch) | |
tree | 5d6a4881e9dfb440faaaf91772d60d91ca16e3f7 /nuttx | |
parent | 953334cef0d815362633d35c326a0a62aefb0c39 (diff) | |
download | px4-nuttx-a0fa0517d8641ebf91ef0ece1dcefb1c093be3d4.tar.gz px4-nuttx-a0fa0517d8641ebf91ef0ece1dcefb1c093be3d4.tar.bz2 px4-nuttx-a0fa0517d8641ebf91ef0ece1dcefb1c093be3d4.zip |
Add support for close and fsync
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@242 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/fs/fs_close.c | 2 | ||||
-rw-r--r-- | nuttx/fs/fs_fat32.c | 141 | ||||
-rw-r--r-- | nuttx/fs/fs_fat32.h | 55 | ||||
-rw-r--r-- | nuttx/fs/fs_fat32util.c | 160 | ||||
-rw-r--r-- | nuttx/fs/fs_inoderemove.c | 4 | ||||
-rw-r--r-- | nuttx/fs/fs_read.c | 2 |
6 files changed, 296 insertions, 68 deletions
diff --git a/nuttx/fs/fs_close.c b/nuttx/fs/fs_close.c index 97444c2f2..91480e077 100644 --- a/nuttx/fs/fs_close.c +++ b/nuttx/fs/fs_close.c @@ -77,7 +77,7 @@ int close(int fd) * may have been opened numerous times (for different file * descriptors) and must also handle being closed numerous times. * (3) for the case of the mountpoint, we depend on the close - * methods bing identical in signal and position in the operations + * methods bing identical in signature and position in the operations * vtable. */ diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c index 9d75e9a49..51441bacf 100644 --- a/nuttx/fs/fs_fat32.c +++ b/nuttx/fs/fs_fat32.c @@ -75,6 +75,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer, size_t buflen); static off_t fat_seek(FAR struct file *filp, off_t offset, int whence); static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg); +static int fat_sync(FAR struct file *filp); static int fat_bind(FAR struct inode *blkdriver, const void *data, void **handle); static int fat_unbind(void *handle); @@ -100,6 +101,7 @@ const struct mountpt_operations fat_operations = fat_write, fat_seek, fat_ioctl, + fat_sync, fat_bind, fat_unbind }; @@ -326,12 +328,13 @@ static int fat_close(FAR struct file *filp) struct inode *inode; struct fat_mountpt_s *fs; struct fat_file_s *ff; + int ret = OK; /* Sanity checks */ DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL); - /* Recover our private data from struct file instance */ + /* Recover our private data from the struct file instance */ ff = filp->f_priv; inode = filp->f_inode; @@ -343,7 +346,26 @@ static int fat_close(FAR struct file *filp) * the file even when there is healthy mount. */ - return -ENOSYS; + /* Synchronize the file buffers and disk content; update times */ + + ret = fat_sync(filp); + + /* Then deallocate the memory structures created when the open method + * was called. + * + * Free the sector buffer that was used to manage partial sector accesses. + */ + + if (ff->ff_buffer) + { + free(ff->ff_buffer); + } + + /* Then free the file structure itself. */ + + free(ff); + filp->f_priv = NULL; + return ret; } /**************************************************************************** @@ -361,14 +383,14 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen) unsigned int nsectors; size_t readsector; size_t bytesleft; - char *userbuffer = buffer; + ubyte *userbuffer = (ubyte*)buffer; int ret; /* Sanity checks */ DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL); - /* Recover our private data from struct file instance */ + /* Recover our private data from the struct file instance */ ff = filp->f_priv; inode = filp->f_inode; @@ -564,7 +586,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer, DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL); - /* Recover our private data from struct file instance */ + /* Recover our private data from the struct file instance */ ff = filp->f_priv; inode = filp->f_inode; @@ -578,8 +600,11 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer, ret = fat_checkmount(fs); if (ret != OK) { + fat_semgive(fs); return ret; } + + fat_semgive(fs); return -ENOSYS; } @@ -598,7 +623,7 @@ static off_t fat_seek(FAR struct file *filp, off_t offset, int whence) DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL); - /* Recover our private data from struct file instance */ + /* Recover our private data from the struct file instance */ ff = filp->f_priv; inode = filp->f_inode; @@ -612,8 +637,11 @@ static off_t fat_seek(FAR struct file *filp, off_t offset, int whence) ret = fat_checkmount(fs); if (ret != OK) { + fat_semgive(fs); return ret; } + + fat_semgive(fs); return -ENOSYS; } @@ -632,7 +660,7 @@ static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg) DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL); - /* Recover our private data from struct file instance */ + /* Recover our private data from the struct file instance */ ff = filp->f_priv; inode = filp->f_inode; @@ -646,14 +674,113 @@ static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg) ret = fat_checkmount(fs); if (ret != OK) { + fat_semgive(fs); return ret; } /* ioctl calls are just passed through to the contained block driver */ + + fat_semgive(fs); return -ENOSYS; } /**************************************************************************** + * Name: fat_sync + * + * Description: Synchronize the file state on disk to match internal, in- + * memory state. + * + ****************************************************************************/ + +static int fat_sync(FAR struct file *filp) +{ + struct inode *inode; + struct fat_mountpt_s *fs; + struct fat_file_s *ff; + uint32 wrttime; + ubyte *direntry; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + ff = filp->f_priv; + inode = filp->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Make sure that the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Check if the has been modified in any way */ + if ((ff->ff_bflags & FFBUFF_MODIFIED) != 0) + { + /* Flush any unwritten data in the file buffer */ + + ret = fat_ffcacheflush(fs, ff); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Update the directory entry. First read the directory + * entry into the fs_buffer (preserving the ff_buffer) + */ + + ret = fat_fscacheread(fs, ff->ff_dirsector); + if (ret < 0) + { + goto errout_with_semaphore; + } + + /* Recover a pointer to the specific directory entry + * in the sector using the saved directory index. + */ + + direntry = &fs->fs_buffer[ff->ff_dirindex]; + + /* Set the archive bit, set the write time, and update + * anything that may have* changed in the directory + * entry: the file size, and the start cluster + */ + + direntry[DIR_ATTRIBUTES] |= FATATTR_ARCHIVE; + + DIR_PUTFILESIZE(direntry, ff->ff_size); + DIR_PUTFSTCLUSTLO(direntry, ff->ff_startcluster); + DIR_PUTFSTCLUSTHI(direntry, ff->ff_startcluster >> 16); + + wrttime = fat_gettime(); + DIR_PUTWRTTIME(direntry, wrttime); + + /* Clear the modified bit in the flags */ + + ff->ff_bflags &= ~FFBUFF_MODIFIED; + + /* Flush these change to disk and update FSINFO (if + * appropriate. + */ + + fs->fs_dirty = TRUE; + ret = fat_updatefsinfo(fs); + } + + errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** * Name: fat_bind * * Description: This implements a portion of the mount operation. This diff --git a/nuttx/fs/fs_fat32.h b/nuttx/fs/fs_fat32.h index e6e5a5b85..5687b2b16 100644 --- a/nuttx/fs/fs_fat32.h +++ b/nuttx/fs/fs_fat32.h @@ -289,6 +289,12 @@ # define DIR_GETFSTCLUSTLO(p) fat_getuint16(UBYTE_PTR(p,DIR_FSTCLUSTLO)) # define DIR_GETFILESIZE(p) fat_getuint32(UBYTE_PTR(p,DIR_FILESIZE)) +# define FSI_GETLEADSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_LEADSIG)) +# define FSI_GETSTRUCTSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_STRUCTSIG)) +# define FSI_GETFREECOUNT(p) fat_getuint32(UBYTE_PTR(p,FSI_FREECOUNT)) +# define FSI_GETNXTFREE(p) fat_getuint32(UBYTE_PTR(p,FSI_NXTFREE)) +# define FSI_GETTRAILSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_TRAILSIG)) + # define FAT_GETFAT16(p,i) fat_getuint16(UBYTE_PTR(p,i)) # define FAT_GETFAT32(p,i) fat_getuint32(UBYTE_PTR(p,i)) @@ -321,6 +327,12 @@ # define DIR_PUTFSTCLUSTLO(p,v) fat_putuint16(UBYTE_PTR(p,DIR_FSTCLUSTLO),v) # define DIR_PUTFILESIZE(p,v) fat_putuint32(UBYTE_PTR(p,DIR_FILESIZE),v) +# define FSI_PUTLEADSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_LEADSIG),v) +# define FSI_PUTSTRUCTSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_STRUCTSIG),v) +# define FSI_PUTFREECOUNT(p,v) fat_putuint32(UBYTE_PTR(p,FSI_FREECOUNT),v) +# define FSI_PUTNXTFREE(p,v) fat_putuint32(UBYTE_PTR(p,FSI_NXTFREE),v) +# define FSI_PUTTRAILSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_TRAILSIG),v) + # define FAT_PUTFAT16(p,i,v) fat_putuint16(UBYTE_PTR(p,i),v) # define FAT_PUTFAT32(p,i,v) fat_putuint32(UBYTE_PTR(p,i),v) @@ -361,6 +373,12 @@ # define DIR_GETFSTCLUSTLO(p) UINT16_VAL(p,DIR_FSTCLUSTLO) # define DIR_GETFILESIZE(p) UINT32_VAL(p,DIR_FILESIZE) +# define FSI_GETLEADSIG(p) UINT32_VAL(p,FSI_LEADSIG) +# define FSI_GETSTRUCTSIG(p) UINT32_VAL(p,FSI_STRUCTSIG) +# define FSI_GETFREECOUNT(p) UINT32_VAL(p,FSI_FREECOUNT) +# define FSI_GETNXTFREE(p) UINT32_VAL(p,FSI_NXTFREE) +# define FSI_GETTRAILSIG(p) UINT32_VAL(p,FSI_TRAILSIG) + # define FAT_GETFAT16(p,i) UINT16_VAL(p,i) # define FAT_GETFAT32(p,i) UINT32_VAL(p,i) @@ -393,6 +411,12 @@ # define DIR_PUTFSTCLUSTLO(p,v) UINT16_PUT(p,DIR_FSTCLUSTLO,v) # define DIR_PUTFILESIZE(p,v) UINT32_PUT(p,DIR_FILESIZE,v) +# define FSI_PUTLEADSIG(p,v) UINT32_PUT(p,FSI_LEADSIG,v) +# define FSI_PUTSTRUCTSIG(p,v) UINT32_PUT(p,FSI_STRUCTSIG,v) +# define FSI_PUTFREECOUNT(p,v) UINT32_PUT(p,FSI_FREECOUNT,v) +# define FSI_PUTNXTFREE(p,v) UINT32_PUT(p,FSI_NXTFREE,v) +# define FSI_PUTTRAILSIG(p,v) UINT32_PUT(p,FSI_TRAILSIG,v) + # define FAT_PUTFAT16(p,i,v) UINT16_PUT(p,i,v) # define FAT_PUTFAT32(p,i,v) UINT32_PUT(p,i,v) @@ -430,6 +454,7 @@ struct fat_mountpt_s uint16 fs_rootentcnt; /* MBR: Count of 32-bit root directory entries */ boolean fs_mounted; /* TRUE: The file system is ready */ boolean fs_dirty; /* TRUE: fs_buffer is dirty */ + boolean fs_fsidirty; /* TRUE: FSINFO sector must be written to disk */ ubyte fs_type; /* FSTYPE_FAT12, FSTYPE_FAT16, or FSTYPE_FAT32 */ ubyte fs_fatnumfats; /* MBR: Number of FATs (probably 2) */ ubyte fs_fatsecperclus; /* MBR: Sectors per allocation unit: 2**n, n=0..7 */ @@ -446,7 +471,7 @@ struct fat_file_s { struct fat_file_s *ff_next; /* Retained in a singly linked list */ boolean ff_open; /* TRUE: The file is (still) open */ - boolean ff_bflags; /* The file buffer flags */ + ubyte ff_bflags; /* The file buffer flags */ ubyte ff_oflags; /* Flags provided when file was opened */ ubyte ff_sectorsincluster; /* Sectors remaining in cluster */ uint16 ff_dirindex; /* Index into ff_dirsector to directory entry */ @@ -503,6 +528,10 @@ EXTERN void fat_putuint32(ubyte *ptr, uint32 value32); EXTERN void fat_semtake(struct fat_mountpt_s *fs); EXTERN void fat_semgive(struct fat_mountpt_s *fs); +/* Get the current time for FAT creation and write times */ + +EXTERN uint32 fat_gettime(void); + /* Handle hardware interactions for mounting */ EXTERN int fat_mount(struct fat_mountpt_s *fs, boolean writeable); @@ -510,16 +539,17 @@ EXTERN int fat_checkmount(struct fat_mountpt_s *fs); /* low-level hardware access */ -EXTERN int fat_hwread(struct fat_mountpt_s *fs, ubyte *buffer, size_t sector, - unsigned int nsectors); -EXTERN int fat_hwwrite(struct fat_mountpt_s *fs, ubyte *buffer, size_t sector, - unsigned int nsectors); +EXTERN int fat_hwread(struct fat_mountpt_s *fs, ubyte *buffer, + size_t sector, unsigned int nsectors); +EXTERN int fat_hwwrite(struct fat_mountpt_s *fs, ubyte *buffer, + size_t sector, unsigned int nsectors); /* Cluster access helpers */ EXTERN ssize_t fat_cluster2sector(struct fat_mountpt_s *fs, uint32 cluster ); EXTERN ssize_t fat_getcluster(struct fat_mountpt_s *fs, unsigned int clusterno); -EXTERN int fat_putcluster(struct fat_mountpt_s *fs, unsigned int clusterno, size_t startsector); +EXTERN int fat_putcluster(struct fat_mountpt_s *fs, unsigned int clusterno, + size_t startsector); /* Help for traverseing directory trees */ @@ -531,11 +561,16 @@ EXTERN int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path); EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); EXTERN int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); -/* File buffer cache (for partial sector accesses) */ +/* Mountpoint and fFile buffer cache (for partial sector accesses) */ + +EXTERN int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector); +EXTERN int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff); +EXTERN int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, size_t sector); +EXTERN int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff); + +/* FSINFO sector support */ -EXTERN int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff); -EXTERN int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, size_t sector); -EXTERN int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff); +EXTERN int fat_updatefsinfo(struct fat_mountpt_s *fs); #undef EXTERN #if defined(__cplusplus) diff --git a/nuttx/fs/fs_fat32util.c b/nuttx/fs/fs_fat32util.c index 9cfce4dc9..55378a84b 100644 --- a/nuttx/fs/fs_fat32util.c +++ b/nuttx/fs/fs_fat32util.c @@ -129,51 +129,6 @@ static int fat_fscacheflush(struct fat_mountpt_s *fs) } /**************************************************************************** - * Name: fat_fscacheread - * - * Desciption: Read the specified sector into the sector cache, flushing any - * existing dirty sectors as necessary. - * - ****************************************************************************/ - -static int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector) -{ - int ret; - - /* fs->fs_currentsector holds the current sector that is buffered in - * fs->fs_buffer. If the requested sector is the same as this sector, then - * we do nothing. Otherwise, we will have to read the new sector. - */ - - if (fs->fs_currentsector != sector) - { - /* We will need to read the new sector. First, flush the cached - * sector if it is dirty. - */ - - ret = fat_fscacheflush(fs); - if (ret < 0) - { - return ret; - } - - /* Then read the specified sector into the cache */ - - ret = fat_hwread(fs, fs->fs_buffer, sector, 1); - if (ret < 0) - { - return ret; - } - - /* Update the cached sector number */ - - fs->fs_currentsector = sector; - } - - return OK; -} - -/**************************************************************************** * Name: fat_path2dirname * * Desciption: Convert a user filename into a properly formatted FAT @@ -727,6 +682,28 @@ void fat_semgive(struct fat_mountpt_s *fs) } /**************************************************************************** + * Name: fat_gettime + * + * Desciption: Get the time and date suitble for writing into the FAT FS. + * TIME in LS 16-bits: + * Bits 0:4 = 2 second count (0-29 representing 0-58 seconds) + * Bits 5-10 = minutes (0-59) + * Bits 11-15 = hours (0-23) + * DATE in MS 16-bits + * Bits 0:4 = Day of month (0-31) + * Bits 5:8 = Month of year (1-12) + * Bits 9:15 = Year from 1980 (0-127 representing 1980-2107) + * + * + ****************************************************************************/ + +uint32 fat_gettime(void) +{ +#warning "Time not implemented" + return 0; +} + +/**************************************************************************** * Name: fat_mount * * Desciption: This function is called only when the mountpoint is first @@ -1542,6 +1519,51 @@ int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo) } /**************************************************************************** + * Name: fat_fscacheread + * + * Desciption: Read the specified sector into the sector cache, flushing any + * existing dirty sectors as necessary. + * + ****************************************************************************/ + +int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector) +{ + int ret; + + /* fs->fs_currentsector holds the current sector that is buffered in + * fs->fs_buffer. If the requested sector is the same as this sector, then + * we do nothing. Otherwise, we will have to read the new sector. + */ + + if (fs->fs_currentsector != sector) + { + /* We will need to read the new sector. First, flush the cached + * sector if it is dirty. + */ + + ret = fat_fscacheflush(fs); + if (ret < 0) + { + return ret; + } + + /* Then read the specified sector into the cache */ + + ret = fat_hwread(fs, fs->fs_buffer, sector, 1); + if (ret < 0) + { + return ret; + } + + /* Update the cached sector number */ + + fs->fs_currentsector = sector; + } + + return OK; +} + +/**************************************************************************** * Name: fat_ffcacheflush * * Desciption: Flush any dirty sectors as necessary @@ -1649,4 +1671,52 @@ int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff) return OK; } +/**************************************************************************** + * Name: fat_updatefsinfo + * + * Desciption: Flush evertyhing buffered for the mountpoint and update + * the FSINFO sector, if appropriate + * + ****************************************************************************/ + +int fat_updatefsinfo(struct fat_mountpt_s *fs) +{ + int ret; + + /* Flush the fs_buffer if it is dirty */ + + ret = fat_fscacheflush(fs); + if (ret == OK) + { + /* The FSINFO sector only has to be update for the case of a FAT32 file + * system. Check if the file system type.. If this is a FAT32 file + * system then the fs_fsidirty flag will indicate if the FSINFO sector + * needs to be re-written. + */ + + if (fs->fs_type == FSTYPE_FAT32 && fs->fs_fsidirty) + { + /* Create an image of the FSINFO sector in the fs_buffer */ + + memset(fs->fs_buffer, 0, fs->fs_hwsectorsize); + FSI_PUTLEADSIG(fs->fs_buffer, 0x41615252); + FSI_PUTSTRUCTSIG(fs->fs_buffer, 0x61417272); + FSI_PUTFREECOUNT(fs->fs_buffer, fs->fs_fsifreecount); + FSI_PUTNXTFREE(fs->fs_buffer, fs->fs_fsinextfree); + FSI_PUTTRAILSIG(fs->fs_buffer, 0xaa550000); + + /* Then flush this to disk */ + + fs->fs_currentsector = fs->fs_fsinfo; + fs->fs_dirty = TRUE; + ret = fat_fscacheflush(fs); + + /* No longer dirty */ + + fs->fs_fsidirty = FALSE; + } + } + return ret; +} + #endif /* CONFIG_FS_FAT */ diff --git a/nuttx/fs/fs_inoderemove.c b/nuttx/fs/fs_inoderemove.c index b6b56c4af..633222567 100644 --- a/nuttx/fs/fs_inoderemove.c +++ b/nuttx/fs/fs_inoderemove.c @@ -119,7 +119,6 @@ STATUS inode_remove(const char *path) /* Find the node to delete */ - inode_semtake(); node = inode_search(&name, &left, &parent, NULL); if (node) { @@ -137,13 +136,11 @@ STATUS inode_remove(const char *path) */ node->i_flags |= FSNODEFLAG_DELETED; - inode_semgive(); } else { /* And delete it now -- recursively to delete all of its children */ - inode_semgive(); inode_free(node->i_child); free(node); return OK; @@ -152,6 +149,5 @@ STATUS inode_remove(const char *path) /* The node does not exist or it has references */ - inode_semgive(); return ERROR; } diff --git a/nuttx/fs/fs_read.c b/nuttx/fs/fs_read.c index 4b1a2ce77..1cd291936 100644 --- a/nuttx/fs/fs_read.c +++ b/nuttx/fs/fs_read.c @@ -89,7 +89,7 @@ int read(int fd, void *buf, unsigned int nbytes) { /* Yes, then let it perform the read. NOTE that for the case * of the mountpoint, we depend on the read methods bing - * identical in signal and position in the operations vtable. + * identical in signature and position in the operations vtable. */ ret = (int)inode->u.i_ops->read(this_file, (char*)buf, (size_t)nbytes); |