summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-04-16 23:01:21 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-04-16 23:01:21 +0000
commit285afeb744b1f37187c2390e61ef598d7dcec3b4 (patch)
treeeb553133030277d62e8977a3536a5f1743a52205
parent97aec5202649d84fb92278a5ff5c2a6e53adecb6 (diff)
downloadnuttx-285afeb744b1f37187c2390e61ef598d7dcec3b4.tar.gz
nuttx-285afeb744b1f37187c2390e61ef598d7dcec3b4.tar.bz2
nuttx-285afeb744b1f37187c2390e61ef598d7dcec3b4.zip
NFS client FS update
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4622 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/fs/nfs/Make.defs2
-rw-r--r--nuttx/fs/nfs/nfs.h113
-rw-r--r--nuttx/fs/nfs/nfs_mount.h21
-rw-r--r--nuttx/fs/nfs/nfs_proto.h163
-rw-r--r--nuttx/fs/nfs/nfs_socket.c2
-rwxr-xr-xnuttx/fs/nfs/nfs_util.c693
-rw-r--r--nuttx/fs/nfs/nfs_vfsops.c1354
-rw-r--r--nuttx/include/nuttx/fs/dirent.h5
8 files changed, 871 insertions, 1482 deletions
diff --git a/nuttx/fs/nfs/Make.defs b/nuttx/fs/nfs/Make.defs
index 915d6bb9c..bfe1265c3 100644
--- a/nuttx/fs/nfs/Make.defs
+++ b/nuttx/fs/nfs/Make.defs
@@ -42,7 +42,7 @@ CSRCS +=
# Files required for NFS RPC
ASRCS +=
-CSRCS += rpc_clnt.c nfs_socket.c
+CSRCS += rpc_clnt.c nfs_socket.c nfs_util.c nfs_vfsops.c
# Argument for dependency checking
diff --git a/nuttx/fs/nfs/nfs.h b/nuttx/fs/nfs/nfs.h
index d9e61e57c..497cfd666 100644
--- a/nuttx/fs/nfs/nfs.h
+++ b/nuttx/fs/nfs/nfs.h
@@ -270,11 +270,6 @@ struct nfsstats
* by them and break.
*/
-struct uio;
-struct buf;
-struct vattr;
-struct nameidata; /* XXX */
-
/* Nfs outstanding request list element */
struct nfsreq
@@ -338,114 +333,6 @@ struct nfsrv_descript
uint32_t nd_retxid; /* Reply xid */
};
-/* NFS procedures args */
-
-struct wcc_attr
-{
- nfsuint64 size;
- nfstime3 mtime;
- nfstime3 ctime;
-}
-
-struct wcc_data
-{
- wcc_attr before;
- nfs_fattr after;
-};
-
-struct diropargs3
-{
- nfsfh_t dir;
- const char name;
-};
-
-struct CREATE3args
-{
- diropargs3 where;
- nfsv3_sattr how;
-};
-
-struct CREATE3resok
-{
- const char handle;
- nfs_fattr attributes;
- wcc_data dir_wcc;
-};
-
-struct READ3args
-{
- nfstype file;
- uint64_t offset;
- uint32_t count;
-};
-
-struct READ3resok
-{
- nfs_fattr file_attributes;
- uint32_t count;
- bool eof;
- const char data;
-};
-
-enum stable_how
-{
- UNSTABLE = 0,
- DATA_SYNC = 1,
- FILE_SYNC = 2
-};
-
-struct WRITE3args
-{
- nfstype file;
- uint64_t offset;
- uint32_t count;
- stable_how stable;
- const char data;
-};
-
-struct WRITE3resok
-{
- wcc_data file_wcc;
- count3 count;
- stable_how committed;
- unsigned char verf;
-};
-
-struct REMOVE3args
-{
- diropargs3 object;
-};
-
-struct REMOVE3resok
-{
- wcc_data dir_wcc;
-};
-
-struct RENAME3args
-{
- diropargs3 from;
- diropargs3 to;
-};
-
-struct RENAME3resok
-{
- wcc_data fromdir_wcc;
- wcc_data todir_wcc;
-};
-
-struct MKDIR3args
-{
- diropargs3 where;
- nfsv3_sattr attributes;
-};
-
-struct MKDIR3resok
-{
- const char handle;
- nfs_fattr obj_attributes;
- wcc_data dir_wcc;
-};
-
/****************************************************************************
* Public Data
****************************************************************************/
diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h
index 5c0e5a5fd..78048f443 100644
--- a/nuttx/fs/nfs/nfs_mount.h
+++ b/nuttx/fs/nfs/nfs_mount.h
@@ -75,7 +75,7 @@ struct nfsmount
int nm_numgrps; /* Max. size of groupslist */
nfsfh_t nm_fh; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */
- struct rpcclnt nm_rpcclnt; /* rpc state */
+ struct rpcclnt *nm_rpcclnt; /* rpc state */
struct socket *nm_so; /* Rpc socket */
int nm_sotype; /* Type of socket */
int nm_soproto; /* and protocol */
@@ -99,24 +99,7 @@ struct nfsmount
int nm_acregmax; /* Reg file attr cache max lifetime */
unsigned char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
//char nm_mntonname[90]; /* directory on which mounted */
- uint8_t *nm_buffer; /* This is an allocated buffer to hold one sector*/
+//uint8_t *nm_buffer; /* This is an allocated buffer to hold one sector*/
};
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/* Prototypes for NFS mount operations: */
-
-int nfs_mount(struct inode *, const char *, void *);
-int mountnfs(struct nfs_args *, struct inode *, char *, char *);
-void nfs_decode_args(struct nfsmount *, struct nfs_args *, struct nfs_args *);
-int nfs_unmount(struct inode *, int);
-int nfs_root(struct inode *, struct file **);
-int nfs_statfs(struct inode *, struct statfs *);
-int nfs_sync(struct inode *, int);
-int nfs_vget(struct inode *, ino_t, struct file **);
-int nfs_fsinfo(struct nfsmount *, struct file *);
-void nfs_init(void);
-
#endif
diff --git a/nuttx/fs/nfs/nfs_proto.h b/nuttx/fs/nfs/nfs_proto.h
index 8b6e8cf94..d8e7e990c 100644
--- a/nuttx/fs/nfs/nfs_proto.h
+++ b/nuttx/fs/nfs/nfs_proto.h
@@ -430,6 +430,7 @@ struct nfsv3_sattr
struct nfs_statfs
{
+ struct nfs_fattr obj_attributes;
union
{
struct
@@ -468,6 +469,7 @@ struct nfs_statfs
struct nfsv3_fsinfo
{
+ struct nfs_fattr obj_attributes;
uint32_t fs_rtmax;
uint32_t fs_rtpref;
uint32_t fs_rtmult;
@@ -480,14 +482,161 @@ struct nfsv3_fsinfo
uint32_t fs_properties;
};
-struct nfsv3_pathconf
+/* NFS procedures args */
+
+struct wcc_attr
+{
+ nfsuint64 size;
+ nfstime3 mtime;
+ nfstime3 ctime;
+};
+
+struct wcc_data
+{
+ struct wcc_attr before;
+ struct nfs_fattr after;
+};
+
+struct diropargs3
+{
+ nfsfh_t dir;
+ const char name;
+};
+
+struct CREATE3args
+{
+ struct diropargs3 where;
+ struct nfsv3_sattr how;
+};
+
+struct CREATE3resok
+{
+ nfsfh_t handle;
+ struct nfs_fattr attributes;
+ struct wcc_data dir_wcc;
+};
+
+struct READ3args
+{
+ nfstype file;
+ uint64_t offset;
+ uint32_t count;
+};
+
+struct READ3resok
+{
+ struct nfs_fattr file_attributes;
+ uint32_t count;
+ bool eof;
+ const char data;
+};
+
+enum stable_how
+{
+ UNSTABLE = 0,
+ DATA_SYNC = 1,
+ FILE_SYNC = 2
+};
+
+struct WRITE3args
+{
+ nfstype file;
+ uint64_t offset;
+ uint32_t count;
+ enum stable_how stable;
+ const char data;
+};
+
+struct WRITE3resok
+{
+ struct wcc_data file_wcc;
+ uint32_t count;
+ enum stable_how committed;
+ unsigned char verf;
+};
+
+struct REMOVE3args
+{
+ struct diropargs3 object;
+};
+
+struct REMOVE3resok
+{
+ struct wcc_data dir_wcc;
+};
+
+struct RENAME3args
+{
+ struct diropargs3 from;
+ struct diropargs3 to;
+};
+
+struct RENAME3resok
+{
+ struct wcc_data fromdir_wcc;
+ struct wcc_data todir_wcc;
+};
+
+struct MKDIR3args
+{
+ struct diropargs3 where;
+ struct nfsv3_sattr attributes;
+};
+
+struct MKDIR3resok
+{
+ nfsfh_t handle;
+ struct nfs_fattr obj_attributes;
+ struct wcc_data dir_wcc;
+};
+
+struct RMDIR3args
+{
+ struct diropargs3 object;
+};
+
+struct RMDIR3resok
+{
+ struct wcc_data dir_wcc;
+};
+
+struct READDIR3args
+{
+ nfsfh_t dir;
+ nfsuint64 cookie;
+ nfsuint64 cookieverf;
+ uint32_t count;
+};
+
+struct entry3
+{
+ uint64_t fileid;
+ unsigned char name;
+ nfsuint64 cookie;
+ struct entry3 *nextentry;
+ };
+
+struct dirlist3
+{
+ struct entry3 *entries;
+ bool eof;
+};
+
+struct READDIR3resok
+{
+ struct nfs_fattr dir_attributes;
+ nfsuint64 cookieverf;
+ struct dirlist3 reply;
+};
+
+struct FSINFOargs
+{
+ nfsfh_t fsroot;
+};
+
+struct FSSTAT3args
{
- uint32_t pc_linkmax;
- uint32_t pc_namemax;
- uint32_t pc_notrunc;
- uint32_t pc_chownrestricted;
- uint32_t pc_caseinsensitive;
- uint32_t pc_casepreserving;
+ nfsfh_t fsroot;
};
#endif
diff --git a/nuttx/fs/nfs/nfs_socket.c b/nuttx/fs/nfs/nfs_socket.c
index 663cf8e26..0dbca8297 100644
--- a/nuttx/fs/nfs/nfs_socket.c
+++ b/nuttx/fs/nfs/nfs_socket.c
@@ -163,7 +163,7 @@ void nfsx_safedisconnect(struct nfsmount *nmp)
}
#endif
-int nfsx_request_xx(struct nfsmount *nm, int procnum,void *datain, void *dataout)
+int nfsx_request_xx(struct nfsmount *nm, int procnum, void *datain, void *dataout)
{
int error;
struct nfsmount *nmp;
diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c
index 94e2cdca9..1e8805a92 100755
--- a/nuttx/fs/nfs/nfs_util.c
+++ b/nuttx/fs/nfs/nfs_util.c
@@ -39,8 +39,10 @@
#include <nuttx/config.h>
#include <sys/types.h>
+#include <sys/time.h>
#include <stdint.h>
+#include <queue.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@@ -49,10 +51,11 @@
#include <assert.h>
#include <debug.h>
-#include <nuttx/fs/ioctl.h>
#include <nuttx/fs/dirent.h>
-#include "nfsmount.h"
+#include "nfs_proto.h"
+#include "nfs_mount.h"
+#include "nfs_node.h"
/****************************************************************************
* Private Types
@@ -75,199 +78,6 @@
****************************************************************************/
/****************************************************************************
- * 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
****************************************************************************/
@@ -299,223 +109,6 @@ void nfs_semgive(struct nfsmount *nmp)
}
/****************************************************************************
- * 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.
@@ -536,7 +129,7 @@ int nfs_checkmount(struct nfsmount *nmp)
*/
DEBUGASSERT(nmp && nmp->nm_blkdriver);
- if (nmp->mm_mounted)
+ if (nmp->nm_mounted)
{
/* We still think the mount is healthy. Check an see if this is
* still the case
@@ -566,277 +159,3 @@ int nfs_checkmount(struct nfsmount *nmp)
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 4d14feac9..805b48967 100644
--- a/nuttx/fs/nfs/nfs_vfsops.c
+++ b/nuttx/fs/nfs/nfs_vfsops.c
@@ -44,13 +44,19 @@
* Included Files
****************************************************************************/
+#include <nuttx/config.h>
+
#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/systm.h>
-#include <sys/sysctl.h>
-#include <sys/statfs>
+#include <sys/statfs.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
#include <queue.h>
+#include <string.h>
+#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
@@ -60,8 +66,8 @@
#include <net/if.h>
#include <netinet/in.h>
-#include "rpcv2.h"
-#include "nfsproto.h"
+#include "rpc_v2.h"
+#include "nfs_proto.h"
#include "nfs_node.h"
#include "nfs.h"
#include "nfs_mount.h"
@@ -77,7 +83,7 @@
/****************************************************************************
* Private Type Definitions
****************************************************************************/
-
+
struct nfs_dirent
{
uint32_t cookie[2];
@@ -85,6 +91,29 @@ struct nfs_dirent
};
/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int nfs_open(FAR struct file *filep, const char *relpath,
+ int oflags, mode_t mode);
+static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen);
+static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
+ size_t buflen);
+static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
+static int nfs_mount(FAR struct inode *blkdriver, const void *data,
+ void **handle);
+static int nfs_unmount(void *handle, FAR struct inode **blkdriver);
+static int nfs_statfs(struct inode *mountpt, struct statfs *buf);
+static int nfs_remove(struct inode *mountpt, const char *relpath);
+static int nfs_mkdir(struct inode *mountpt, const char *relpath,
+ mode_t mode);
+static int nfs_rmdir(struct inode *mountpt, const char *relpath);
+static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
+ const char *newrelpath);
+static int nfs_fsinfo(struct inode *mountpt, const char *relpath,
+ struct stat *buf);
+
+/****************************************************************************
* External Public Data (this belong in a header file)
****************************************************************************/
@@ -98,19 +127,17 @@ extern uint32_t nfs_procids[NFS_NPROCS];
/****************************************************************************
* Public Data
****************************************************************************/
-
-int nfs_numasync = 0;
-
/* nfs vfs operations. */
-const struct mountpt_operations nfs_ops = {
+const struct mountpt_operations nfs_ops =
+{
nfs_open, /* open */
- nfs_close, /* close */
+ NULL, /* close */
nfs_read, /* read */
nfs_write, /* write */
NULL, /* seek */
NULL, /* ioctl */
- nfs_sync, /* sync */
+ NULL, /* sync */
NULL, /* opendir */
NULL, /* closedir */
@@ -125,7 +152,7 @@ const struct mountpt_operations nfs_ops = {
nfs_mkdir, /* mkdir */
nfs_rmdir, /* rmdir */
nfs_rename, /* rename */
- NULL /* stat */
+ nfs_fsinfo /* stat */
};
/****************************************************************************
@@ -136,14 +163,16 @@ const struct mountpt_operations nfs_ops = {
* Public Functions
****************************************************************************/
-/* nfs create struct file
- * if oflags == O_CREAT it creates a file, if not it
- * check to see if the type is ok
- * and that deletion is not in progress.
- */
+ /****************************************************************************
+ * Name: nfs_open
+ *
+ * Description: if oflags == O_CREAT it creates a file, if not it
+ * check to see if the type is ok and that deletion is not in progress.
+ ****************************************************************************/
+
-int
-nfs_open(FAR struct file *filp, FAR const char *relpath, // done but check variable how
+static int
+nfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
struct inode *in;
@@ -202,7 +231,7 @@ again:
create->where->dir= nmp->nm_fh;
create->where->name = relpath;
- error = nfs_request(in, NFSPROC_CREATE, (void *) create, replydata);
+ error = nfs_request(in, NFSPROC_CREATE, create, replydata);
if (!error)
{
/* Create an instance of the file private data to describe the opened
@@ -224,6 +253,7 @@ again:
resok = (struct CREATE3resok *) replydata;
np->n_open = true;
np->nfsv3_type = NFREG;
+ np->n_fhp = resok->handle;
np->n_size = (struct uint64_t *)resok->attributes->nfsv3fa_size;
np->n_fattr = resok->attributes;
np->n_mtime = (struct timespec*) resok->attributes->nfsv3fa_mtime
@@ -279,11 +309,12 @@ errout_with_semaphore:
return error;
}
+#ifdef 0
/****************************************************************************
* Name: nfs_close
****************************************************************************/
-int nfs_close(FAR struct file *filep) //done
+static int nfs_close(FAR struct file *filep) done
{
struct nfsmount *nmp;
struct nfsnode *np;
@@ -311,12 +342,13 @@ int nfs_close(FAR struct file *filep) //done
return error;
}
+#endif
/****************************************************************************
* Name: nfs_read
****************************************************************************/
-static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) //done
+static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
{
struct nfsmount *nmp;
struct nfsnode *np;
@@ -365,7 +397,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) //d
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
{
- (void)nfs_fsinfo(nmp);
+ (void)nfs_fsinfo(filep->f_inode, NULL, NULL);
}
/* Get the number of bytes left in the file */
@@ -387,7 +419,6 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) //d
{
error = EFBIG
goto errout_with_semaphore;
-
}
nfsstats.rpccnt[NFSPROC_READ]++;
@@ -409,7 +440,6 @@ again:
readsize = resok->count;
np->n_fattr = resok->file_attributes;
memcpy(userbuffer, resok->data, (struct size_t)readsize);
-
}
else
{
@@ -429,19 +459,15 @@ errout_with_semaphore:
****************************************************************************/
static ssize_t
-nfs_write(FAR struct file *filep, const char *buffer, size_t buflen) // done
+nfs_write(FAR struct file *filep, const char *buffer, size_t buflen)
{
- /*struct nfsm_info info;
- uint32_t *tl;
- int32_t t1, backup;
- caddr_t cp2;*/
struct inode *inode;
struct nfsmount *nmp;
struct nfsnode *np;
unsigned int writesize;
void *datareply;
struct WRITE3args *write;
- struct WRITE3resok resok;
+ struct WRITE3resok *resok;
uint8_t *userbuffer = (uint8_t*)buffer;
int error = 0;
uint64_t offset;
@@ -543,490 +569,433 @@ errout_with_semaphore:
return error;
}
-/* nfs file remove call
- * To try and make nfs semantics closer to ufs semantics, a file that has
- * other processes using the vnode is renamed instead of removed and then
- * removed later on the last close.
- * - If v_usecount > 1
- * If a rename is not already in the works
- * call nfs_sillyrename() to set it up
- * else
- * do the remove rpc
- */
/****************************************************************************
- * Name: nfs_remove
+ * Name: nfs_readdir
*
- * Description: Remove a file
+ * Description: Read the next directory entry
*
****************************************************************************/
-int nfs_remove(struct inode *mountpt, const char *relpath) //done
+static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
- struct nsfmount *nmp;
- struct nfsnode *np;
- void *datreply;
- struct REMOVE3args *remove;
- struct REMOVE3resok resok;
int error = 0;
-
- /* Sanity checks */
-
- DEBUGASSERT(mountpt && mountpt->i_private);
-
- /* Get the mountpoint private data from the inode structure */
-
- nmp = (struct nfsmount *)mountpt->i_private;
- np = nmp->nm_head;
-
- /* Check if the mount is still healthy */
-
- nfs_semtake(nmp);
- error = fat_checkmount(nmp);
- if (error == 0)
- {
- /* If the file is open, the correct behavior is to remove the file
- * name, but to keep the file cluster chain in place until the last
- * open reference to the file is closed.
- */
-
- /* Remove the file */
-
- if (np->n_type != NFREG)
- {
- error = EPERM;
- goto errout_with_semaphore;
- }
-
- /* Do the rpc */
-
- nfsstats.rpccnt[NFSPROC_REMOVE]++;
- remove->dir = nmp->nm_fh;
- remove->name = relpath;
-
- error = nfs_request(nmp, NFSPROC_REMOVE, remove, datareply);
-
- /* Kludge City: If the first reply to the remove rpc is lost..
- * the reply to the retransmitted request will be ENOENT
- * since the file was in fact removed
- * Therefore, we cheat and return success.
- */
-
- if (error == ENOENT)
- {
- error = 0;
- }
-
- if (error)
- {
- goto errout_with_semaphore;
- }
-
- resok = (struct REMOVE3resok *)datareply;
- np->n_fattr = resok->dir_wcc->after;
- np->n_flag |= NMODIFIED;
- }
- NFS_INVALIDATE_ATTRCACHE(np);
-
-errout_with_semaphore:
- nfs_semgive(nmp);
- return error;
-}
-
-/****************************************************************************
- * Name: nfs_rename
- *
- * Description: Rename a file or directory
- *
- ****************************************************************************/
-
-int nfs_rename(struct inode *mountpt, const char *oldrelpath,
- const char *newrelpath)
-{
- struct nsfmount *nmp;
+ unsigned long *cookies = NULL;
+ int cnt;
+ struct nfsmount *nmp;
struct nfsnode *np;
- void *datreply;
- struct RENAME3args *rename;
- struct RENAME3resok resok;
- int error = 0;
+ bool eof = false;
+ //struct nfs_dirent *ndp;
+
+ fvdbg("Entry\n");
/* Sanity checks */
- DEBUGASSERT(mountpt && mountpt->i_private);
+ DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
- /* Get the mountpoint private data from the inode structure */
+ /* Recover our private data from the inode instance */
- nmp = (struct nfsmount *)mountpt->i_private;
- np = nmp->nm_head;
+ nmp = mountpt->i_private;
+ np = np->nm_head;
+ dir->fd_root = mountpt;
- /* Check if the mount is still healthy */
+ /* 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 (np->nfsv3_type != NFREG && np->nfsv3_type != NFDIR)
+ if (np->nfsv3_type != NFDIR)
{
- fdbg("open eacces typ=%d\n", np->nfsv3_type);
- error= -EACCES;
+ error = EPERM;
goto errout_with_semaphore;
}
- nfsstats.rpccnt[NFSPROC_RENAME]++;
- rename->from->dir = nmp->nm_fh;
- rename->from->name = oldrelpath;
- rename->to->dir = nmp->nm_fh;
- rename->to->name = oldrelpath;
-
- error = nfs_request(fdvp, NFSPROC_RENAME, rename, datareply);
+ dir->u.nfs.nd_direoffset = np->nd_direoffset;
- /* Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. */
+ /* First, check for hit on the EOF offset */
- if (error == ENOENT)
+ if (dir->u.nfs.nd_direoffset != 0)
{
- error = 0;
+ nfsstats.direofcache_hits++;
+ //np->n_open = true;
+ return 0;
}
- if (error)
+ if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
{
- goto errout_with_semaphore;
+ (void)nfs_fsinfo(mountpt, NULL, NULL);
}
- resok = (struct RENAME3resok *) datareply;
- np->n_fattr = resok->todir_wcc->after
- np->n_flag |= NMODIFIED;
- NFS_INVALIDATE_ATTRCACHE(np);
+ error = nfs_readdirrpc(nmp, np, &eof, dir);
+
+ if (error == NFSERR_BAD_COOKIE)
+ {
+ error = EINVAL;
+ }
+
+ if (!error && eof)
+ {
+ nfsstats.direofcache_misses++;
+ nfs_semgive(nmp);
+ return 0;
+ }
errout_with_semaphore:
- nfs_semgive(nmp);
- return error;
+ nfs_semgive(nmp);
+ return error;
}
/****************************************************************************
- * Name: nfs_mkdir
- *
- * Description: Create a directory
+ * Name: nfs_readdirrpc
*
+ * Description: The function below stuff the cookies in after the name.
****************************************************************************/
-int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
+static int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np, bool *end_of_directory, fs_dirent_s *dir)
{
- struct nfsv3_sattr *vap;
- struct nfsv3_sattr *sp;
- struct nfsmount *nmp;
- struct nfsnode *np;
- struct MKDIR3args *mkdir;
- struct MKDIR3resok resok;
- void *datareply;
- int len;
- struct nfsnode *npL;
int error = 0;
+ void *datareply;
+ struct READDIR3args *readdir;
+ struct READDIR3resok *resok;
- /* Sanity checks */
+ /* Loop around doing readdir rpc's of size nm_readdirsize
+ * truncated to a multiple of NFS_READDIRBLKSIZ.
+ * The stopping criteria is EOF.
+ */
- DEBUGASSERT(mountpt && mountpt->i_private);
+ while (end_of_directory == false)
+ {
+ nfsstats.rpccnt[NFSPROC_READDIR]++;
+ readdir->dir = np->n_fhp;
+ readdir->count = nmp->nm_readdirsiz;
+ if (nfsstats.rpccnt[NFSPROC_READDIR] == 1)
+ {
+ readdir->cookie.nfsuquad[0] = 0;
+ readdir->cookie.nfsuquad[1] = 0;
+ readdir->cookieverf.nfsuquad[0] = 0;
+ readdir->cookieverf.nfsuquad[1] = 0;
+ }
+ else
+ {
+ readdir->cookie.nfsuquad[0] = dir->u.nfs.cookie[0];
+ readdir->cookie.nfsuquad[1] = dir->u.nfs.cookie[1];
+ readdir->cookieverf.nfsuquad[0] = np->n_cookieverf.nfsuquad[0];
+ readdir->cookieverf.nfsuquad[1] = np->n_cookieverf.nfsuquad[1];
+ }
- /* Get the mountpoint private data from the inode structure */
+ error = nfs_request(nmp, NFSPROC_READDIR, readdir, datareply);
- nmp = (struct nfsmount*) mountpt->i_private;
- np = nmp->nm_head;
- vap = np->n_fattr;
+ if (error)
+ {
+ goto nfsmout;
+ }
- /* Check if the mount is still healthy */
+ resok = (void READDIR3resok*) datareply;
+ np->n_fattr = resok->dir_attributes;
+ np->nd_cookieverf.nfsuquad[0] = resok->cookieverf.nfsuquad[0];
+ np->nd_cookieverf.nfsuquad[1] = resok->cookieverf.nfsuquad[1];
+ dir->fd_dir->d_type = resok->reply->entries->fileid;
+ dir->fd_dir->d_name = resok->reply->entries->name;
+ dir->u.nfs.cookie[0] = resok->reply->entries->cookie.nfsuquad[0];
+ dir->u.nfs.cookie[1] = resok->reply->entries->cookie.nfsuquad[1];
+
+ if(resok->reply->eof == true)
+ {
+ end_of_directory = true;
+ }
- nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != 0)
- {
- goto errout_with_semaphore;
- }
+ //more_dirs = fxdr_unsigned(int, *dp);
- nfsstats.rpccnt[NFSPROC_MKDIR]++;
- mkdir->dir = nmp->nm_fh;
- mkdir->name = relpath;
+ /* loop thru the dir entries*/
+/*
+ while (more_dirs && bigenough)
+ {
+ if (bigenough)
+ {
+ if (info_v3)
+ {
+ dir->u.nfs.cookie[0] = cookie.nfsuquad[0];
+ }
+ else
+ {
+ dir->u.nfs.cookie[0] = ndp->cookie[0] = 0;
+ }
- 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;
- sp->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
- sp->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
+ dir->u.nfs.cookie[1] = ndp->cookie[1] = cookie.nfsuquad[1];
+ }
- txdr_nfsv3time(&vap->sa_atime, &sp->sa_atime);
- txdr_nfsv3time(&vap->sa_mtime, &sp->sa_mtime);
+ more_dirs = fxdr_unsigned(int, *ndp);
+ }
+ */
+ }
- mkdir->attributes = sp;
+ /* We are now either at the end of the directory */
- error = nfs_request(nmp, NFSPROC_MKDIR, mkdir, datareply);
- if (error)
+ if (resok->reply->entries == NULL)
{
- goto errout_with_semaphore;
- }
+ np->n_direofoffset = fxdr_hyper(&dir->u.nfs.cookie[0]);
- nmp->n_flag |= NMODIFIED;
- NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
+ /* We signal the end of the directory by returning the
+ * special error -ENOENT
+ */
-errout_with_semaphore:
- nfs_semgive(nmp);
+ fdbg("End of directory\n");
+ error = -ENOENT;
+ }
+
+nfsmout:
return error;
}
-/* nfs remove directory call */
+/****************************************************************************
+ * Name: nfs_mount
+ *
+ * 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().
+ *
+ ****************************************************************************/
-int nfs_rmdir(void *v)
+static int nfs_mount(struct inode *blkdriver, void *data, void **handle)
{
- struct vop_rmdir_args *ap = v;
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- struct nfsm_info info;
- uint32_t *tl;
- int32_t t1;
- caddr_t cp2;
- int error = 0, wccflag = NFSV3_WCCRATTR;
-
- info.nmi_v3 = NFS_ISV3(dvp);
-
- if (dvp == vp)
- {
- vrele(dvp);
- vrele(dvp);
- pool_put(&namei_pool, cnp->cn_pnbuf);
- return EINVAL;
- }
-
- nfsstats.rpccnt[NFSPROC_RMDIR]++;
- info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
- NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen));
- nfsm_fhtom(&info, dvp, info.nmi_v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
+ int error;
+ struct nfs_args args;
+ struct sockaddr *nam;
+ nfsfh_t nfh[NFSX_V3FHMAX];
- info.nmi_procp = cnp->cn_proc;
- info.nmi_cred = cnp->cn_cred;
- error = nfs_request(dvp, NFSPROC_RMDIR, &info);
- if (info.nmi_v3)
+ bcopy(data, &args, sizeof(args.version));
+ if (args.version == 3)
{
- nfsm_wcc_data(dvp, wccflag);
+ bcopy(data, &args, sizeof(struct nfs_args3));
+ args.flags &= ~(NFSMNT_INTERNAL | NFSMNT_NOAC);
+ }
+ else if (args.version == NFS_ARGSVERSION)
+ {
+ error = copyin(data, &args, sizeof(struct nfs_args));
+ args.flags &= ~NFSMNT_NOAC;
+ }
+ else
+ {
+ return EPROGMISMATCH;
}
- m_freem(info.nmi_mrep);
-
-nfsmout:
- pool_put(&namei_pool, cnp->cn_pnbuf);
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
+ if ((args.flags & (NFSMNT_NFSV3 | NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS)
{
- NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
+ return EINVAL;
}
- VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
- VN_KNOTE(vp, NOTE_DELETE);
+ if (blkdriver->mnt_flag & MNT_UPDATE)
+ {
+ struct nfsmount *nmp = (struct nfsmount*)blkdriver->i_private;
+
+ if (nmp == NULL)
+ {
+ return EIO;
+ }
- cache_purge(vp);
- vrele(vp);
- vrele(dvp);
+ /* When doing an update, we can't change from or to v3. */
- /* Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. */
+ args.flags = (args.flags & ~(NFSMNT_NFSV3)) |
+ (nmp->nm_flag & (NFSMNT_NFSV3));
+ nfs_decode_args(nmp, &args);
+ return 0;
+ }
- if (error == ENOENT)
+ if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
{
- error = 0;
+ return EINVAL;
}
+ bcopy(args.fh, nfh, args.fhsize);
+ bcopy(args.addr, nam, sizeof(args.addr));
+ args.fh = nfh;
+ error = mountnfs(&args, blkdriver, nam);
return error;
}
-/* The readdir logic below has a big design bug. It stores the NFS cookie in
- * the returned uio->uio_offset but does not store the verifier (it cannot).
- * Instead, the code stores the verifier in the nfsnode and applies that
- * verifies to all cookies, no matter what verifier was originally with
- * the cookie.
+/****************************************************************************
+ * Name: mountnfs
*
- * From a practical standpoint, this is not a problem since almost all
- * NFS servers do not change the validity of cookies across deletes
- * and inserts.
- */
-
-/* nfs readdir call */
+ * Description: Common code for nfs_mount.
+ *
+ ****************************************************************************/
-int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) //seems done
+static int mountnfs(struct nfs_args *argp, struct inode *blkdriver,
+ struct sockaddr *nam, void **handle)
{
- //struct nfsnode *np = VTONFS(vp);
- int error = 0;
- unsigned long *cookies = NULL;
- int cnt;
struct nfsmount *nmp;
- struct nfsnode *np;
- int eof = 0;
- //struct nfs_dirent *ndp;
+ int error;
- fvdbg("Entry\n");
+ if (blkdriver->mnt_flag & MNT_UPDATE)
+ {
+ nmp = (struct nfsmount*)blkdriver->i_private;
- /* Sanity checks */
+ /* update paths, file handles, etc, here XXX */
- DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
+ return 0;
+ }
+ else
+ {
+ /* Open the block driver */
- /* Recover our private data from the inode instance */
+ if (!blkdriver || !blkdriver->u.i_bops)
+ {
+ fdbg("No block driver/ops\n");
+ return -ENODEV;
+ }
- nmp = mountpt->i_private;
- np = np->nm_head;
+ if (blkdriver->u.i_bops->open &&
+ blkdriver->u.i_bops->open(blkdriver) != OK)
+ {
+ fdbg("No open method\n");
+ return -ENODEV;
+ }
- /* Make sure that the mount is still healthy */
+ /* Create an instance of the mountpt state structure */
- nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != 0)
- {
- fdbg("romfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
+ nmp = (struct nfsmount*)zalloc(sizeof(struct nfmount));
+ if (!nmp)
+ {
+ fdbg("Failed to allocate mountpoint structure\n");
+ return -ENOMEM;
+ }
- if (np->nfsv3_type != NFDIR)
- {
- error = EPERM;
- goto errout_with_semaphore;
- }
+ /* 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().
+ */
- dir->u.nfs.nd_direoffset = np->nd_direoffset;
+ sem_init(&rm->rm_sem, 0, 0); /* Initialize the semaphore that controls access */
- /* First, check for hit on the EOF offset */
+ //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);
+ // bcopy(pth, nmp->nm_mntonname, 90);
+ //memmove(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp));
+ nmp->nm_nam = nam;
+ nfs_decode_args(nmp, argp);
- if (dir->u.nfs.nd_direoffset != 0)
- {
- nfsstats.direofcache_hits++;
- //np->n_open = true;
- return 0;
- }
+ /* Set up the sockets and per-host congestion */
- if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
- {
- (void)nfs_fsinfo(nmp);
- }
- cnt = 5;
+ nmp->nm_sotype = argp->sotype;
+ nmp->nm_soproto = argp->proto;
- do
- {
- error = nfs_readdirrpc(nmp, &eof, dir);
+ /* For Connection based sockets (TCP,...) defer the connect until
+ * the first request, in case the server is not responding.
+ */
- if (error == NFSERR_BAD_COOKIE)
+ if (nmp->nm_sotype == SOCK_DGRAM && (error = nfs_connect(nmp)))
{
- error = EINVAL;
+ goto bad;
}
- }
- while (!error && !eof && cnt--);
- if (!error && eof)
- {
- nfsstats.direofcache_misses++;
+ /* Mounted! */
+
+ nmp->nfs_mounted = true;
+ nfs_init();
+ *handle = blkdriver->i_private = &nmp;
nfs_semgive(nmp);
+
return 0;
- }
+ }
-errout_with_semaphore:
- nfs_semgive(nmp);
+bad:
+ nfs_disconnect(nmp);
+ sem_destroy(&nmp->nm_sem);
+ kfree(nmp);
return error;
}
-/* The function below stuff the cookies in after the name */
-
-/* Readdir rpc call. */
+/****************************************************************************
+ * Name: nfs_unmount
+ *
+ * Description: This implements the filesystem portion of the umount
+ * operation.
+ *
+ ****************************************************************************/
-int nfs_readdirrpc(struct nfsmount *nmp, int *end_of_directory, fs_dirent_s *dir) //seems done
+int nfs_unmount(struct inode *blkdriver, void *handle)
{
- int len, left;
- struct nfs_dirent *ndp = NULL;
- struct nfs_dirent *dp = NULL;
- nfsuint64 cookie;
- struct nfsnode *dnp = nmp->nm_head;
- int error = 0, more_dirs = 1, blksiz = 0, bigenough = 1;
- int attrflag;
- int info_v3;
- void *datareply;
-
- info_v3 = (nmp->nm_flag & NFSMNT_NFSV3);
+ struct nfsmount *nmp = (struct nfsmount*) handle ;
+ int error;
- /* 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.
- */
+ fvdbg("Entry\n");
- while (more_dirs && bigenough)
+ if (!nmp)
{
- nfsstats.rpccnt[NFSPROC_READDIR]++;
- if (info_v3)
- {
- cookie.nfsuquad[0] = dnp->n_cookieverf.nfsuquad[0];
- cookie.nfsuquad[1] = dnp->n_cookieverf.nfsuquad[1];
- }
- else
- {
- cookie.nfsuquad[1] = dnp->n_cookieverf.nfsuquad[1];
- }
-
- error = nfs_request(nmp, NFSPROC_READDIR, datareply);
- dp = (void nfs_dirent*) datareply;
-
- if (error)
- {
- goto nfsmout;
- }
-
- if (info_v3)
- {
- dnp->n_cookieverf.nfsuquad[0] = dp->cookie[0];
- dnp->n_cookieverf.nfsuquad[1] = dp->cookie[1];
- }
+ return -EINVAL;
+ }
- more_dirs = fxdr_unsigned(int, *dp);
+ nfs_semtake(nmp)
+ if (nmp->nm_head)
+ {
+ /* We cannot unmount now.. there are open files */
- /* loop thru the dir entries*/
+ error = -EBUSY;
+ }
+ else
+ {
+ /* Unmount ... close the block driver */
- while (more_dirs && bigenough)
+ if (nmp->nm_blkdriver)
{
- if (bigenough)
+ struct inode *inode = nmp->nm_blkdriver;
+ if (inode)
{
- if (info_v3)
+ if (inode->u.i_bops && inode->u.i_bops->close)
{
- dir->u.nfs.cookie[0] = cookie.nfsuquad[0];
+ (void)inode->u.i_bops->close(inode);
}
- else
+
+ /* 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)
{
- dir->u.nfs.cookie[0] = ndp->cookie[0] = 0;
+ *blkdriver = inode;
}
-
- dir->u.nfs.cookie[1] = ndp->cookie[1] = cookie.nfsuquad[1];
}
-
- more_dirs = fxdr_unsigned(int, *ndp);
}
- }
- /* We are now either at the end of the directory or have filled the
- * block.
- */
+ /* Release the mountpoint private data */
- if (bigenough)
- {
- dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
- if (end_of_directory)
+ if (blkdriver->i_private)
{
- *end_of_directory = 1;
+ kfree(blkdriver->nm_buffer);
}
- /* We signal the end of the directory by returning the
- * special error -ENOENT
- */
+ nfs_disconnect(nmp);
+ sem_destroy(&nmp->nm_sem);
+ kfree(nmp);
- fdbg("End of directory\n");
- error = ENOENT;
+ return 0;
}
-nfsmout:
- return error;
+ nfs_semgive(nmp)
+ return 0;
}
/****************************************************************************
@@ -1036,13 +1005,14 @@ nfsmout:
*
****************************************************************************/
-int nfs_statfs(struct inode *mountpt, struct statfs *sbp) //done
+static int nfs_statfs(struct inode *mountpt, struct statfs *sbp)
{
struct nfs_statfs *sfp = NULL;
struct nfsmount *nmp;
int error = 0;
uint64_t tquad;
void *datareply;
+ struct FSSTAT3args *fsstat
int info_v3;
/* Sanity checks */
@@ -1051,7 +1021,7 @@ int nfs_statfs(struct inode *mountpt, struct statfs *sbp) //done
/* Get the mountpoint private data from the inode structure */
- nmp = mountpt->i_private;
+ nmp = (struct nfsmount*)mountpt->i_private;
info_v3 = (nmp->nm_flag & NFSMNT_NFSV3);
/* Check if the mount is still healthy */
@@ -1071,18 +1041,19 @@ int nfs_statfs(struct inode *mountpt, struct statfs *sbp) //done
if (info_v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
{
- (void)nfs_fsinfo(nmp);
+ (void)nfs_fsinfo(mountpt, NULL, NULL);
}
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
-
- error = nfs_request(nmp, NFSPROC_FSSTAT, datareply);
+ fsstat->fsroot = nmp->nm_fh;
+ error = nfs_request(nmp, NFSPROC_FSSTAT, fsstat, datareply);
if (error)
{
goto errout_with_semaphore;
}
sfp = (struct nfs_statfs *)datareply;
+ nmp->nm_head->n_fattr = sfp->obj_attributes
if (info_v3)
{
sbp->f_bsize = NFS_FABLKSIZE;
@@ -1114,37 +1085,341 @@ errout_with_semaphore:
return error;
}
-/* Print out the contents of an nfsnode. */
-/*
-int nfs_print(struct file *filep)
+/****************************************************************************
+ * Name: nfs_remove
+ *
+ * Description: Remove a file
+ *
+ ****************************************************************************/
+
+static int nfs_remove(struct inode *mountpt, const char *relpath)
+{
+ struct nsfmount *nmp;
+ struct nfsnode *np;
+ void *datreply;
+ struct REMOVE3args *remove;
+ struct REMOVE3resok *resok;
+ int error = 0;
+
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the inode structure */
+
+ nmp = (struct nfsmount *)mountpt->i_private;
+ np = nmp->nm_head;
+
+ /* Check if the mount is still healthy */
+
+ nfs_semtake(nmp);
+ error = fat_checkmount(nmp);
+ if (error == 0)
+ {
+ /* If the file is open, the correct behavior is to remove the file
+ * name, but to keep the file cluster chain in place until the last
+ * open reference to the file is closed.
+ */
+
+ /* Remove the file */
+
+ if (np->n_type != NFREG)
+ {
+ error = EPERM;
+ goto errout_with_semaphore;
+ }
+
+ /* Do the rpc */
+
+ nfsstats.rpccnt[NFSPROC_REMOVE]++;
+ remove->object->dir = np->n_fhp;
+ remove->object->name = relpath;
+
+ error = nfs_request(nmp, NFSPROC_REMOVE, remove, datareply);
+
+ /* Kludge City: If the first reply to the remove rpc is lost..
+ * the reply to the retransmitted request will be ENOENT
+ * since the file was in fact removed
+ * Therefore, we cheat and return success.
+ */
+
+ if (error == ENOENT)
+ {
+ error = 0;
+ }
+
+ if (error)
+ {
+ goto errout_with_semaphore;
+ }
+
+ resok = (struct REMOVE3resok *)datareply;
+ np->n_fattr = resok->dir_wcc->after;
+ np->n_flag |= NMODIFIED;
+ }
+ NFS_INVALIDATE_ATTRCACHE(np);
+
+errout_with_semaphore:
+ nfs_semgive(nmp);
+ return error;
+}
+
+/****************************************************************************
+ * Name: nfs_mkdir
+ *
+ * Description: Create a directory
+ *
+ ****************************************************************************/
+
+static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
{
- //struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(filep);
+ struct nfsv3_sattr *vap;
+ struct nfsv3_sattr *sp;
+ struct nfsmount *nmp;
+ struct nfsnode *np;
+ struct MKDIR3args *mkdir;
+ struct MKDIR3resok *resok;
+ void *datareply;
+ int len;
+ int error = 0;
- nvdbg("tag VT_NFS, fileid %ld fsid 0x%lx",
- np->n_fattr.nfsv3fa_fileid, np->n_fattr.nfsv3fa_fsid);
- nvdbg("\n");
- return 0;
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the inode structure */
+
+ nmp = (struct nfsmount*) mountpt->i_private;
+ np = nmp->nm_head;
+ vap = np->n_fattr;
+
+ /* 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]++;
+ mkdir->where->dir = nmp->nm_fh;
+ mkdir->where->name = relpath;
+
+ 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;
+ 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);
+
+ mkdir->attributes = sp;
+
+ error = nfs_request(nmp, NFSPROC_MKDIR, mkdir, datareply);
+ if (error)
+ {
+ goto errout_with_semaphore;
+ }
+
+ resok = (struct MKDIR3resok *) datareply;
+ np->nfsv3_type = NDIR;
+ np->n_fhp = resok->handle;
+ np->n_fattr = resok->obj_attributes;
+ nmp->n_flag |= NMODIFIED;
+ NFS_INVALIDATE_ATTRCACHE(np);
+
+errout_with_semaphore:
+ nfs_semgive(nmp);
+ return error;
+}
+
+/****************************************************************************
+ * Name: nfs_rmdir
+ *
+ * Description: Remove a directory
+ *
+ ****************************************************************************/
+
+static int nfs_rmdir(struct inode *mountpt, const char *relpath)
+{
+ struct nfsmount *nmp;
+ struct nfsnode *np;
+ struct RMDIR3args *rmdir;
+ struct RMDIR3resok *resok;
+ void *datareply;
+ int error = 0;
+
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the inode structure */
+
+ nmp = (struct nfsmount *)mountpt->i_private;
+ np = nmp->nm_head;
+
+ /* Check if the mount is still healthy */
+
+ nfs_semtake(nmp);
+ error = fat_checkmount(nmp);
+ if (error == 0)
+ {
+ /* Remove the directory */
+
+ if (np->n_type != NDIR)
+ {
+ error = EPERM;
+ goto errout_with_semaphore;
+ }
+
+ /* Do the rpc */
+
+ nfsstats.rpccnt[NFSPROC_RMDIR]++;
+ rmdir->object->dir = np->n_fhp;
+ rmdir->object->name = relpath;
+ error = nfs_request(dvp, NFSPROC_RMDIR, rmdir, datareply);
+
+ if (error == ENOENT)
+ {
+ error = 0;
+ }
+
+ if (error)
+ {
+ goto errout_with_semaphore;
+ }
+
+ resok = (struct REMOVE3resok *)datareply;
+ np->n_fattr = resok->dir_wcc->after;
+ np->n_flag |= NMODIFIED;
+ }
+ NFS_INVALIDATE_ATTRCACHE(np);
+
+errout_with_semaphore:
+ nfs_semgive(nmp);
+ return error;
}
-*/
-/* nfs version 3 fsinfo rpc call */
-int nfs_fsinfo(struct nfsmount *nmp) //done
+/****************************************************************************
+ * Name: nfs_rename
+ *
+ * Description: Rename a file or directory
+ *
+ ****************************************************************************/
+
+static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
+ const char *newrelpath)
+{
+ struct nsfmount *nmp;
+ struct nfsnode *np;
+ void *datreply;
+ struct RENAME3args *rename;
+ struct RENAME3resok *resok;
+ int error = 0;
+
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the inode structure */
+
+ nmp = (struct nfsmount *)mountpt->i_private;
+ np = nmp->nm_head;
+
+ /* Check if the mount is still healthy */
+
+ nfs_semtake(nmp);
+ error = nfs_checkmount(nmp);
+ if (error != 0)
+ {
+ goto errout_with_semaphore;
+ }
+
+ if (np->nfsv3_type != NFREG && np->nfsv3_type != NFDIR)
+ {
+ fdbg("open eacces typ=%d\n", np->nfsv3_type);
+ error= -EACCES;
+ goto errout_with_semaphore;
+ }
+
+ nfsstats.rpccnt[NFSPROC_RENAME]++;
+ rename->from->dir = np->n_fhp;
+ rename->from->name = oldrelpath;
+ rename->to->dir = np->n_fhp;
+ rename->to->name = newrelpath;
+
+ error = nfs_request(fdvp, NFSPROC_RENAME, rename, datareply);
+
+ /* Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. */
+
+ if (error == ENOENT)
+ {
+ error = 0;
+ }
+
+ if (error)
+ {
+ goto errout_with_semaphore;
+ }
+
+ resok = (struct RENAME3resok *) datareply;
+ np->n_fattr = resok->todir_wcc->after;
+ np->n_flag |= NMODIFIED;
+ NFS_INVALIDATE_ATTRCACHE(np);
+
+errout_with_semaphore:
+ nfs_semgive(nmp);
+ return error;
+}
+
+/****************************************************************************
+ * Name: nfs_fsinfo
+ *
+ * Description: Return information about a file or directory
+ *
+ ****************************************************************************/
+
+static int nfs_fsinfo(struct inode *mountpt, const char *relpath, struct stat *buf)
{
struct nfsv3_fsinfo *fsp;
+ struct FSINFOargs *fsinfo;
+ struct nfsmount *nmp;
uint32_t pref, max;
int error = 0;
void *datareply;
- nfsstats.rpccnt[NFSPROC_FSINFO]++;
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the inode structure */
+
+ nmp = (struct nfsmount*)mountpt->i_private;
+
+ /* Check if the mount is still healthy */
+
+ nfs_semtake(nmp);
+ error = nfd_checkmount(nmp);
+ if (error != 0)
+ {
+ goto errout_with_semaphore;
+ }
- error = nfs_request(nmp, NFSPROC_FSINFO, datareply);
+ memset(buf, 0, sizeof(struct stat));
+ nfsstats.rpccnt[NFSPROC_FSINFO]++;
+ fsinfo->fsroot = nmp->nm_fh;
+ error = nfs_request(nmp, NFSPROC_FSINFO, fsinfo, datareply);
if (error)
{
- goto nfsmout;
+ goto errout_with_semaphoret;
}
fsp = (struct nfsv3_fsinfo *)datareply;
+ nmp->nm_head->n_fattr = fsp->obj_attributes;
pref = fxdr_unsigned(uint32_t, fsp->fs_wtpref);
if (pref < nmp->nm_wsize)
{
@@ -1190,13 +1465,25 @@ int nfs_fsinfo(struct nfsmount *nmp) //done
}
}
+ buf->st_mode = fxdr_hyper(&fsp->obj_attributes->fa_mode);
+ buf->st_size = fxdr_hyper(&fsp->obj_attributes->fa3_size);
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_mtime = fxdr_hyper(&fsp->obj_attributes->fa3_mtime);
+ buf->st_atime = fxdr_hyper(&fsp->obj_attributes->fa3_atime);
+ buf->st_ctime = fxdr_hyper(&fsp->obj_attributes->fa3_ctime);
nmp->nm_flag |= NFSMNT_GOTFSINFO;
-nfsmout:
+errout_with_semaphore:
+ nfs_semgive(nmp);
return error;
}
-void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) //done
+/****************************************************************************
+ * Name: nfs_decode_args
+ ****************************************************************************/
+
+void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp)
{
int adjsock = 0;
int maxio;
@@ -1411,247 +1698,7 @@ void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) //done
}
}
-/****************************************************************************
- * Name: nfs_mount
- *
- * 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().
- *
- ****************************************************************************/
-
-int nfs_mount(struct inode *blkdriver, void *data, void **handle) //done
-{
- int error;
- struct nfs_args args;
- struct sockaddr *nam;
- nfsfh_t nfh[NFSX_V3FHMAX];
-
- bcopy(data, &args, sizeof(args.version));
- if (args.version == 3)
- {
- bcopy(data, &args, sizeof(struct nfs_args3));
- args.flags &= ~(NFSMNT_INTERNAL | NFSMNT_NOAC);
- }
- else if (args.version == NFS_ARGSVERSION)
- {
- error = copyin(data, &args, sizeof(struct nfs_args));
- args.flags &= ~NFSMNT_NOAC;
- }
- else
- {
- return EPROGMISMATCH;
- }
-
- if ((args.flags & (NFSMNT_NFSV3 | NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS)
- {
- return EINVAL;
- }
-
- if (blkdriver->mnt_flag & MNT_UPDATE)
- {
- struct nfsmount *nmp = (struct nfsmount*)blkdriver->i_private;
-
- if (nmp == NULL)
- {
- return EIO;
- }
-
- /* When doing an update, we can't change from or to v3. */
-
- args.flags = (args.flags & ~(NFSMNT_NFSV3)) |
- (nmp->nm_flag & (NFSMNT_NFSV3));
- nfs_decode_args(nmp, &args);
- return 0;
- }
-
- if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
- {
- return EINVAL;
- }
-
- bcopy(args.fh, nfh, args.fhsize);
- bcopy(args.addr, nam, sizeof(args.addr));
- args.fh = nfh;
- error = mountnfs(&args, blkdriver, nam);
- return error;
-}
-
-/* Common code for nfs_mount */
-
-int mountnfs(struct nfs_args *argp, struct inode *blkdriver,
- struct sockaddr *nam, void **handle) //done
-{
- struct nfsmount *nmp;
- int error;
-
- if (blkdriver->mnt_flag & MNT_UPDATE)
- {
- nmp = (struct nfsmount*)blkdriver->i_private;
-
- /* update paths, file handles, etc, here XXX */
-
- return 0;
- }
- 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;
- }
-
- /* 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().
- */
-
- 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);
- // bcopy(pth, nmp->nm_mntonname, 90);
- //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;
- }
-
- /* Mounted! */
-
- nmp->nfs_mounted = true;
- nfs_init();
- *handle = blkdriver->i_private = &nmp;
- nfs_semgive(nmp);
-
- return 0;
- }
-
-bad:
- nfs_disconnect(nmp);
- sem_destroy(&nmp->nm_sem);
- kfree(nmp);
- return error;
-}
-
-/****************************************************************************
- * Name: nfs_unmount
- *
- * Description: This implements the filesystem portion of the umount
- * operation.
- *
- ****************************************************************************/
-
-int nfs_unmount(struct inode *blkdriver, void *handle) //done
-{
- struct nfsmount *nmp = (struct nfsmount*) handle ;
- int error;
-
- fvdbg("Entry\n");
-
- if (!nmp)
- {
- return -EINVAL;
- }
-
- nfs_semtake(nmp)
- if (nmp->nm_head)
- {
- /* We cannot unmount now.. there are open files */
-
- error = -EBUSY;
- }
- else
- {
- /* Unmount ... close the block driver */
-
- 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;
-}
+#ifdef 0
/****************************************************************************
* Name: nfs_sync
*
@@ -1659,7 +1706,7 @@ int nfs_unmount(struct inode *blkdriver, void *handle) //done
*
****************************************************************************/
-int nfs_sync(struct file *filep) //falta
+int nfs_sync(struct file *filep)
{
struct inode *inode;
struct nfsmount *nmp;
@@ -1693,12 +1740,13 @@ int nfs_sync(struct file *filep) //falta
if ((np->n_flag & NMODIFIED) != 0)
{
- error = VOP_FSYNC(vp, cred, waitfor, p); ///////////////////////////////
+ //error = VOP_FSYNC(vp, cred, waitfor, p);
}
- return allerror;
+ return error;
errout_with_semaphore:
nfs_semgive(nmp);
return error;
}
+#endif
diff --git a/nuttx/include/nuttx/fs/dirent.h b/nuttx/include/nuttx/fs/dirent.h
index 19cda705d..f08861817 100644
--- a/nuttx/include/nuttx/fs/dirent.h
+++ b/nuttx/include/nuttx/fs/dirent.h
@@ -118,12 +118,15 @@ struct fs_nxffsdir_s
#endif
#ifdef CONFIG_NFS
+/* The NFS client file system */
+
struct nfsdir_s
{
off_t nd_direoffset; /* Directory EOF offset */
uint32_t cookie[2];
-}
+};
#endif
+
#endif /* CONFIG_DISABLE_MOUNTPOINT */
struct fs_dirent_s