From 769ffb8a4b5f09b705ca8d74ba8961afbbfeac07 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 31 Oct 2017 09:00:49 -0600 Subject: [PATCH] apps/examples/userfs: Add a test case for verifying UserFS. --- examples/README.txt | 5 + examples/userfs/.gitignore | 11 + examples/userfs/Kconfig | 30 ++ examples/userfs/Make.defs | 39 +++ examples/userfs/Makefile | 56 ++++ examples/userfs/userfs_main.c | 554 ++++++++++++++++++++++++++++++++++ 6 files changed, 695 insertions(+) create mode 100644 examples/userfs/.gitignore create mode 100644 examples/userfs/Kconfig create mode 100644 examples/userfs/Make.defs create mode 100644 examples/userfs/Makefile create mode 100644 examples/userfs/userfs_main.c diff --git a/examples/README.txt b/examples/README.txt index 4a916cc99..7b7f7f437 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -2127,6 +2127,11 @@ examples/usbserial The host and target will exchange are variety of very small and very large serial messages. +examples/userfs +^^^^^^^^^^^^^^^ + + A simple test of the UserFS file system. + examples/ustream ^^^^^^^^^^^^^^^^ diff --git a/examples/userfs/.gitignore b/examples/userfs/.gitignore new file mode 100644 index 000000000..fa1ec7579 --- /dev/null +++ b/examples/userfs/.gitignore @@ -0,0 +1,11 @@ +/Make.dep +/.depend +/.built +/*.asm +/*.obj +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src diff --git a/examples/userfs/Kconfig b/examples/userfs/Kconfig new file mode 100644 index 000000000..47e250798 --- /dev/null +++ b/examples/userfs/Kconfig @@ -0,0 +1,30 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_USERFS + bool "UserFS test" + default n + ---help--- + Enables a simple test of the UserFS + +if EXAMPLES_USERFS + +config EXAMPLES_USERFS_PROGNAME + string "Program name" + default "userfs" + depends on BUILD_KERNEL + ---help--- + This is the name of the program that will be use when the NSH ELF + program is installed. + +config EXAMPLES_USERFS_PRIORITY + int "UserFS task priority" + default 100 + +config EXAMPLES_USERFS_STACKSIZE + int "UserFS stack size" + default 2048 + +endif diff --git a/examples/userfs/Make.defs b/examples/userfs/Make.defs new file mode 100644 index 000000000..31f241c86 --- /dev/null +++ b/examples/userfs/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# apps/examples/userfs/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_EXAMPLES_USERFS),y) +CONFIGURED_APPS += examples/userfs +endif diff --git a/examples/userfs/Makefile b/examples/userfs/Makefile new file mode 100644 index 000000000..13f68bea7 --- /dev/null +++ b/examples/userfs/Makefile @@ -0,0 +1,56 @@ +############################################################################ +# apps/examples/userfs/Makefile +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +# UserFS test application info + +CONFIG_EXAMPLES_USERFS_PRIORITY ?= SCHED_PRIORITY_DEFAULT +CONFIG_EXAMPLES_USERFS_STACKSIZE ?= 2048 + +APPNAME = userfs +PRIORITY = $(CONFIG_EXAMPLES_USERFS_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_USERFS_STACKSIZE) + +# UserFS test application source files + +ASRCS = +CSRCS = +MAINSRC = userfs_main.c + +CONFIG_EXAMPLES_USERFS_PROGNAME ?= userfs$(EXEEXT) +PROGNAME = $(CONFIG_EXAMPLES_USERFS_PROGNAME) + +include $(APPDIR)/Application.mk diff --git a/examples/userfs/userfs_main.c b/examples/userfs/userfs_main.c new file mode 100644 index 000000000..f4381ae40 --- /dev/null +++ b/examples/userfs/userfs_main.c @@ -0,0 +1,554 @@ +/**************************************************************************** + * examples/userfs/userfs_main.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define UFSTEST_NFILES 3 +#define UFSTEST_FS_BLOCKSIZE 32 + +#define UFSTEST_FILE1_BLOCKS (2) +#define UFSTEST_FILE1_MXSIZE (UFSTEST_FILE1_BLOCKS * UFSTEST_FS_BLOCKSIZE) +#define UFSTEST_FILE2_BLOCKS (3) +#define UFSTEST_FILE2_MXSIZE (UFSTEST_FILE2_BLOCKS * UFSTEST_FS_BLOCKSIZE) +#define UFSTEST_FILE3_BLOCKS (4) +#define UFSTEST_FILE3_MXSIZE (UFSTEST_FILE3_BLOCKS * UFSTEST_FS_BLOCKSIZE) + +#define UFSTEST_FS_NBLOCKS (UFSTEST_FILE1_BLOCKS + UFSTEST_FILE2_BLOCKS + UFSTEST_FILE3_BLOCKS) +#define UFSTEST_FS_NBYTES (UFSTEST_FILE1_MXSIZE + UFSTEST_FILE2_MXSIZE + UFSTEST_FILE3_MXSIZE) +#define UFSTEST_MXWRITE UFSTEST_FILE3_MXSIZE + +#define UFSTEST_MOUNTPOUNT "/mnt/ufstest" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ufstest_file_s +{ + struct dirent entry; + uint16_t inuse; + uint16_t mxsize; + FAR char *data; +}; + +struct ufstest_openfile_s +{ + int16_t pos; + FAR struct ufstest_file_s *file; +}; + +struct ufstest_opendir_s +{ + int16_t index; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* UserFS methods */ + +static int ufstest_open(FAR void *volinfo, FAR const char *relpath, + int oflags, mode_t mode, FAR void **openinfo); +static int ufstest_close(FAR void *volinfo, FAR void *openinfo); +static ssize_t ufstest_read(FAR void *volinfo, FAR void *openinfo, + FAR char *buffer, size_t buflen); +static ssize_t ufstest_write(FAR void *volinfo, FAR void *openinfo, + FAR const char *buffer, size_t buflen); +static off_t ufstest_seek(FAR void *volinfo, FAR void *openinfo, + off_t offset, int whence); +static int ufstest_ioctl(FAR void *volinfo, FAR void *openinfo, int cmd, + unsigned long arg); +static int ufstest_sync(FAR void *volinfo, FAR void *openinfo); +static int ufstest_dup(FAR void *volinfo, FAR void *oldinfo, + FAR void *newinfo); +static int ufstest_fstat(FAR void *volinfo, FAR void *openinfo, + FAR struct stat *buf); +static int ufstest_opendir(FAR void *volinfo, FAR const char *relpath, + FAR void **dir); +static int ufstest_closedir(FAR void *volinfo, FAR void *dir); +static int ufstest_readdir(FAR void *volinfo, FAR void *dir, + FAR struct dirent *entry); +static int ufstest_rewinddir(FAR void *volinfo, FAR void *dir); +static int ufstest_statfs(FAR void *volinfo, FAR struct statfs *buf); +static int ufstest_unlink(FAR void *volinfo, FAR const char *relpath); +static int ufstest_mkdir(FAR void *volinfo, FAR const char *relpath, + mode_t mode); +static int ufstest_rmdir(FAR void *volinfo, FAR const char *relpath); +static int ufstest_rename(FAR void *volinfo, FAR const char *oldrelpath, + FAR const char *newrelpath); +static int ufstest_stat(FAR void *volinfo, FAR const char *relpath, + FAR struct stat *buf); +static int ufstest_destroy(FAR void *volinfo); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char g_file1_data[UFSTEST_FILE1_MXSIZE] = "This is file 1"; +#define UFSTEST_INIT_FILE1_SIZE 14 + +static char g_file2_data[UFSTEST_FILE2_MXSIZE] = "This is file 2"; +#define UFSTEST_INIT_FILE2_SIZE 14 + +static char g_file3_data[UFSTEST_FILE3_MXSIZE] = "This is file 3"; +#define UFSTEST_INIT_FILE3_SIZE 14 + +static struct ufstest_file_s g_rootdir[UFSTEST_NFILES] = +{ + { + { DTYPE_FILE, "File1" }, + UFSTEST_INIT_FILE1_SIZE, + UFSTEST_FILE1_MXSIZE, + g_file1_data + }, + { + { DTYPE_FILE, "File2" }, + UFSTEST_INIT_FILE2_SIZE, + UFSTEST_FILE2_MXSIZE, + g_file2_data + }, + { + { DTYPE_FILE, "File3" }, + UFSTEST_INIT_FILE3_SIZE, + UFSTEST_FILE3_MXSIZE, + g_file3_data + } +}; + +static const struct userfs_operations_s g_ufstest_ops = +{ + ufstest_open, + ufstest_close, + ufstest_read, + ufstest_write, + ufstest_seek, + ufstest_ioctl, + ufstest_sync, + ufstest_dup, + ufstest_fstat, + ufstest_opendir, + ufstest_closedir, + ufstest_readdir, + ufstest_rewinddir, + ufstest_statfs, + ufstest_unlink, + ufstest_mkdir, + ufstest_rmdir, + ufstest_rename, + ufstest_stat, + ufstest_destroy +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ufstest_findbyname + ****************************************************************************/ + +static FAR struct ufstest_file_s *ufstest_findbyname(FAR const char *relpath) +{ + int i; + + for (i = 0; i < UFSTEST_NFILES; i++) + { + if (strcmp(relpath, g_rootdir[i].entry.d_name) == 0) + { + return &g_rootdir[i]; + } + } + + return NULL; +} + +/**************************************************************************** + * UserFS methods + ****************************************************************************/ + +static int ufstest_open(FAR void *volinfo, FAR const char *relpath, + int oflags, mode_t mode, FAR void **openinfo) +{ + FAR struct ufstest_openfile_s *opriv; + FAR struct ufstest_file_s *file; + + file = ufstest_findbyname(relpath); + if (file != NULL) + { + opriv = (FAR struct ufstest_openfile_s *) + malloc(sizeof(struct ufstest_openfile_s )); + if (opriv == NULL) + { + return -ENOMEM; + } + + if ((oflags && O_APPEND) != 0) + { + opriv->pos = file->inuse; + } + else + { + opriv->pos = 0; + } + + opriv->file = file; + + *openinfo = opriv; + return OK; + } + + return -ENOENT; +} + +static int ufstest_close(FAR void *volinfo, FAR void *openinfo) +{ + free(openinfo); + return OK; +} + +static ssize_t ufstest_read(FAR void *volinfo, FAR void *openinfo, + FAR char *buffer, size_t buflen) +{ + FAR struct ufstest_openfile_s *opriv = + (FAR struct ufstest_openfile_s *)openinfo; + ssize_t readsize; + + readsize = opriv->file->inuse - opriv->pos; + if (readsize > buflen) + { + readsize = buflen; + } + + if (readsize > 0) + { + memcpy(buffer, &opriv->file->data[opriv->pos], readsize); + opriv->pos += readsize; + } + + return readsize <= 0 ? 0 : readsize; +} + +static ssize_t ufstest_write(FAR void *volinfo, FAR void *openinfo, + FAR const char *buffer, size_t buflen) +{ + FAR struct ufstest_openfile_s *opriv = + (FAR struct ufstest_openfile_s *)openinfo; + ssize_t writesize; + + writesize = opriv->file->mxsize - opriv->pos; + if (writesize > buflen) + { + writesize = buflen; + } + + memcpy(&opriv->file->data[opriv->pos], buffer, writesize); + opriv->pos += writesize; + if (opriv->pos > opriv->file->inuse) + { + opriv->file->inuse = opriv->pos; + } + + return writesize; +} + +static off_t ufstest_seek(FAR void *volinfo, FAR void *openinfo, + off_t offset, int whence) +{ + FAR struct ufstest_openfile_s *opriv = + (FAR struct ufstest_openfile_s *)openinfo; + off_t newpos; + + switch (whence) + { + case SEEK_SET: /* The offset is set to offset bytes. */ + newpos = offset; + break; + + case SEEK_CUR: /* The offset is set to its current location plus + * offset bytes. */ + + newpos = offset + opriv->pos; + break; + + case SEEK_END: /* The offset is set to the size of the file plus + * offset bytes. */ + + newpos = offset + opriv->file->inuse; + break; + + default: + fprintf(stderr, "ERROR: Whence is invalid: %d\n", whence); + return -EINVAL; + } + + if (newpos < 0) + { + newpos = 0; + } + else if (newpos > opriv->file->mxsize) + { + newpos = opriv->file->mxsize; + } + + opriv->pos = newpos; + return newpos; +} + +static int ufstest_ioctl(FAR void *volinfo, FAR void *openinfo, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +static int ufstest_sync(FAR void *volinfo, FAR void *openinfo) +{ + return OK; +} + +static int ufstest_dup(FAR void *volinfo, FAR void *oldinfo, + FAR void *newinfo) +{ + memcpy(newinfo, oldinfo, sizeof(struct ufstest_openfile_s)); + return OK; +} + +static int ufstest_fstat(FAR void *volinfo, FAR void *openinfo, + FAR struct stat *buf) +{ + FAR struct ufstest_openfile_s *opriv = + (FAR struct ufstest_openfile_s *)openinfo; + + buf->st_mode = (S_IFREG | S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + buf->st_size = opriv->file->inuse; + buf->st_blksize = UFSTEST_FS_BLOCKSIZE; + buf->st_blocks = (opriv->file->inuse + UFSTEST_FS_BLOCKSIZE - 1) / + UFSTEST_FS_BLOCKSIZE; + buf->st_atime = 0; + buf->st_mtime = 0; + buf->st_ctime = 0; + return OK; +} + +static int ufstest_opendir(FAR void *volinfo, FAR const char *relpath, + FAR void **dir) +{ + FAR struct ufstest_opendir_s *odir; + + if (!relpath || relpath[0] == '\0') + { + /* The path refers to the top level directory. */ + + odir = (FAR struct ufstest_opendir_s *) + malloc(sizeof(struct ufstest_opendir_s )); + if (odir == NULL) + { + return -ENOMEM; + } + + odir->index = 0; + *dir = odir; + return OK; + } + + return -ENOENT; +} + +static int ufstest_closedir(FAR void *volinfo, FAR void *dir) +{ + free(dir); + return OK; +} + +static int ufstest_readdir(FAR void *volinfo, FAR void *dir, + FAR struct dirent *entry) +{ + FAR struct ufstest_file_s *priv = (FAR struct ufstest_file_s *)volinfo; + FAR struct ufstest_opendir_s *odir = (FAR struct ufstest_opendir_s *)dir; + + if (odir->index < UFSTEST_NFILES) + { + memcpy(entry, &priv[odir->index].entry, sizeof(struct dirent)); + odir->index++; + return OK; + } + + return -ENOENT; +} + +static int ufstest_rewinddir(FAR void *volinfo, FAR void *dir) +{ + FAR struct ufstest_opendir_s *odir = (FAR struct ufstest_opendir_s *)dir; + + odir->index = 0; + return OK; +} + +static int ufstest_statfs(FAR void *volinfo, FAR struct statfs *buf) +{ + int inuse = 0; + int i; + + for (i = 0; i < UFSTEST_NFILES; i++) + { + inuse += (g_rootdir[i].inuse + UFSTEST_FS_BLOCKSIZE - 1) / + UFSTEST_FS_BLOCKSIZE; + } + + buf->f_type = USERFS_MAGIC; + buf->f_namelen = NAME_MAX; + buf->f_bsize = UFSTEST_FS_BLOCKSIZE; + buf->f_blocks = UFSTEST_FS_NBLOCKS; + buf->f_bfree = UFSTEST_FS_NBLOCKS - inuse; + buf->f_bavail = UFSTEST_FS_NBLOCKS - inuse; + buf->f_files = UFSTEST_NFILES; + buf->f_ffree = 0; + return OK; +} + +static int ufstest_unlink(FAR void *volinfo, FAR const char *relpath) +{ + return -ENOSYS; +} + +static int ufstest_mkdir(FAR void *volinfo, FAR const char *relpath, + mode_t mode) +{ + return -ENOSYS; +} + +static int ufstest_rmdir(FAR void *volinfo, FAR const char *relpath) +{ + return -ENOSYS; +} + +static int ufstest_rename(FAR void *volinfo, FAR const char *oldrelpath, + FAR const char *newrelpath) +{ + FAR struct ufstest_file_s *file; + + file = ufstest_findbyname(oldrelpath); + if (file != NULL) + { + strncpy(file->entry.d_name, newrelpath, NAME_MAX + 1); + return OK; + } + + return -ENOENT; +} + +static int ufstest_stat(FAR void *volinfo, FAR const char *relpath, + FAR struct stat *buf) +{ + FAR void *openinfo; + int ret; + + ret = ufstest_open(volinfo, relpath, O_RDWR, 0644, &openinfo); + if (ret >= 0) + { + ret = ufstest_fstat(volinfo, openinfo, buf); + (void)ufstest_close(volinfo, openinfo); + } + + return ret; +} + +static int ufstest_destroy(FAR void *volinfo) +{ + return OK; +} + +/**************************************************************************** + * ufstest_daemon + ****************************************************************************/ + +int ufstest_daemon(int argc, char *argv[]) +{ + int ret; + + ret = userfs_run(UFSTEST_MOUNTPOUNT, &g_ufstest_ops, g_rootdir, + UFSTEST_MXWRITE); + + fprintf(stderr, "ERROR: userfs_run() returned: %d\n", ret); + return EXIT_FAILURE; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * userfs_main + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int userfs_main(int argc, char *argv[]) +#endif +{ + FAR char *nshargv[1]; + int pid; + + /* Spawn the UserFS test daemon */ + + nshargv[0] = NULL; + pid = task_create("UserFS", CONFIG_EXAMPLES_USERFS_PRIORITY, + CONFIG_EXAMPLES_USERFS_STACKSIZE, ufstest_daemon, + (FAR char * const *)nshargv); + if (pid < 0) + { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +}