From 2272d60c0c7045ffdcfdb3d2c37ed8849a129783 Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 29 Apr 2011 23:50:38 +0000 Subject: Some initial NXFFS bugfixes git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3541 42af7a65-404d-4744-a932-0658087f49c3 --- apps/examples/nxffs/nxffs_main.c | 236 +++++++++++++++++++++++++++++++++++++- nuttx/fs/fs_mount.c | 161 ++++++++++++++++++++------ nuttx/fs/nxffs/nxffs.h | 3 +- nuttx/fs/nxffs/nxffs_initialize.c | 1 + nuttx/fs/nxffs/nxffs_inode.c | 1 + nuttx/tools/mkconfig.c | 5 +- 6 files changed, 369 insertions(+), 38 deletions(-) diff --git a/apps/examples/nxffs/nxffs_main.c b/apps/examples/nxffs/nxffs_main.c index 2e046a26f..f4000b6ea 100644 --- a/apps/examples/nxffs/nxffs_main.c +++ b/apps/examples/nxffs/nxffs_main.c @@ -39,9 +39,16 @@ #include +#include + #include -#include #include +#include +#include +#include +#include +#include +#include #include #include @@ -68,19 +75,222 @@ #define CONFIG_EXAMPLES_NXFFS_BUFSIZE \ (CONFIG_RAMMTD_ERASESIZE * CONFIG_EXAMPLES_NXFFS_NEBLOCKS) +#ifndef CONFIG_EXAMPLES_NXFFS_MAXNAME +# define CONFIG_EXAMPLES_NXFFS_MAXNAME 128 +#endif + +#ifndef CONFIG_EXAMPLES_NXFFS_MAXFILE +# define CONFIG_EXAMPLES_NXFFS_MAXFILE 8192 +#endif + +#ifndef CONFIG_EXAMPLES_NXFFS_GULP +# define CONFIG_EXAMPLES_NXFFS_GULP 347 +#endif + +#ifndef CONFIG_EXAMPLES_NXFFS_MAXOPEN +# define CONFIG_EXAMPLES_NXFFS_MAXOPEN 512 +#endif + +#ifndef CONFIG_EXAMPLES_NXFFS_MOUNTPT +# define CONFIG_EXAMPLES_NXFFS_MOUNTPT "/mnt/nxffs" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nxffs_filedesc_s +{ + FAR char *name; + size_t len; + uint32_t crc; +}; + /**************************************************************************** * Private Data ****************************************************************************/ /* Pre-allocated simulated flash */ static uint8_t g_simflash[CONFIG_EXAMPLES_NXFFS_BUFSIZE]; +static uint8_t g_fileimage[CONFIG_EXAMPLES_NXFFS_MAXFILE]; +static struct nxffs_filedesc_s g_files[CONFIG_EXAMPLES_NXFFS_MAXOPEN]; +static const char g_mountdir[] = CONFIG_EXAMPLES_NXFFS_MOUNTPT "/"; +static int g_nfiles; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxffs_randchar + ****************************************************************************/ + +static inline char nxffs_randchar(void) +{ + int value = rand() % 63; + if (value == 0) + { + return '/'; + } + else if (value <= 10) + { + return value + '0' - 1; + } + else if (value <= 36) + { + return value + 'a' - 11; + } + else /* if (value <= 62) */ + { + return value + 'A' - 37; + } +} + +/**************************************************************************** + * Name: nxffs_randname + ****************************************************************************/ + +static inline void nxffs_randname(FAR struct nxffs_filedesc_s *file) +{ + int dirlen; + int maxname; + int namelen; + int alloclen; + int i; + + dirlen = strlen(g_mountdir); + maxname = CONFIG_EXAMPLES_NXFFS_MAXNAME - dirlen; + namelen = (rand() % maxname) + 1; + alloclen = namelen + dirlen; + + file->name = (FAR char*)malloc(alloclen + 1); + if (!file->name) + { + fprintf(stderr, "ERROR: Failed to allocate name, length=%d\n", namelen); + exit(3); + } + + memcpy(file->name, g_mountdir, dirlen); + for (i = dirlen; i < alloclen; i++) + { + file->name[i] = nxffs_randchar(); + } + + file->name[alloclen] = '\0'; +} + +/**************************************************************************** + * Name: nxffs_randfile + ****************************************************************************/ + +static inline void nxffs_randfile(FAR struct nxffs_filedesc_s *file) +{ + int i; + + file->len = (rand() % CONFIG_EXAMPLES_NXFFS_MAXFILE) + 1; + for (i = 0; i < file->len; i++) + { + g_fileimage[i] = nxffs_randchar(); + } + file->crc = crc32(g_fileimage, file->len); +} + +/**************************************************************************** + * Name: nxffs_freefile + ****************************************************************************/ + +static void nxffs_freefile(FAR struct nxffs_filedesc_s *file) +{ + if (file->name) + { + free(file->name); + } + memset(file, 0, sizeof(struct nxffs_filedesc_s)); +} + +/**************************************************************************** + * Name: nxffs_wrfile + ****************************************************************************/ + +static inline int nxffs_wrfile(void) +{ + struct nxffs_filedesc_s *file = NULL; + size_t offset; + int fd; + int i; + + for (i = 0; i < CONFIG_EXAMPLES_NXFFS_MAXOPEN; i++) + { + if (g_files[i].name == NULL) + { + file = &g_files[i]; + break; + } + } + + if (!file) + { + fprintf(stderr, "No available files\n"); + return ERROR; + } + + nxffs_randname(file); + nxffs_randfile(file); + fd = open(file->name, O_WRONLY, 0666); + if (fd < 0) + { + fprintf(stderr, "Failed to open file: %d\n", errno); + fprintf(stderr, " File name: %s\n", file->name); + fprintf(stderr, " File size: %d\n", file->len); + nxffs_freefile(file); + return ERROR; + } + + for (offset = 0; offset < file->len; ) + { + size_t nbytestowrite = file->len - offset; + ssize_t nbyteswritten; + + if (nbytestowrite > CONFIG_EXAMPLES_NXFFS_GULP) + { + nbytestowrite = CONFIG_EXAMPLES_NXFFS_GULP; + } + + nbyteswritten = write(fd, &g_fileimage[offset], nbytestowrite); + if (nbyteswritten < 0) + { + fprintf(stderr, "Failed to write file: %d\n", errno); + fprintf(stderr, " File name: %s\n", file->name); + fprintf(stderr, " File size: %d\n", file->len); + fprintf(stderr, " Write offset: %d\n", offset); + fprintf(stderr, " Write size: %d\n", nbytestowrite); + nxffs_freefile(file); + close(fd); + return ERROR; + } + else if (nbyteswritten != nbytestowrite) + { + fprintf(stderr, "Partial write: %d\n"); + fprintf(stderr, " File name: %s\n", file->name); + fprintf(stderr, " File size: %d\n", file->len); + fprintf(stderr, " Write offset: %d\n", offset); + fprintf(stderr, " Write size: %d\n", nbytestowrite); + fprintf(stderr, " Written: %d\n", nbyteswritten); + } + offset += nbyteswritten; + } + + close(fd); + g_nfiles++; + return OK; +} /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * user_start + * Name: user_start ****************************************************************************/ int user_start(int argc, char *argv[]) @@ -88,6 +298,10 @@ int user_start(int argc, char *argv[]) FAR struct mtd_dev_s *mtd; int ret; + /* Seed the random number generated */ + + srand(0x93846); + /* Create and initialize a RAM MTD device instance */ mtd = rammtd_initialize(g_simflash, CONFIG_EXAMPLES_NXFFS_BUFSIZE); @@ -106,6 +320,24 @@ int user_start(int argc, char *argv[]) exit(2); } + /* Mount the file system */ + + ret = mount(NULL, CONFIG_EXAMPLES_NXFFS_MOUNTPT, "nxffs", 0, NULL); + if (ret < 0) + { + fprintf(stderr, "ERROR: Failed to mount the NXFFS volume: %d\n", errno); + exit(3); + } + + /* Then write a file to the NXFFS file system */ + + ret = nxffs_wrfile(); + if (ret < 0) + { + fprintf(stderr, "ERROR: Failed to write a file\n"); + exit(3); + } + return 0; } diff --git a/nuttx/fs/fs_mount.c b/nuttx/fs/fs_mount.c index 02317ef19..803f4e797 100644 --- a/nuttx/fs/fs_mount.c +++ b/nuttx/fs/fs_mount.c @@ -41,8 +41,10 @@ #include #include -#include #include +#include +#include + #include #ifdef CONFIG_APPS_BINDIR @@ -62,6 +64,23 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Configuration ************************************************************/ +/* In the canonical case, a file system is bound to a block driver. However, + * some less typical cases a block driver is not required. Examples are + * pseudo file systems (like BINFS) and MTD file systems (like NXFFS). + * + * These file systems all require block drivers: + */ + +#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) +# define BDFS_SUPPORT 1 +#endif + +/* These file systems do not require block drivers */ + +#if defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR) +# define NONBDFS_SUPPORT +#endif /**************************************************************************** * Private Types @@ -69,14 +88,15 @@ struct fsmap_t { - const char *fs_filesystemtype; - const struct mountpt_operations *fs_mops; + FAR const char *fs_filesystemtype; + FAR const struct mountpt_operations *fs_mops; }; /**************************************************************************** * Private Variables ****************************************************************************/ +#ifdef BDFS_SUPPORT #ifdef CONFIG_FS_FAT extern const struct mountpt_operations fat_operations; #endif @@ -84,19 +104,34 @@ extern const struct mountpt_operations fat_operations; extern const struct mountpt_operations romfs_operations; #endif -static const struct fsmap_t g_fsmap[] = +static const struct fsmap_t g_bdfsmap[] = { #ifdef CONFIG_FS_FAT { "vfat", &fat_operations }, #endif #ifdef CONFIG_FS_ROMFS { "romfs", &romfs_operations }, +#endif + { NULL, NULL }, +}; +#endif /* BDFS_SUPPORT*/ + +#ifdef NONBDFS_SUPPORT +#ifdef CONFIG_FS_NXFFS +extern const struct mountpt_operations nxffs_operations; +#endif + +static const struct fsmap_t g_nonbdfsmap[] = +{ +#ifdef CONFIG_FS_NXFFS + { "nxffs", &nxffs_operations }, #endif #ifdef CONFIG_APPS_BINDIR { "binfs", &binfs_operations }, #endif { NULL, NULL }, }; +#endif /* NONBDFS_SUPPORT */ /**************************************************************************** * Public Variables @@ -114,10 +149,12 @@ static const struct fsmap_t g_fsmap[] = * ****************************************************************************/ -static FAR const struct mountpt_operations *mount_findfs(const char *filesystemtype ) +#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT) +static FAR const struct mountpt_operations * +mount_findfs(FAR const struct fsmap_t *fstab, FAR const char *filesystemtype) { - const struct fsmap_t *fsmap; - for (fsmap = g_fsmap; fsmap->fs_filesystemtype; fsmap++) + FAR const struct fsmap_t *fsmap; + for (fsmap = fstab; fsmap->fs_filesystemtype; fsmap++) { if (strcmp(filesystemtype, fsmap->fs_filesystemtype) == 0) { @@ -126,6 +163,7 @@ static FAR const struct mountpt_operations *mount_findfs(const char *filesystemt } return NULL; } +#endif /**************************************************************************** * Public Functions @@ -159,7 +197,10 @@ int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) { - FAR struct inode *blkdrvr_inode; +#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT) +#ifdef BDFS_SUPPORT + FAR struct inode *blkdrvr_inode = NULL; +#endif FAR struct inode *mountpt_inode; FAR const struct mountpt_operations *mops; void *fshandle; @@ -168,33 +209,42 @@ int mount(const char *source, const char *target, /* Verify required pointer arguments */ - if (!source || !target || !filesystemtype) - { - errcode = EFAULT; - goto errout; - } + DEBUGASSERT(target && filesystemtype); - /* Find the specified filesystem */ + /* Find the specified filesystem. Try the block driver file systems first */ - mops = mount_findfs(filesystemtype); - if (!mops) +#ifdef BDFS_SUPPORT + if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL) { - fdbg("Failed to find filsystem %s\n", filesystemtype); - errcode = ENODEV; - goto errout; - } + /* Make sure that a block driver argument was provided */ - /* Find the inode of the block driver indentified by 'source' */ + DEBUGASSERT(source); - status = find_blockdriver(source, mountflags, &blkdrvr_inode); - if (status < 0) + /* Find the block driver */ + + status = find_blockdriver(source, mountflags, &blkdrvr_inode); + if (status < 0) + { + fdbg("Failed to find block driver %s\n", source); + errcode = -status; + goto errout; + } + } + else +#endif /* BDFS_SUPPORT */ +#ifdef NONBDFS_SUPPORT + if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL) { - fdbg("Failed to find block driver %s\n", source); - errcode = -status; - goto errout; + } + else +#endif /* NONBDFS_SUPPORT */ + { + fdbg("Failed to find file system %s\n", filesystemtype); + errcode = ENODEV; + goto errout; } - /* Insert a dummy node -- we need to hold the inode semaphore + /* Insert a dummy node -- we need to hold the inode semaphore * to do this because we will have a momentarily bad structure. */ @@ -227,11 +277,22 @@ int mount(const char *source, const char *target, /* Increment reference count for the reference we pass to the file system */ - blkdrvr_inode->i_crefs++; +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + blkdrvr_inode->i_crefs++; + } +#endif /* On failure, the bind method returns -errorcode */ +#ifdef BDFS_SUPPORT status = mops->bind(blkdrvr_inode, data, &fshandle); +#else + status = mops->bind(NULL, data, &fshandle); +#endif if (status != 0) { /* The inode is unhappy with the blkdrvr for some reason. Back out @@ -240,7 +301,14 @@ int mount(const char *source, const char *target, */ fdbg("Bind method failed: %d\n", status); - blkdrvr_inode->i_crefs--; +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + blkdrvr_inode->i_crefs--; + } +#endif errcode = -status; goto errout_with_mountpt; } @@ -262,7 +330,14 @@ int mount(const char *source, const char *target, * that will persist until umount() is called. */ - inode_release(blkdrvr_inode); +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + inode_release(blkdrvr_inode); + } +#endif return OK; /* A lot of goto's! But they make the error handling much simpler */ @@ -271,18 +346,38 @@ errout_with_mountpt: mountpt_inode->i_crefs = 0; inode_remove(target); inode_semgive(); - inode_release(blkdrvr_inode); +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + inode_release(blkdrvr_inode); + } +#endif inode_release(mountpt_inode); goto errout; errout_with_semaphore: inode_semgive(); - inode_release(blkdrvr_inode); +#ifdef BDFS_SUPPORT +#ifdef NONBDFS_SUPPORT + if (blkdrvr_inode) +#endif + { + inode_release(blkdrvr_inode); + } +#endif errout: errno = errcode; return ERROR; + +#else + fdbg("No filesystems enabled\n"); + ernno = ENOSYS; + return error; +#endif /* BDFS_SUPPORT || NONBDFS_SUPPORT */ } -#endif /* Need at least one filesystem */ +#endif /* CONFIG_FS_READABLE */ diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h index 5b1809ebc..41421c57e 100644 --- a/nuttx/fs/nxffs/nxffs.h +++ b/nuttx/fs/nxffs/nxffs.h @@ -157,8 +157,9 @@ * * INODE_STATE_FILE - The inode is a valid usuable, file * INODE_STATE_DELETED - The inode has been deleted. + * Other values - The inode is bad and has an invalid state. * - * Care is taken so that the GOOD to BAD transition only involves burning + * Care is taken so that the VALID to DELETED transition only involves burning * bits from the erased to non-erased state. */ diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c index fc2d97b65..4b4e272a2 100644 --- a/nuttx/fs/nxffs/nxffs_initialize.c +++ b/nuttx/fs/nxffs/nxffs_initialize.c @@ -182,6 +182,7 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd) /* Initialize the NXFFS volume structure */ volume->mtd = mtd; + sem_init(&volume->exclsem, 0, 1); /* Get the volume geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different diff --git a/nuttx/fs/nxffs/nxffs_inode.c b/nuttx/fs/nxffs/nxffs_inode.c index ae61c9d24..cf87fdb5b 100644 --- a/nuttx/fs/nxffs/nxffs_inode.c +++ b/nuttx/fs/nxffs/nxffs_inode.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c index a10f359d3..c8a6fb261 100644 --- a/nuttx/tools/mkconfig.c +++ b/nuttx/tools/mkconfig.c @@ -198,10 +198,11 @@ int main(int argc, char **argv, char **envp) printf("/* Check if any readable and writable filesystem (OR USB storage) is supported */\n\n"); printf("#undef CONFIG_FS_READABLE\n"); printf("#undef CONFIG_FS_WRITABLE\n"); - printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) || defined(CONFIG_USBSTRG)\n"); + printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) || defined(CONFIG_USBSTRG) || \\\n"); + printf(" defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR)\n"); printf("# define CONFIG_FS_READABLE 1\n"); printf("#endif\n\n"); - printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_USBSTRG)\n"); + printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_USBSTRG) || defined(CONFIG_FS_NXFFS)\n"); printf("# define CONFIG_FS_WRITABLE 1\n"); printf("#endif\n\n"); printf("/* There can be no network support with no socket descriptors */\n\n"); -- cgit v1.2.3