diff options
author | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2012-03-28 23:27:24 +0000 |
---|---|---|
committer | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2012-03-28 23:27:24 +0000 |
commit | 2ad4791dfa7d321661a0b75860a791bbb8df492a (patch) | |
tree | 4a3dd57f16aca637a553cc076b74af38dea9f9df | |
parent | da091bc45e9eb024a288a677fa47e918ed2b3704 (diff) | |
download | px4-firmware-2ad4791dfa7d321661a0b75860a791bbb8df492a.tar.gz px4-firmware-2ad4791dfa7d321661a0b75860a791bbb8df492a.tar.bz2 px4-firmware-2ad4791dfa7d321661a0b75860a791bbb8df492a.zip |
NFS update
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4538 7fd9a85b-ad96-42d3-883c-3090e2eb8679
-rw-r--r-- | apps/examples/nsh/nsh_main.c | 6 | ||||
-rw-r--r-- | nuttx/ChangeLog | 2 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_mount.h | 13 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_node.h | 5 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_socket.c | 3 | ||||
-rwxr-xr-x | nuttx/fs/nfs/nfs_util.c | 842 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_vfsops.c | 552 | ||||
-rw-r--r-- | nuttx/include/nuttx/fs/dirent.h | 10 |
8 files changed, 1173 insertions, 260 deletions
diff --git a/apps/examples/nsh/nsh_main.c b/apps/examples/nsh/nsh_main.c index 1d1592b4d..c5b671ab1 100644 --- a/apps/examples/nsh/nsh_main.c +++ b/apps/examples/nsh/nsh_main.c @@ -53,6 +53,12 @@ * Pre-processor Definitions ****************************************************************************/ +/* The NSH telnet console requires networking support (and TCP/IP) */ + +#ifndef CONFIG_NET +# undef CONFIG_NSH_TELNET +#endif + /**************************************************************************** * Private Types ****************************************************************************/ diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 45ce3331f..b7fca2d77 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -2602,3 +2602,5 @@ user NX server because of lack of use. * graphics/nxconsole: The NX text console is basically function (in multi- user NX mode only). + * arch/arm/src/stm32/stm32_i2c.c: Correct a bug in the STM32 I2C driver. The + behavior of I2C status bits seems to be different between F1 and F4. diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h index 107f4d966..9f6e9b340 100644 --- a/nuttx/fs/nfs/nfs_mount.h +++ b/nuttx/fs/nfs/nfs_mount.h @@ -51,10 +51,6 @@ * Pre-processor Definitions ****************************************************************************/ -#define NFSOP(nmp, op) (*nmp->nm_nfsops->nn_##op) -#define NFSHASOP(nmp, op) (nmp->nm_nfsops->nn_##op != NULL) -#define NFSDAT(nmp, nam) (nmp->nm_nfsops->nn_##nam) - /* Convert mount ptr to nfsmount ptr. */ #define VFSTONFS(mp) ((struct nfsmount *)((mp)->i_private)) @@ -72,9 +68,11 @@ struct nfsmount { int nm_flag; /* Flags for soft/hard... */ int nm_state; /* Internal state flags */ - struct inode *nm_mountp; /* Vfs structure for this filesystem */ - struct nfsnode *nfs_head; /* A list to all files opened on this mountpoint */ - bool nfs_mounted; /* true: The file system is ready */ + struct inode *nm_blkdriver; /* Vfs structure for this filesystem */ + struct nfsnode *nm_head; /* A list to all files opened on this mountpoint */ + bool nm_mounted; /* true: The file system is ready */ + sem_t nm_sem; /* Used to assume thread-safe access */ + nfstype nfsv3_type; /* File type */ int nm_numgrps; /* Max. size of groupslist */ nfsfh_t nm_fh; /* File handle of root dir */ int nm_fhsize; /* Size of root file handle */ @@ -101,6 +99,7 @@ struct nfsmount int nm_acregmin; /* Reg file attr cache min lifetime */ int nm_acregmax; /* Reg file attr cache max lifetime */ unsigned char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */ + uint8_t *nm_buffer; /* This is an allocated buffer to hold one sector*/ }; /**************************************************************************** diff --git a/nuttx/fs/nfs/nfs_node.h b/nuttx/fs/nfs/nfs_node.h index 88e4a9d4b..2cc1e14a7 100644 --- a/nuttx/fs/nfs/nfs_node.h +++ b/nuttx/fs/nfs/nfs_node.h @@ -111,15 +111,14 @@ struct sillyrename struct nfsnode { - struct nfsnode *nfs_next; /* Retained in a singly linked list filehandle/node tree. */ - bool nfs_open; /* true: The file is (still) open */ + struct nfsnode *n_next; /* Retained in a singly linked list filehandle/node tree. */ + bool n_open; /* true: The file is (still) open */ uint64_t n_size; /* Current size of file */ struct nfs_fattr n_fattr; /* nfs file attribute cache */ time_t n_attrstamp; /* Attr. cache timestamp */ struct timespec n_mtime; /* Prev modify time. */ time_t n_ctime; /* Prev create time. */ nfsfh_t *n_fhp; /* NFS File Handle */ - nfstype nfsv3_type; /* File type */ struct inode *n_inode; /* associated inode */ int n_error; /* Save write error value */ union diff --git a/nuttx/fs/nfs/nfs_socket.c b/nuttx/fs/nfs/nfs_socket.c index e821ce697..c1953369c 100644 --- a/nuttx/fs/nfs/nfs_socket.c +++ b/nuttx/fs/nfs/nfs_socket.c @@ -95,7 +95,6 @@ void nfs_init(void) rpcclnt_init(); } -/* XXXMARIUS: name collision */ int nfsx_connect(struct nfsmount *nmp) { struct rpcclnt *rpc; @@ -144,8 +143,6 @@ int nfsx_connect(struct nfsmount *nmp) /* NFS disconnect. Clean up and unlink. */ -/* XXXMARIUS: name collision */ - void nfsx_disconnect(struct nfsmount *nmp) { rpcclnt_disconnect(&nmp->nm_rpcclnt); diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c new file mode 100755 index 000000000..94e2cdca9 --- /dev/null +++ b/nuttx/fs/nfs/nfs_util.c @@ -0,0 +1,842 @@ +/**************************************************************************** + * fs/nfs/nfs_util.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> +#include <sys/types.h> + +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/fs/ioctl.h> +#include <nuttx/fs/dirent.h> + +#include "nfsmount.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nfs_checkentry + * + * Desciption: + * Check if the entry at offset is a directory or file path segment + * + ****************************************************************************/ + +static inline int nfs_checkentry(struct nfs_mountpt_s *rm, uint32_t offset, + const char *entryname, int entrylen, + struct nfs_dirinfo_s *dirinfo) +{ + char name[NAME_MAX+1]; + uint32_t linkoffset; + uint32_t next; + uint32_t info; + uint32_t size; + int ret; + + /* Parse the directory entry at this offset (which may be re-directed + * to some other entry if HARLINKED). + */ + + ret = nfs_parsedirentry(rm, offset, &linkoffset, &next, &info, &size); + if (ret < 0) + { + return ret; + } + + /* Now we are pointing to the real entry of interest. Is it a + * directory? Or a file? + */ + + if (IS_DIRECTORY(next) || IS_FILE(next)) + { + /* Get the name of the directory entry. */ + + ret = nfs_parsefilename(rm, offset, name); + if (ret < 0) + { + return ret; + } + + /* Then check if this the name segment we are looking for. The + * string comparison is awkward because there is no terminator + * on entryname (there is a terminator on name, however) + */ + + if (memcmp(entryname, name, entrylen) == 0 && + strlen(name) == entrylen) + { + /* Found it -- save the component info and return success */ + + if (IS_DIRECTORY(next)) + { + dirinfo->rd_dir.fr_firstoffset = info; + dirinfo->rd_dir.fr_curroffset = info; + dirinfo->rd_size = 0; + } + else + { + dirinfo->rd_dir.fr_curroffset = offset; + dirinfo->rd_size = size; + } + dirinfo->rd_next = next; + return OK; + } + } + + /* The entry is not a directory or it does not have the matching name */ + + return -ENOENT; +} + +/**************************************************************************** + * Name: nfs_devcacheread + * + * Desciption: + * Read the specified sector for specified offset into the sector cache. + * Return the index into the sector corresponding to the offset + * + ****************************************************************************/ + +int16_t nfs_devcacheread(struct nfs_mountpt_s *rm, uint32_t offset) +{ + uint32_t sector; + int ret; + + /* rm->rm_cachesector holds the current sector that is buffer in or referenced + * by rm->tm_buffer. If the requested sector is the same as this sector, + * then we do nothing. + */ + + sector = SEC_NSECTORS(rm, offset); + if (rm->rm_cachesector != sector) + { + /* Check the access mode */ + + if (rm->rm_xipbase) + { + /* In XIP mode, rf_buffer is just an offset pointer into the device + * address space. + */ + + rm->rm_buffer = rm->rm_xipbase + SEC_ALIGN(rm, offset); + } + else + { + /* In non-XIP mode, we will have to read the new sector.*/ + + ret = nfs_hwread(rm, rm->rm_buffer, sector, 1); + if (ret < 0) + { + return (int16_t)ret; + } + } + + /* Update the cached sector number */ + + rm->rm_cachesector = sector; + } + + /* Return the offset */ + + return offset & SEC_NDXMASK(rm); +} + +/**************************************************************************** + * Name: nfs_searchdir + * + * Desciption: + * This is part of the nfs_finddirentry log. Search the directory + * beginning at dirinfo->fr_firstoffset for entryname. + * + ****************************************************************************/ + +static inline int nfs_searchdir(struct nfs_mountpt_s *rm, + const char *entryname, int entrylen, + struct nfs_dirinfo_s *dirinfo) +{ + uint32_t offset; + uint32_t next; + int16_t ndx; + int ret; + + /* Then loop through the current directory until the directory + * with the matching name is found. Or until all of the entries + * the directory have been examined. + */ + + offset = dirinfo->rd_dir.fr_firstoffset; + do + { + /* Read the sector into memory (do this before calling + * nfs_checkentry() so we won't have to read the sector + * twice in the event that the offset refers to a hardlink). + */ + + ndx = nfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Because everything is chunked and aligned to 16-bit boundaries, + * we know that most the basic node info fits into the sector. + */ + + next = nfs_devread32(rm, ndx + ROMFS_FHDR_NEXT) & RFNEXT_OFFSETMASK; + + /* Check if the name this entry is a directory with the matching + * name + */ + + ret = nfs_checkentry(rm, offset, entryname, entrylen, dirinfo); + if (ret == OK) + { + /* Its a match! Return success */ + + return OK; + } + + /* No match... select the offset to the next entry */ + + offset = next; + } + while (next != 0); + + /* There is nothing in this directoy with that name */ + + return -ENOENT; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nfs_semtake + ****************************************************************************/ + +void nfs_semtake(struct nfsmount *nmp) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&nmp->nm_sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(*get_errno_ptr() == EINTR); + } +} + +/**************************************************************************** + * Name: nfs_semgive + ****************************************************************************/ + +void nfs_semgive(struct nfsmount *nmp) +{ + sem_post(&nmp->nm_sem); +} + +/**************************************************************************** + * Name: nfs_hwread + * + * Desciption: Read the specified sector into the sector buffer + * + ****************************************************************************/ + +int nfs_hwread(struct nfs_mountpt_s *rm, uint8_t *buffer, uint32_t sector, + unsigned int nsectors) +{ + int ret = -ENODEV; + + /* Check the access mode */ + + if (rm->rm_xipbase) + { + /* In XIP mode, we just copy the requested data */ + + memcpy(buffer, + rm->rm_xipbase + sector*rm->rm_hwsectorsize, + nsectors*rm->rm_hwsectorsize); + ret = OK; + } + else + { + /* In non-XIP mode, we have to read the data from the device */ + + struct inode *inode = rm->rm_blkdriver; + ssize_t nsectorsread; + + DEBUGASSERT(inode); + if (inode->u.i_bops && inode->u.i_bops->read) + { + nsectorsread = + inode->u.i_bops->read(inode, buffer, sector, nsectors); + + if (nsectorsread == (ssize_t)nsectors) + { + ret = OK; + } + else if (nsectorsread < 0) + { + ret = nsectorsread; + } + } + } + return ret; +} + +/**************************************************************************** + * Name: nfs_filecacheread + * + * Desciption: + * Read the specified sector into the sector cache + * + ****************************************************************************/ + +int nfs_filecacheread(struct nfs_mountpt_s *rm, struct nfs_file_s *rf, uint32_t sector) +{ + int ret; + + fvdbg("sector: %d cached: %d sectorsize: %d XIP base: %p buffer: %p\n", + sector, rf->rf_cachesector, rm->rm_hwsectorsize, + rm->rm_xipbase, rf->rf_buffer); + + /* rf->rf_cachesector holds the current sector that is buffer in or referenced + * by rf->rf_buffer. If the requested sector is the same as this sector, + * then we do nothing. + */ + + if (rf->rf_cachesector != sector) + { + /* Check the access mode */ + + if (rm->rm_xipbase) + { + /* In XIP mode, rf_buffer is just an offset pointer into the device + * address space. + */ + + rf->rf_buffer = rm->rm_xipbase + sector * rm->rm_hwsectorsize; + fvdbg("XIP buffer: %p\n", rf->rf_buffer); + } + else + { + /* In non-XIP mode, we will have to read the new sector.*/ + + fvdbg("Calling nfs_hwread\n"); + ret = nfs_hwread(rm, rf->rf_buffer, sector, 1); + if (ret < 0) + { + fdbg("nfs_hwread failed: %d\n", ret); + return ret; + } + } + + /* Update the cached sector number */ + + rf->rf_cachesector = sector; + } + + return OK; +} + +/**************************************************************************** + * Name: nfs_hwconfigure + * + * Desciption: + * This function is called as part of the ROMFS mount operation It + * configures the ROMFS filestem for use on this block driver. This includes + * the accounting for the geometry of the device, setting up any XIP modes + * of operation, and/or allocating any cache buffers. + * + ****************************************************************************/ + +int nfs_hwconfigure(struct nfs_mountpt_s *rm) +{ + struct inode *inode = rm->rm_blkdriver; + struct geometry geo; + int ret; + + /* Get the underlying device geometry */ + +#ifdef CONFIG_DEBUG + if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry) + { + return -ENODEV; + } +#endif + + ret = inode->u.i_bops->geometry(inode, &geo); + if (ret != OK) + { + return ret; + } + + if (!geo.geo_available) + { + return -EBUSY; + } + + /* Save that information in the mount structure */ + + rm->rm_hwsectorsize = geo.geo_sectorsize; + rm->rm_hwnsectors = geo.geo_nsectors; + + /* Determine if block driver supports the XIP mode of operation */ + + rm->rm_cachesector = (uint32_t)-1; + + if (inode->u.i_bops->ioctl) + { + ret = inode->u.i_bops->ioctl(inode, BIOC_XIPBASE, + (unsigned long)&rm->rm_xipbase); + if (ret == OK && rm->rm_xipbase) + { + /* Yes.. Then we will directly access the media (vs. + * copying into an allocated sector buffer. + */ + + rm->rm_buffer = rm->rm_xipbase; + rm->rm_cachesector = 0; + return OK; + } + } + + /* Allocate the device cache buffer for normal sector accesses */ + + rm->rm_buffer = (uint8_t*)malloc(rm->rm_hwsectorsize); + if (!rm->rm_buffer) + { + return -ENOMEM; + } + + return OK; +} + +/**************************************************************************** + * Name: nfs_ffileconfigure + * + * Desciption: + * This function is called as part of the ROMFS file open operation It + * sets up the file structure to handle buffer appropriately, depending + * upon XIP mode or not. + * + ****************************************************************************/ + +int nfs_fileconfigure(struct nfs_mountpt_s *rm, struct nfs_file_s *rf) +{ + /* Check if XIP access mode is supported. If so, then we do not need + * to allocate anything. + */ + + if (rm->rm_xipbase) + { + /* We'll put a valid address in rf_buffer just in case. */ + + rf->rf_cachesector = 0; + rf->rf_buffer = rm->rm_xipbase; + } + else + { + /* Nothing in the cache buffer */ + + rf->rf_cachesector = (uint32_t)-1; + + /* Create a file buffer to support partial sector accesses */ + + rf->rf_buffer = (uint8_t*)malloc(rm->rm_hwsectorsize); + if (!rf->rf_buffer) + { + return -ENOMEM; + } + } + return OK; +} + +/**************************************************************************** + * Name: nfs_checkmount + * + * Desciption: Check if the mountpoint is still valid. + * + * The caller should hold the mountpoint semaphore + * + ****************************************************************************/ + +int nfs_checkmount(struct nfsmount *nmp) +{ + struct nfsnode *file; + struct inode *inode; + struct geometry geo; + int ret; + + /* If the fs_mounted flag is false, then we have already handled the loss + * of the mount. + */ + + DEBUGASSERT(nmp && nmp->nm_blkdriver); + if (nmp->mm_mounted) + { + /* We still think the mount is healthy. Check an see if this is + * still the case + */ + + inode = nmp->nm_blkdriver; + if (inode->u.i_bops && inode->u.i_bops->geometry) + { + ret = inode->u.i_bops->geometry(inode, &geo); + if (ret == OK && geo.geo_available && !geo.geo_mediachanged) + { + return OK; + } + } + + /* If we get here, the mount is NOT healthy */ + + nmp->nm_mounted = false; + + /* Make sure that this is flagged in every opened file */ + + for (file = nmp->nm_head; file; file = file->n_next) + { + file->n_open = false; + } + } + return -ENODEV; +} + +/**************************************************************************** + * Name: nfs_finddirentry + * + * Desciption: + * Given a path to something that may or may not be in the file system, + * return the directory entry of the item. + * + ****************************************************************************/ + +int nfs_finddirentry(struct nfs_mountpt_s *rm, struct nfs_dirinfo_s *dirinfo, + const char *path) +{ + const char *entryname; + const char *terminator; + int entrylen; + int ret; + + /* Start with the first element after the root directory */ + + dirinfo->rd_dir.fr_firstoffset = rm->rm_rootoffset; + dirinfo->rd_dir.fr_curroffset = rm->rm_rootoffset; + dirinfo->rd_next = RFNEXT_DIRECTORY; + dirinfo->rd_size = 0; + + /* The root directory is a special case */ + + if (!path || path[0] == '\0') + { + return OK; + } + + /* Then loop for each directory/file component in the full path */ + + entryname = path; + terminator = NULL; + + for (;;) + { + /* Find the start of the next path component */ + + while (*entryname == '/') entryname++; + + /* Find the end of the next path component */ + + terminator = strchr(entryname, '/'); + if (!terminator) + { + entrylen = strlen(entryname); + } + else + { + entrylen = terminator - entryname; + } + + /* Long path segment names will be truncated to NAME_MAX */ + + if (entrylen > NAME_MAX) + { + entrylen = NAME_MAX; + } + + /* Then find the entry in the current directory with the + * matching name. + */ + + ret = nfs_searchdir(rm, entryname, entrylen, dirinfo); + if (ret < 0) + { + return ret; + } + + /* Was that the last path component? */ + + if (!terminator) + { + /* Yes.. return success */ + + return OK; + } + + /* No... If that was not the last path component, then it had + * better have been a directory + */ + + if (!IS_DIRECTORY(dirinfo->rd_next)) + { + return -ENOTDIR; + } + + /* Setup to search the next directory for the next component + * of the path + */ + + entryname = terminator; + } + + return ERROR; /* Won't get here */ +} + +/**************************************************************************** + * Name: nfs_parsedirentry + * + * Desciption: + * Return the directory entry at this offset. If rf is NULL, then the + * mount device resources are used. Otherwise, file resources are used. + * + ****************************************************************************/ + +int nfs_parsedirentry(struct nfs_mountpt_s *rm, uint32_t offset, uint32_t *poffset, + uint32_t *pnext, uint32_t *pinfo, uint32_t *psize) +{ + uint32_t save; + uint32_t next; + int16_t ndx; + int ret; + + /* Read the sector into memory */ + + ndx = nfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Yes.. Save the first 'next' value. That has the offset needed to + * traverse the parent directory. But we may need to change the type + * after we follow the hard links. + */ + + save = nfs_devread32(rm, ndx + ROMFS_FHDR_NEXT); + + /* Traverse hardlinks as necesssary to get to the real file header */ + + ret = nfs_followhardlinks(rm, offset, poffset); + if (ret < 0) + { + return ret; + } + + /* Because everything is chunked and aligned to 16-bit boundaries, + * we know that most the basic node info fits into the sector. The + * associated name may not, however. + */ + + next = nfs_devread32(rm, ndx + ROMFS_FHDR_NEXT); + *pnext = (save & RFNEXT_OFFSETMASK) | (next & RFNEXT_ALLMODEMASK); + *pinfo = nfs_devread32(rm, ndx + ROMFS_FHDR_INFO); + *psize = nfs_devread32(rm, ndx + ROMFS_FHDR_SIZE); + return OK; +} + +/**************************************************************************** + * Name: nfs_parsefilename + * + * Desciption: + * Return the filename from directory entry at this offset + * + ****************************************************************************/ + +int nfs_parsefilename(struct nfs_mountpt_s *rm, uint32_t offset, char *pname) +{ + int16_t ndx; + uint16_t namelen; + uint16_t chunklen; + bool done; + + /* Loop until the whole name is obtained or until NAME_MAX characters + * of the name have been parsed. + */ + + offset += ROMFS_FHDR_NAME; + for (namelen = 0, done = false; namelen < NAME_MAX && !done;) + { + /* Read the sector into memory */ + + ndx = nfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Is the name terminated in this 16-byte block */ + + if (rm->rm_buffer[ndx + 15] == '\0') + { + /* Yes.. then this chunk is less than 16 */ + + chunklen = strlen((char*)&rm->rm_buffer[ndx]); + done = true; + } + else + { + /* No.. then this chunk is 16 bytes in length */ + + chunklen = 16; + } + + /* Check if we would exceed the NAME_MAX */ + + if (namelen + chunklen > NAME_MAX) + { + chunklen = NAME_MAX - namelen; + done = true; + } + + /* Copy the chunk */ + + memcpy(&pname[namelen], &rm->rm_buffer[ndx], chunklen); + namelen += chunklen; + } + + /* Terminate the name (NAME_MAX+1 chars total) and return success */ + + pname[namelen] = '\0'; + return OK; +} + +/**************************************************************************** + * Name: nfs_datastart + * + * Desciption: + * Given the offset to a file header, return the offset to the start of + * the file data + * + ****************************************************************************/ + +int nfs_datastart(struct nfs_mountpt_s *rm, uint32_t offset, uint32_t *start) +{ + int16_t ndx; + int ret; + + /* Traverse hardlinks as necesssary to get to the real file header */ + + ret = nfs_followhardlinks(rm, offset, &offset); + if (ret < 0) + { + return ret; + } + + /* Loop until the header size is obtained. */ + + offset += ROMFS_FHDR_NAME; + for (;;) + { + /* Read the sector into memory */ + + ndx = nfs_devcacheread(rm, offset); + if (ndx < 0) + { + return ndx; + } + + /* Get the offset to the next chunk */ + + offset += 16; + if (offset >= rm->rm_volsize) + { + return -EIO; + } + + /* Is the name terminated in this 16-byte block */ + + if (rm->rm_buffer[ndx + 15] == '\0') + { + /* Yes.. then the data starts at the next chunk */ + + *start = offset; + return OK; + } + } + + return -EINVAL; /* Won't get here */ +} + diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c index 3a5e41b24..c2f390b2e 100644 --- a/nuttx/fs/nfs/nfs_vfsops.c +++ b/nuttx/fs/nfs/nfs_vfsops.c @@ -44,18 +44,6 @@ * Included Files ****************************************************************************/ -#include <sys/param.h> -#include <sys/conf.h> -#include <sys/ioctl.h> -#include <sys/signal.h> -#include <sys/proc.h> -#include <sys/namei.h> -#include <sys/vnode.h> -#include <sys/kernel.h> -#include <sys/mount.h> -#include <sys/buf.h> -#include <sys/mbuf.h> -#include <sys/dirent.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/systm.h> @@ -63,6 +51,7 @@ #include <sys/statfs> #include <queue.h> +#include <nuttx/fs/dirent.h> #include <nuttx/fs/fs.h> #include <net/if.h> @@ -656,8 +645,7 @@ nfs_renameit(struct vnode *sdvp, struct componentname *scnp, int nfs_renamerpc(struct vnode *fdvp, char *fnameptr, int fnamelen, - struct vnode *tdvp, char *tnameptr, int tnamelen, - struct ucred *cred, struct proc *proc) + struct vnode *tdvp, char *tnameptr, int tnamelen) { struct nfsm_info info; u_int32_t *tl; @@ -677,15 +665,12 @@ nfs_renamerpc(struct vnode *fdvp, char *fnameptr, int fnamelen, nfsm_fhtom(&info, tdvp, info.nmi_v3); nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); - info.nmi_procp = proc; - info.nmi_cred = cred; error = nfs_request(fdvp, NFSPROC_RENAME, &info); if (info.nmi_v3) { nfsm_wcc_data(fdvp, fwccflag); nfsm_wcc_data(tdvp, twccflag); } - m_freem(info.nmi_mrep); nfsmout: VTONFS(fdvp)->n_flag |= NMODIFIED; @@ -699,73 +684,75 @@ nfsmout: /* nfs make dir call */ -int nfs_mkdir(void *v) +int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) { - struct vop_mkdir_args *ap = v; struct vnode *dvp = ap->a_dvp; - struct vattr *vap = ap->a_vap; + struct nfsv3_sattr *vap; + struct nfsmount *nmp; + struct nfsnode *np; struct componentname *cnp = ap->a_cnp; - struct nfsv2_sattr *sp; - struct nfsm_info info; - u_int32_t *tl; - int32_t t1; + struct nfsv3_sattr *sp; + int info_v3; + //struct nfsm_info info; + //u_int32_t *tl; + //int32_t t1; int len; struct nfsnode *np = NULL; - struct vnode *newvp = NULL; - caddr_t cp2; + struct file *newfilep = NULL; + //caddr_t cp2; int error = 0, wccflag = NFSV3_WCCRATTR; int gotvp = 0; - info.nmi_v3 = NFS_ISV3(dvp); + /* Sanity checks */ - len = cnp->cn_namelen; + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + nmp = mountpt->i_private; + np = nmp->nm_head; + vap = np->n_fattr; + info_v3 = (nmp->nm_flag & NFSMNT_NFSV3); + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != 0) + { + goto errout_with_semaphore; + } + nfsstats.rpccnt[NFSPROC_MKDIR]++; - info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) + - NFSX_UNSIGNED + nfsm_rndup(len) + - NFSX_SATTR(info.nmi_v3)); - nfsm_fhtom(&info, dvp, info.nmi_v3); - nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); - if (info.nmi_v3) + if (info_v3) { nfsm_v3attrbuild(&info.nmi_mb, vap, 0); } else { - sp = nfsm_build(&info.nmi_mb, NFSX_V2SATTR); - sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); + sp->sa_modetrue = nfs_true; + sp->sa_mode = txdr_unsigned(vap->sa_mode); sp->sa_uid = nfs_xdrneg1; sp->sa_gid = nfs_xdrneg1; sp->sa_size = nfs_xdrneg1; - txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); - txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); + sp->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); + sp->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); + txdr_nfsv3time(&vap->sa_atime, &sp->sa_atime); + txdr_nfsv3time(&vap->sa_mtime, &sp->sa_mtime); } - info.nmi_procp = cnp->cn_proc; - info.nmi_cred = cnp->cn_cred; error = nfs_request(dvp, NFSPROC_MKDIR, &info); if (!error) nfsm_mtofh(dvp, newvp, info.nmi_v3, gotvp); if (info.nmi_v3) nfsm_wcc_data(dvp, wccflag); - m_freem(info.nmi_mrep); nfsmout: VTONFS(dvp)->n_flag |= NMODIFIED; if (!wccflag) NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp)); - if (error == 0 && newvp == NULL) - { - error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, - cnp->cn_proc, &np); - if (!error) - { - newvp = NFSTOV(np); - if (newvp->v_type != VDIR) - error = EEXIST; - } - } if (error) { if (newvp) @@ -781,6 +768,10 @@ nfsmout: pool_put(&namei_pool, cnp->cn_pnbuf); vrele(dvp); return (error); + + errout_with_semaphore: + nfs_semgive(nmp); + return error; } /* nfs remove directory call */ @@ -854,128 +845,102 @@ nfsmout: /* nfs readdir call */ -int nfs_readdir(void *v) +int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) { - struct vop_readdir_args *ap = v; - struct vnode *vp = ap->a_vp; - struct nfsnode *np = VTONFS(vp); - struct uio *uio = ap->a_uio; + //struct nfsnode *np = VTONFS(vp); int tresid, error = 0; - struct vattr vattr; - u_long *cookies = NULL; + unsigned long *cookies = NULL; int ncookies = 0, cnt; - u_int64_t newoff = uio->uio_offset; - struct nfsmount *nmp = VFSTONFS(vp->v_mount); - struct uio readdir_uio; - struct iovec readdir_iovec; - struct proc *p = uio->uio_procp; - int done = 0, eof = 0; - struct ucred *cred = ap->a_cred; - void *data; - - if (vp->v_type != VDIR) + struct nfsmount *nmp; + int eof = 0; + uint64_t newoff; + + fvdbg("Entry\n"); + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + nmp = mountpt->i_private; + + /* Make sure that the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != 0) + { + fdbg("romfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + + if (nmp->nfsv3_type != NFDIR) return (EPERM); +#ifdef 0 /* First, check for hit on the EOF offset cache */ - if (np->n_direofoffset != 0 && uio->uio_offset == np->n_direofoffset) + if (np->n_direofoffset != 0) { - if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && - timespeccmp(&np->n_mtime, &vattr.va_mtime, ==)) - { - nfsstats.direofcache_hits++; - *ap->a_eofflag = 1; - return (0); - } + nfsstats.direofcache_hits++; + filep->f_oflags = 1; + return (0); } +#endif if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3) - (void)nfs_fsinfo(nmp); - + { + (void)nfs_fsinfo(nmp); + } cnt = 5; - data = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK); do { struct nfs_dirent *ndp = data; - - readdir_iovec.iov_len = NFS_DIRBLKSIZ; - readdir_iovec.iov_base = data; - readdir_uio.uio_offset = newoff; - readdir_uio.uio_iov = &readdir_iovec; - readdir_uio.uio_iovcnt = 1; - readdir_uio.uio_segflg = UIO_SYSSPACE; - readdir_uio.uio_rw = UIO_READ; - readdir_uio.uio_resid = NFS_DIRBLKSIZ; - readdir_uio.uio_procp = curproc; - - error = nfs_readdirrpc(vp, &readdir_uio, cred, &eof); + dir->nfs->cookie[0] = ndp->cookie[0]; + dir->nfs->cookie[1] = ndp->cookie[1]; + dir->fd_dir = ndp->dirent; + + error = nfs_readdirrpc(vp, &eof); if (error == NFSERR_BAD_COOKIE) error = EINVAL; - while (error == 0 && - (ap->a_cookies == NULL || ncookies != 0) && - ndp < (struct nfs_dirent *)readdir_iovec.iov_base) + while (error == 0 &&(ncookies != 0)) { - struct dirent *dp = &ndp->dirent; + struct dirent *dp = &dir->fd_dir; int reclen = dp->d_reclen; dp->d_reclen -= NFS_DIRENT_OVERHEAD; - if (uio->uio_resid < dp->d_reclen) - { - eof = 0; - done = 1; - break; - } - - error = uiomove((caddr_t) dp, dp->d_reclen, uio); - if (error) - break; - - newoff = fxdr_hyper(&ndp->cookie[0]); - if (ap->a_cookies != NULL) - { - *cookies = newoff; - cookies++; - ncookies--; - } + newoff = fxdr_hyper(&dir->nfs->cookie[0]); + *cookies = newoff; + cookies++; + ncookies--; + - ndp = (struct nfs_dirent *)((u_int8_t *) ndp + reclen); + ndp = (struct nfs_dirent *)((uint8_t *) ndp + reclen); + dir->nfs->cookie[0] = ndp->cookie[0]; + dir->nfs->cookie[1] = ndp->cookie[1]; + dir->fd_dir = ndp->dirent; } } - while (!error && !done && !eof && cnt--); + while (!error && !eof && cnt--); - free(data, M_TEMP); data = NULL; - if (ap->a_cookies) - { - if (error) - { - free(*ap->a_cookies, M_TEMP); - *ap->a_cookies = NULL; - *ap->a_ncookies = 0; - } - else - { - *ap->a_ncookies -= ncookies; - } - } - - if (!error) - uio->uio_offset = newoff; - - if (!error && (eof || uio->uio_resid == tresid)) + if (!error && eof) { nfsstats.direofcache_misses++; - *ap->a_eofflag = 1; + filep->f_oflags = 1; + nfs_semgive(nmp); return (0); } - *ap->a_eofflag = 0; + filep->f_oflags = 0; + nfs_semgive(nmp); return (error); } @@ -983,34 +948,25 @@ int nfs_readdir(void *v) /* Readdir rpc call. */ -int -nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, - int *end_of_directory) +int nfs_readdirrpc(struct vnode *vp, int *end_of_directory) { int len, left; struct nfs_dirent *ndp = NULL; struct dirent *dp = NULL; - struct nfsm_info info; - u_int32_t *tl; - caddr_t cp; + //struct nfsm_info info; + //u_int32_t *tl; + /*caddr_t cp; int32_t t1; - caddr_t cp2; + caddr_t cp2;*/ nfsuint64 cookie; struct nfsmount *nmp = VFSTONFS(vp->v_mount); struct nfsnode *dnp = VTONFS(vp); - u_quad_t fileno; + uint64_t fileno; int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; int attrflag; info.nmi_v3 = NFS_ISV3(vp); -#ifdef DIAGNOSTIC - if (uiop->uio_iovcnt != 1 || (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) - panic("nfs readdirrpc bad uio"); -#endif - - txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]); - /* Loop around doing readdir rpc's of size nm_readdirsize * truncated to a multiple of NFS_READDIRBLKSIZ. * The stopping criteria is EOF or buffer full. @@ -1019,10 +975,7 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, while (more_dirs && bigenough) { nfsstats.rpccnt[NFSPROC_READDIR]++; - info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) - + NFSX_READDIR(info.nmi_v3)); - nfsm_fhtom(&info, vp, info.nmi_v3); - if (info.nmi_v3) + if (info.nmi_v3) { { tl = nfsm_build(&info.nmi_mb, 5 * NFSX_UNSIGNED); *tl++ = cookie.nfsuquad[0]; @@ -1045,15 +998,12 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, } *tl = txdr_unsigned(nmp->nm_readdirsize); - info.nmi_procp = uiop->uio_procp; - info.nmi_cred = cred; - error = nfs_request(vp, NFSPROC_READDIR, &info); + error = nfs_request(nmp, NFSPROC_READDIR, &info); if (info.nmi_v3) nfsm_postop_attr(vp, attrflag); if (error) { - m_freem(info.nmi_mrep); goto nfsmout; } @@ -1159,7 +1109,6 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); more_dirs = (fxdr_unsigned(int, *tl) == 0); } - m_freem(info.nmi_mrep); } /* Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ @@ -1170,9 +1119,6 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, { left = NFS_READDIRBLKSIZ - blksiz; dp->d_reclen += left; - uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + left; - uiop->uio_iov->iov_len -= left; - uiop->uio_resid -= left; } /* We are now either at the end of the directory or have filled the @@ -1185,27 +1131,46 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, if (end_of_directory) *end_of_directory = 1; } - else - { - if (uiop->uio_resid > 0) - printf("EEK! readdirrpc resid > 0\n"); - } nfsmout: return (error); } -/* nfs statfs call */ +/**************************************************************************** + * Name: nfs_statfs + * + * Description: Return filesystem statistics + * + ****************************************************************************/ -int nfs_statfs(struct inode *mp, struct statfs *sbp) +int nfs_statfs(struct inode *mountpt, struct statfs *sbp) { struct nfs_statfs *sfp = NULL; - struct nfsmount *nmp = VFSTONFS(mp); + struct nfsmount *nmp; int error = 0; uint64_t tquad; void *datareply; - int info_v3 = (nmp->nm_flag & NFSMNT_NFSV3); + int info_v3; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + /* Get the mountpoint private data from the inode structure */ + + nmp = mountpt->i_private; + info_v3 = (nmp->nm_flag & NFSMNT_NFSV3); + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error < 0) + { + fdbg("romfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + /* Fill in the statfs info */ memset(sbp, 0, sizeof(struct statfs)); @@ -1217,7 +1182,7 @@ int nfs_statfs(struct inode *mp, struct statfs *sbp) error = nfs_request(nmp, NFSPROC_FSSTAT, datareply); if (error) - goto nfsmout; + goto errout_with_semaphore; sfp = (struct nfs_statfs *)datareply; if (info_v3) { @@ -1244,7 +1209,9 @@ int nfs_statfs(struct inode *mp, struct statfs *sbp) sbp->f_files = 0; sbp->f_ffree = 0; } -nfsmout: + +errout_with_semaphore: + nfs_semgive(nmp); return (error); } @@ -1459,26 +1426,25 @@ void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) printf("nfs_args: retrying connect\n"); } } - } -/* VFS Operations. +/**************************************************************************** + * Name: nfs_mount * - * mount system call - * It seems a bit dumb to copyinstr() the host and path here and then - * bcopy() them in mountnfs(), but I wanted to detect errors before - * doing the sockargs() call because sockargs() allocates an mbuf and - * an error after that means that I have to release the mbuf. - */ + * Description: This implements a portion of the mount operation. This + * function allocates and initializes the mountpoint private data and + * binds the blockdriver inode to the filesystem private data. The final + * binding of the private data (containing the blockdriver) to the + * mountpoint is performed by mount(). + * + ****************************************************************************/ -/* ARGSUSED */ -int nfs_mount(struct inode *mp, const char *path, void *data) +int nfs_mount(struct inode *blkdriver, const char *path, void *data, void **handle) { int error; struct nfs_args args; struct sockaddr *nam; char pth[MNAMELEN]; - size_t len; nfsfh_t nfh[NFSX_V3FHMAX]; bcopy(data, &args, sizeof(args.version)); @@ -1498,9 +1464,9 @@ int nfs_mount(struct inode *mp, const char *path, void *data) if ((args.flags & (NFSMNT_NFSV3 | NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS) return (EINVAL); - if (mp->mnt_flag & MNT_UPDATE) + if (blkdriver->mnt_flag & MNT_UPDATE) { - struct nfsmount *nmp = VFSTONFS(mp); + struct nfsmount *nmp = VFSTONFS(blkdriver); if (nmp == NULL) return (EIO); @@ -1519,20 +1485,20 @@ int nfs_mount(struct inode *mp, const char *path, void *data) bcopy(path, pth, MNAMELEN - 1); bcopy(args.addr, nam, sizeof(args.addr)); args.fh = nfh; - error = mountnfs(&args, mp, nam); + error = mountnfs(&args, blkdriver, nam); return (error); } /* Common code for nfs_mount */ -int mountnfs(struct nfs_args *argp, struct inode *mp, struct sockaddr *nam) +int mountnfs(struct nfs_args *argp, struct inode *blkdriver, struct sockaddr *nam, void **handle) { struct nfsmount *nmp; int error; - if (mp->mnt_flag & MNT_UPDATE) + if (blkdriver->mnt_flag & MNT_UPDATE) { - nmp = VFSTONFS(mp); + nmp = VFSTONFS(blkdriver); /* update paths, file handles, etc, here XXX */ @@ -1540,87 +1506,179 @@ int mountnfs(struct nfs_args *argp, struct inode *mp, struct sockaddr *nam) } else { + /* Open the block driver */ + + if (!blkdriver || !blkdriver->u.i_bops) + { + fdbg("No block driver/ops\n"); + return -ENODEV; + } + + if (blkdriver->u.i_bops->open && + blkdriver->u.i_bops->open(blkdriver) != OK) + { + fdbg("No open method\n"); + return -ENODEV; + } + + /* Create an instance of the mountpt state structure */ + nmp = (struct nfsmount *)zalloc(sizeof(struct nfmount)); if (!nmp) { + fdbg("Failed to allocate mountpoint structure\n"); return -ENOMEM; } - mp->i_private = &nmp; - } - -//vfs_getnewfsid(mp); - nmp->nm_mountp = mp; - nmp->nfs_mounted = true; - nmp->nm_timeo = NFS_TIMEO; - nmp->nm_retry = NFS_RETRANS; - nmp->nm_wsize = NFS_WSIZE; - nmp->nm_rsize = NFS_RSIZE; - nmp->nm_readdirsize = NFS_READDIRSIZE; - nmp->nm_numgrps = NFS_MAXGRPS; - nmp->nm_readahead = NFS_DEFRAHEAD; - nmp->nm_fhsize = argp->fhsize; - nmp->nm_acregmin = NFS_MINATTRTIMO; - nmp->nm_acregmax = NFS_MAXATTRTIMO; - nmp->nm_acdirmin = NFS_MINATTRTIMO; - nmp->nm_acdirmax = NFS_MAXATTRTIMO; - memmove(nmp->nm_fh, argp->fh, argp->fhsize); -//strncpy(&mp->mnt_stat.f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN); -//memmove(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); -//memmove(pth, mp->mnt_stat.f_mntonname, MNAMELEN); -//memmove(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp)); - nmp->nm_nam = nam; - nfs_decode_args(nmp, argp); - - /* Set up the sockets and per-host congestion */ - - nmp->nm_sotype = argp->sotype; - nmp->nm_soproto = argp->proto; - - /* For Connection based sockets (TCP,...) defer the connect until - * the first request, in case the server is not responding. - */ - - if (nmp->nm_sotype == SOCK_DGRAM && (error = nfs_connect(nmp))) - goto bad; + + /* Initialize the allocated mountpt state structure. The filesystem is + * responsible for one reference ont the blkdriver inode and does not + * have to addref() here (but does have to release in ubind(). + */ - nfs_init(); + sem_init(&rm->rm_sem, 0, 0); /* Initialize the semaphore that controls access */ + + //vfs_getnewfsid(mp); + nmp->nm_blkdriver = blkdriver; /* Save the block driver reference */ + nmp->nm_timeo = NFS_TIMEO; + nmp->nm_retry = NFS_RETRANS; + nmp->nm_wsize = NFS_WSIZE; + nmp->nm_rsize = NFS_RSIZE; + nmp->nm_readdirsize = NFS_READDIRSIZE; + nmp->nm_numgrps = NFS_MAXGRPS; + nmp->nm_readahead = NFS_DEFRAHEAD; + nmp->nm_fhsize = argp->fhsize; + nmp->nm_acregmin = NFS_MINATTRTIMO; + nmp->nm_acregmax = NFS_MAXATTRTIMO; + nmp->nm_acdirmin = NFS_MINATTRTIMO; + nmp->nm_acdirmax = NFS_MAXATTRTIMO; + memmove(nmp->nm_fh, argp->fh, argp->fhsize); + //strncpy(&mp->mnt_stat.f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN); + //memmove(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); + //memmove(pth, mp->mnt_stat.f_mntonname, MNAMELEN); + //memmove(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp)); + nmp->nm_nam = nam; + nfs_decode_args(nmp, argp); + + /* Set up the sockets and per-host congestion */ + + nmp->nm_sotype = argp->sotype; + nmp->nm_soproto = argp->proto; + + /* For Connection based sockets (TCP,...) defer the connect until + * the first request, in case the server is not responding. + */ - return (0); + if (nmp->nm_sotype == SOCK_DGRAM && (error = nfs_connect(nmp))) + goto bad; + + /* Mounted! */ + nmp->nfs_mounted = true; + nfs_init(); + *handle = mp->i_private = &nmp; + nfs_semgive(nmp); + + return (0); + } bad: nfs_disconnect(nmp); + sem_destroy(&nmp->nm_sem); kfree(nmp); return (error); } -/* unmount system call */ +/**************************************************************************** + * Name: nfs_unmount + * + * Description: This implements the filesystem portion of the umount + * operation. + * + ****************************************************************************/ -int nfs_unmount(struct inode *mp, int mntflags) // falta +int nfs_unmount(struct inode *blkdriver, void *handle) { - struct nfsmount *nmp; - int error, flags; + struct nfsmount *nmp = (struct nfsmount*) handle ; + int error; - nmp = VFSTONFS(mp); - flags = 0; + fvdbg("Entry\n"); + + if (!nmp) + { + return -EINVAL; + } - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; + nfs_semtake(nmp) + if (nmp->nm_head) + { + /* We cannot unmount now.. there are open files */ - error = vflush(mp, NULL, flags); // ? - if (error) - return (error); + error = -EBUSY; + } + else + { + /* Unmount ... close the block driver */ - nfs_disconnect(nmp); - kfree(nmp); + if (nmp->nm_blkdriver) + { + struct inode *inode = nmp->nm_blkdriver; + if (inode) + { + if (inode->u.i_bops && inode->u.i_bops->close) + { + (void)inode->u.i_bops->close(inode); + } + + /* We hold a reference to the block driver but should + * not but mucking with inodes in this context. So, we will just return + * our contained reference to the block driver inode and let the umount + * logic dispose of it. + */ + + if (blkdriver) + { + *blkdriver = inode; + } + } + } + + /* Release the mountpoint private data */ + + if (nmp->nm_buffer) + { + kfree(nmp->nm_buffer); + } + + nfs_disconnect(nmp); + sem_destroy(&rm->rm_sem); + kfree(nmp); + + return (0); + } + + nfs_semgive(nmp) return (0); } /* Flush out the buffer cache */ -int nfs_sync(struct file *filep) +int nfs_sync(struct file *filep) //falta { - struct inode *in = filep->f_inode; + struct inode *inode; + struct nfsmount *nmp; + struct nfsnode *np; int error, allerror = 0; + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + np = filep->f_priv; + inode = filep->f_inode; + nmp = inode->i_private; + + DEBUGASSERT(nmp != NULL); + /* Force stale buffer cache information to be flushed. */ loop: @@ -1630,7 +1688,7 @@ loop: * associated with this mount point, start over. */ - if (in->nm_mountp != mp) + if (in->nm_blkdriver != mp) goto loop; if (VOP_ISLOCKED(vp) || LIST_FIRST(&vp->v_dirtyblkhd) == NULL) continue; diff --git a/nuttx/include/nuttx/fs/dirent.h b/nuttx/include/nuttx/fs/dirent.h index 31f27957c..fe3c8e5e9 100644 --- a/nuttx/include/nuttx/fs/dirent.h +++ b/nuttx/include/nuttx/fs/dirent.h @@ -116,6 +116,13 @@ struct fs_nxffsdir_s off_t nx_offset; /* Offset to the next inode */ }; #endif + +#ifdef CONFIG_NFS +struct fs_nfsdir_s +{ + uint32_t cookie[2]; +} +#endif #endif /* CONFIG_DISABLE_MOUNTPOINT */ struct fs_dirent_s @@ -167,6 +174,9 @@ struct fs_dirent_s #ifdef CONFIG_FS_NXFFS struct fs_nxffsdir_s nxffs; #endif +#ifdef CONFIG_NFS + struct fs_nfsdir_s nfs; +#endif #endif /* !CONFIG_DISABLE_MOUNTPOINT */ } u; |