You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/03/01 20:55:20 UTC
[incubator-nuttx] branch master updated: NFS bug fix and
improvement (#412)
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 915f094 NFS bug fix and improvement (#412)
915f094 is described below
commit 915f094a7466dcb2d4496a55bf4331aeccacb0cb
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Mon Mar 2 04:53:45 2020 +0800
NFS bug fix and improvement (#412)
* fs/nfs: Remove all nfs_checkmount call. The check just waste cpu cycle since nobody will set nm_mounted to false, and remove the unused fields(nm_mounted and n_flags) and related flags too
* fs/nfs: Fix the definition not confirm to RFC 1813 and other minor issue(unused, typo, duplication, alignment...)
* fs/nfs: Always represent error with negative number and remove the unused arguments from function
* fs/nfs: Set socket receive timeout with nfs_args->timeo and fix warning:
nfs/nfs.h:59:28: warning: large integer implicitly truncated to unsigned type [-Woverflow]
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
^
nfs/nfs_vfsops.c:1857:23: note: in expansion of macro 'NFS_TIMEO'
nprmt.timeo = NFS_TIMEO;
^
^~~~~~~~~
* fs/nfs: Update the file attribute correctly in nfs_filetruncate and simplify the attrbitue conversion between NFSv3 and NuttX
* fs/nfs: Remove the unfinished and buggy EXCLUSIVE creation mode
* fs/nfs: Call nfs_fsinfo in nfs_bind instead of nfs_statfs since we should update the buffer size before transfer happen, and handle the attribute existence variance correctly.
* fs/nfs: Shouldn't insert node into list again in nfs_dup and fix other typo issue
* fs/nfs: Should skip . and .. in nfs_readdir
* fs/nfs: Remove the unnecessary dynamic allocation and the duplicated root handle storage
---
fs/nfs/nfs.h | 19 +-
fs/nfs/nfs_mount.h | 35 +--
fs/nfs/nfs_node.h | 29 +-
fs/nfs/nfs_proto.h | 55 ++--
fs/nfs/nfs_util.c | 125 +++-----
fs/nfs/nfs_vfsops.c | 800 ++++++++++++++++++++--------------------------------
fs/nfs/rpc.h | 103 +++----
fs/nfs/rpc_clnt.c | 233 ++++++---------
fs/nfs/xdr_subs.h | 29 --
9 files changed, 523 insertions(+), 905 deletions(-)
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 2001e2b..a17750c 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -54,18 +54,14 @@
* Pre-processor Definitions
****************************************************************************/
-#define NFS_TICKS 1 /* Number of system ticks */
-#define NFS_HZ CLOCKS_PER_SEC /* Ticks/sec */
-#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
-#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
-#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
-#define NFS_TIMEOUTMUL 2 /* Timeout/Delay multiplier */
+#define NFS_TIMEO 10 /* Default timeout = 1 second */
+#define NFS_MINTIMEO 10 /* Min timeout to use */
+#define NFS_MAXTIMEO 255 /* Max timeout to backoff to */
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
-#define NFS_NPROCS 23
/* Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with
* broken NFS/ethernet drivers that won't work with anything bigger (Linux..)
@@ -85,9 +81,6 @@
* Public Data
****************************************************************************/
-extern uint32_t nfs_true;
-extern uint32_t nfs_false;
-extern uint32_t nfs_xdrneg1;
#ifdef CONFIG_NFS_STATISTICS
extern struct nfsstats nfsstats;
#endif
@@ -115,11 +108,7 @@ extern "C" {
#define EXTERN extern
#endif
-EXTERN void nfs_semtake(FAR struct nfsmount *nmp);
-EXTERN void nfs_semgive(FAR struct nfsmount *nmp);
-EXTERN int nfs_checkmount(FAR struct nfsmount *nmp);
-EXTERN int nfs_fsinfo(FAR struct nfsmount *nmp);
-EXTERN int nfs_request(struct nfsmount *nmp, int procnum,
+EXTERN int nfs_request(FAR struct nfsmount *nmp, int procnum,
FAR void *request, size_t reqlen,
FAR void *response, size_t resplen);
EXTERN int nfs_lookup(FAR struct nfsmount *nmp, FAR const char *filename,
diff --git a/fs/nfs/nfs_mount.h b/fs/nfs/nfs_mount.h
index bb43f44..4bab615 100644
--- a/fs/nfs/nfs_mount.h
+++ b/fs/nfs/nfs_mount.h
@@ -67,23 +67,18 @@
struct nfsmount
{
- struct nfsnode *nm_head; /* A list of all files opened on this mountpoint */
- sem_t nm_sem; /* Used to assure thread-safe access */
- nfsfh_t nm_fh; /* File handle of root dir */
- char nm_path[90]; /* server's path of the directory being mounted */
- struct nfs_fattr nm_fattr; /* nfs file attribute cache */
- struct rpcclnt *nm_rpcclnt; /* RPC state */
- struct socket *nm_so; /* RPC socket */
- struct sockaddr nm_nam; /* Addr of server */
- bool nm_mounted; /* true: The file system is ready */
- uint8_t nm_fhsize; /* Size of root file handle (host order) */
- uint8_t nm_sotype; /* Type of socket */
- uint8_t nm_retry; /* Max retries */
- uint16_t nm_timeo; /* Timeout value (in system clock ticks) */
- uint16_t nm_rsize; /* Max size of read RPC */
- uint16_t nm_wsize; /* Max size of write RPC */
- uint16_t nm_readdirsize; /* Size of a readdir RPC */
- uint16_t nm_buflen; /* Size of I/O buffer */
+ FAR struct nfsnode *nm_head; /* A list of all files opened on this mountpoint */
+ sem_t nm_sem; /* Used to assure thread-safe access */
+ nfsfh_t *nm_fh; /* File handle of root dir */
+ char nm_path[90]; /* server's path of the directory being mounted */
+ struct nfs_fattr nm_fattr; /* nfs file attribute cache */
+ FAR struct rpcclnt *nm_rpcclnt; /* RPC state */
+ struct sockaddr nm_nam; /* Addr of server */
+ uint8_t nm_fhsize; /* Size of root file handle (host order) */
+ uint16_t nm_rsize; /* Max size of read RPC */
+ uint16_t nm_wsize; /* Max size of write RPC */
+ uint16_t nm_readdirsize; /* Size of a readdir RPC */
+ uint16_t nm_buflen; /* Size of I/O buffer */
/* Set aside memory on the stack to hold the largest call message. NOTE
* that for the case of the write call message, it is the reply message that
@@ -104,7 +99,7 @@ struct nfsmount
struct rpc_call_readdir readdir;
struct rpc_call_fs fsstat;
struct rpc_call_setattr setattr;
- struct rpc_call_fs fs;
+ struct rpc_call_fs fsinfo;
struct rpc_reply_write write;
} nm_msgbuffer;
@@ -116,10 +111,10 @@ struct nfsmount
* possible WRITE call message or READ response message.
*/
- uint32_t nm_iobuffer[1]; /* Actual size is given by nm_buflen */
+ uint32_t nm_iobuffer[1]; /* Actual size is given by nm_buflen */
};
-/* The size of the nfsmount structure will debug on the size of the allocated I/O
+/* The size of the nfsmount structure will depend on the size of the allocated I/O
* buffer.
*/
diff --git a/fs/nfs/nfs_node.h b/fs/nfs/nfs_node.h
index cb5925f..cedd884 100644
--- a/fs/nfs/nfs_node.h
+++ b/fs/nfs/nfs_node.h
@@ -51,15 +51,6 @@
#include "nfs_proto.h"
/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* Flags for struct nfsnode n_flag */
-
-#define NFSNODE_OPEN (1 << 0) /* File is still open */
-#define NFSNODE_MODIFIED (1 << 1) /* Might have a modified buffer */
-
-/****************************************************************************
* Public Types
****************************************************************************/
@@ -69,16 +60,16 @@
struct nfsnode
{
- struct nfsnode *n_next; /* Retained in a singly linked list. */
- uint8_t n_crefs; /* Reference count (for nfs_dup) */
- uint8_t n_type; /* File type */
- uint8_t n_fhsize; /* Size in bytes of the file handle */
- uint8_t n_flags; /* Node flags */
- uint16_t n_mode; /* File mode for fstat() */
- time_t n_mtime; /* File modification time */
- time_t n_ctime; /* File creation time */
- nfsfh_t n_fhandle; /* NFS File Handle */
- uint64_t n_size; /* Current size of file */
+ FAR struct nfsnode *n_next; /* Retained in a singly linked list. */
+ uint8_t n_crefs; /* Reference count (for nfs_dup) */
+ uint8_t n_type; /* File type */
+ uint8_t n_fhsize; /* Size in bytes of the file handle */
+ uint16_t n_mode; /* File mode for fstat() */
+ time_t n_atime; /* File access time */
+ time_t n_mtime; /* File modification time */
+ time_t n_ctime; /* File creation time */
+ nfsfh_t n_fhandle; /* NFS File Handle */
+ uint64_t n_size; /* Current size of file */
};
#endif /* __FS_NFS_NFS_NODE_H */
diff --git a/fs/nfs/nfs_proto.h b/fs/nfs/nfs_proto.h
index 185dc6e..7b63d00 100644
--- a/fs/nfs/nfs_proto.h
+++ b/fs/nfs/nfs_proto.h
@@ -118,13 +118,13 @@
/* Specific to NFS Version 3 */
-#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
+#define NFSX_V3FH (sizeof(struct fhandle)) /* size this server uses */
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
#define NFSX_V3FATTR 84
#define NFSX_V3SATTR 60 /* max. all fields filled in */
#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
-#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
+#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 7 * NFSX_UNSIGNED)
#define NFSX_V3COOKIEVERF 8
#define NFSX_V3WRITEVERF 8
#define NFSX_V3CREATEVERF 8
@@ -185,13 +185,6 @@
#define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10
-/* Conversion macros */
-
-#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
-#define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777)
-#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))])
-#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(uint32_t,(a))&0x7]
-
/* Mode bit values */
#define NFSMODE_IXOTH (1 << 0) /* Execute permission for others on a file */
@@ -230,7 +223,7 @@ typedef enum
} nfstype;
/* File Handle variable is up to 64 bytes for version 3. This structures a
- * ariable sized and are provided only for setting aside maximum memory
+ * variable sized and are provided only for setting aside maximum memory
* allocations for a file handle.
*/
@@ -305,7 +298,7 @@ struct nfsv3_sattr
uint32_t sa_gidfollows; /* TRUE: Mode value follows */
uint32_t sa_gid; /* Mode value */
uint32_t sa_sizefollows; /* TRUE: Size value follows */
- uint32_t sa_size; /* Size value */
+ nfsuint64 sa_size; /* Size value */
uint32_t sa_atimetype; /* Don't change, use server timer, or use client time */
nfstime3 sa_atime; /* Client time */
uint32_t sa_mtimetype; /* Don't change, use server timer, or use client time */
@@ -314,6 +307,7 @@ struct nfsv3_sattr
struct nfs_statfs
{
+ uint32_t obj_attributes_follow;
struct nfs_fattr obj_attributes;
nfsuint64 sf_tbytes;
nfsuint64 sf_fbytes;
@@ -324,16 +318,10 @@ struct nfs_statfs
uint32_t sf_invarsec;
};
-struct post_attr
-{
- uint32_t obj_attributesfalse;
- struct nfs_fattr attributes;
-};
-
struct nfsv3_fsinfo
{
-//struct post_attr obj_attributes;
- uint32_t obj_attributesfalse;
+ uint32_t obj_attributes_follow;
+ struct nfs_fattr obj_attributes;
uint32_t fs_rtmax;
uint32_t fs_rtpref;
uint32_t fs_rtmult;
@@ -393,6 +381,18 @@ struct CREATE3resok
struct wcc_data dir_wcc;
};
+struct SETATTR3args
+{
+ struct file_handle fhandle; /* Variable length */
+ struct nfsv3_sattr new_attributes; /* Variable length */
+ uint32_t guard; /* Guard value */
+};
+
+struct SETATTR3resok
+{
+ struct wcc_data wcc_data;
+};
+
/* The actual size of the lookup argument is variable. These structures are, therefore,
* only useful in setting aside maximum memory usage for the LOOKUP arguments.
*/
@@ -409,18 +409,6 @@ struct LOOKUP3args
struct LOOKUP3filename name; /* Variable length */
};
-struct SETATTR3args
-{
- struct file_handle fhandle; /* Variable length */
- struct nfsv3_sattr new_attributes; /* Variable length */
- uint32_t guard; /* Guard value */
-};
-
-struct SETATTR3resok
-{
- struct wcc_data wcc_data;
-};
-
/* Actual size of LOOKUP3args */
#define SIZEOF_LOOKUP3filename(b) (sizeof(uint32_t) + (((b)+3) & ~3))
@@ -464,6 +452,7 @@ struct nfs_wrhdr_s
uint64_t offset;
uint32_t count;
uint32_t stable;
+ uint32_t length;
};
struct WRITE3args
@@ -528,10 +517,6 @@ struct RMDIR3resok
struct wcc_data dir_wcc;
};
-/* The actual size of the lookup argument is variable. This structures is, therefore,
- * only useful in setting aside maximum memory usage for the LOOKUP arguments.
- */
-
struct READDIR3args
{
struct file_handle dir; /* Variable length */
diff --git a/fs/nfs/nfs_util.c b/fs/nfs/nfs_util.c
index 594f6f2..abfa796 100644
--- a/fs/nfs/nfs_util.c
+++ b/fs/nfs/nfs_util.c
@@ -42,18 +42,14 @@
#include <sys/time.h>
#include <stdint.h>
-#include <queue.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
-#include <assert.h>
#include <debug.h>
-#include <nuttx/fs/dirent.h>
-
#include "rpc.h"
#include "nfs.h"
#include "nfs_proto.h"
@@ -105,7 +101,7 @@ static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer,
else if (nbytes >= NAME_MAX)
{
ferr("ERROR: File name segment is too long: %d\n", *path);
- return EFBIG;
+ return -EFBIG;
}
else
{
@@ -122,77 +118,25 @@ static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer,
****************************************************************************/
/****************************************************************************
- * Name: nfs_semtake
- ****************************************************************************/
-
-void nfs_semtake(struct nfsmount *nmp)
-{
- nxsem_wait_uninterruptible(&nmp->nm_sem);
-}
-
-/****************************************************************************
- * Name: nfs_semgive
- ****************************************************************************/
-
-void nfs_semgive(struct nfsmount *nmp)
-{
- nxsem_post(&nmp->nm_sem);
-}
-
-/****************************************************************************
- * Name: nfs_checkmount
- *
- * Description: Check if the mountpoint is still valid.
- *
- * The caller should hold the mountpoint semaphore
- *
- ****************************************************************************/
-
-int nfs_checkmount(struct nfsmount *nmp)
-{
- struct nfsnode *file;
-
- /* If the nm_mounted flag is false, then we have already handled the loss
- * of the mount.
- */
-
- DEBUGASSERT(nmp);
- if (!nmp->nm_mounted)
- {
- /* Make sure that this is flagged in every opened file */
-
- for (file = nmp->nm_head; file; file = file->n_next)
- {
- file->n_flags &= ~NFSNODE_OPEN;
- }
-
- return -ENODEV;
- }
-
- return 0;
-}
-
-/****************************************************************************
* Name: nfs_request
*
* Description:
- * Perform the NFS request. On successful receipt, it verifies the NFS level of the
- * returned values.
+ * Perform the NFS request. On successful receipt, it verifies the NFS level
+ * of the returned values.
*
* Returned Value:
- * Zero on success; a positive errno value on failure.
+ * Zero on success; a negative errno value on failure.
*
****************************************************************************/
-int nfs_request(struct nfsmount *nmp, int procnum,
+int nfs_request(FAR struct nfsmount *nmp, int procnum,
FAR void *request, size_t reqlen,
FAR void *response, size_t resplen)
{
- struct rpcclnt *clnt = nmp->nm_rpcclnt;
+ FAR struct rpcclnt *clnt = nmp->nm_rpcclnt;
struct nfs_reply_header replyh;
int error;
-tryagain:
error = rpcclnt_request(clnt, procnum, NFS_PROG, NFS_VER3,
request, reqlen, response, resplen);
if (error != 0)
@@ -207,29 +151,23 @@ tryagain:
{
if (fxdr_unsigned(uint32_t, replyh.nfs_status) > 32)
{
- error = EOPNOTSUPP;
+ error = -EOPNOTSUPP;
}
else
{
/* NFS_ERRORS are the same as NuttX errno values */
- error = fxdr_unsigned(uint32_t, replyh.nfs_status);
+ error = -fxdr_unsigned(uint32_t, replyh.nfs_status);
}
return error;
}
- if (replyh.rpc_verfi.authtype != 0)
+ if (replyh.rh.rpc_verfi.authtype != 0)
{
- error = fxdr_unsigned(int, replyh.rpc_verfi.authtype);
-
- if (error == EAGAIN)
- {
- error = 0;
- goto tryagain;
- }
-
- ferr("ERROR: NFS error %d from server\n", error);
+ error = -EOPNOTSUPP;
+ ferr("ERROR: NFS authtype %d from server\n",
+ fxdr_unsigned(int, replyh.rpc_verfi.authtype));
return error;
}
@@ -251,7 +189,7 @@ tryagain:
*
****************************************************************************/
-int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
+int nfs_lookup(FAR struct nfsmount *nmp, FAR const char *filename,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes)
@@ -270,7 +208,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
if (namelen > NAME_MAX)
{
ferr("ERROR: Length of the string is too long: %d\n", namelen);
- return E2BIG;
+ return -E2BIG;
}
/* Initialize the request */
@@ -284,7 +222,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
reqlen += sizeof(uint32_t);
memcpy(ptr, &fhandle->handle, fhandle->length);
- reqlen += fhandle->length;
+ reqlen += uint32_alignup(fhandle->length);
ptr += uint32_increment(fhandle->length);
/* Copy the variable-length file name */
@@ -322,7 +260,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
if (value > NFSX_V3FHMAX)
{
ferr("ERROR: Bad file handle length: %d\n", value);
- return EIO;
+ return -EIO;
}
/* Return the file handle */
@@ -367,11 +305,11 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
* return the handle of the directory entry of the requested object.
*
* Returned Value:
- * Zero on success; a positive errno value on failure.
+ * Zero on success; a negative errno value on failure.
*
****************************************************************************/
-int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
+int nfs_findnode(FAR struct nfsmount *nmp, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes)
@@ -385,13 +323,13 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
/* Start with the file handle of the root directory. */
fhandle->length = nmp->nm_fhsize;
- memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize);
+ memcpy(&fhandle->handle, nmp->nm_fh, nmp->nm_fhsize);
/* If no path was provided, then the root directory must be exactly what
* the caller is looking for.
*/
- if (*path == '\0' || strlen(path) == 0)
+ if (*path == '\0')
{
/* Return the root directory attributes */
@@ -461,8 +399,8 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
/* Ooops.. we found something else */
ferr("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n",
- buffer, path);
- return ENOTDIR;
+ buffer, relpath);
+ return -ENOTDIR;
}
}
}
@@ -476,11 +414,11 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
* object.
*
* Returned Value:
- * Zero on success; a positive errno value on failure.
+ * Zero on success; a negative errno value on failure.
*
****************************************************************************/
-int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
+int nfs_finddir(FAR struct nfsmount *nmp, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *attributes, FAR char *filename)
{
@@ -491,17 +429,15 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
/* Verify that a path was provided */
- if (*path == '\0' || strlen(path) == 0)
+ if (*path == '\0')
{
- /* Return the root directory attributes */
-
- return ENOENT;
+ return -ENOENT;
}
/* Start with the file handle of the root directory. */
fhandle->length = nmp->nm_fhsize;
- memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize);
+ memcpy(&fhandle->handle, nmp->nm_fh, nmp->nm_fhsize);
memcpy(attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr));
/* Loop until the directory entry containing the path is found. */
@@ -552,8 +488,8 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
/* Ooops.. we found something else */
ferr("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n",
- filename, path);
- return ENOTDIR;
+ filename, relpath);
+ return -ENOTDIR;
}
}
}
@@ -579,6 +515,9 @@ void nfs_attrupdate(FAR struct nfsnode *np, FAR struct nfs_fattr *attributes)
np->n_mode = fxdr_unsigned(uint16_t, attributes->fa_mode);
np->n_size = fxdr_hyper(&attributes->fa_size);
+ fxdr_nfsv3time(&attributes->fa_atime, &ts);
+ np->n_atime = ts.tv_sec;
+
fxdr_nfsv3time(&attributes->fa_mtime, &ts);
np->n_mtime = ts.tv_sec;
diff --git a/fs/nfs/nfs_vfsops.c b/fs/nfs/nfs_vfsops.c
index f9c55d4..59670c4 100644
--- a/fs/nfs/nfs_vfsops.c
+++ b/fs/nfs/nfs_vfsops.c
@@ -55,7 +55,6 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
-#include <queue.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
@@ -86,10 +85,6 @@
* Pre-processor Definitions
****************************************************************************/
-/* The V3 EXCLUSIVE file creation logic is not fully supported. */
-
-#define USE_GUARDED_CREATE 1
-
/* include/nuttx/fs/dirent.h has its own version of these lengths. They must
* match the NFS versions.
*/
@@ -103,37 +98,20 @@
#endif
/****************************************************************************
- * Private Types
+ * Private Data
****************************************************************************/
-/* Use to pass file information to nfs_stat_common() */
-
-struct nfs_statinfo_s
-{
- uint16_t ns_mode; /* File access mode */
- uint8_t ns_type; /* File type */
- uint64_t ns_size; /* File size */
- time_t ns_atime; /* Time of last access */
- time_t ns_mtime; /* Time of last modification */
- time_t ns_ctime; /* Time of last status change */
-};
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-uint32_t nfs_true;
-uint32_t nfs_false;
-uint32_t nfs_xdrneg1;
-
-#ifdef CONFIG_NFS_STATISTICS
-struct nfsstats nfsstats;
-#endif
+static uint32_t nfs_true;
+static uint32_t nfs_false;
+static uint32_t nfs_xdrneg1;
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
+static void nfs_semtake(FAR struct nfsmount *nmp);
+static void nfs_semgive(FAR struct nfsmount *nmp);
+
static int nfs_filecreate(FAR struct nfsmount *nmp,
FAR struct nfsnode *np, FAR const char *relpath,
mode_t mode);
@@ -143,24 +121,25 @@ static int nfs_fileopen(FAR struct nfsmount *nmp,
FAR struct nfsnode *np, FAR const char *relpath,
int oflags, mode_t mode);
-static int nfs_open(FAR struct file *filep, const char *relpath,
+static int nfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int nfs_close(FAR struct file *filep);
-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,
+static ssize_t nfs_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
+static ssize_t nfs_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp);
+static int nfs_fsinfo(FAR struct nfsmount *nmp);
static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
static int nfs_truncate(FAR struct file *filep, off_t length);
-static int nfs_opendir(struct inode *mountpt, const char *relpath,
- struct fs_dirent_s *dir);
-static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
+static int nfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct fs_dirent_s *dir);
+static int nfs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
static int nfs_rewinddir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt,
FAR struct nfs_args *argp);
-static int nfs_bind(FAR struct inode *blkdriver, const void *data,
- void **handle);
+static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle);
static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
unsigned int flags);
static int nfs_statfs(FAR struct inode *mountpt,
@@ -173,15 +152,18 @@ static int nfs_rmdir(FAR struct inode *mountpt,
FAR const char *relpath);
static int nfs_rename(FAR struct inode *mountpt,
FAR const char *oldrelpath, FAR const char *newrelpath);
-static void nfs_stat_common(FAR struct nfs_statinfo_s *info,
- FAR struct stat *buf);
-static int nfs_stat(struct inode *mountpt, FAR const char *relpath,
+static mode_t nfs_stat_mode(unsigned int mode, unsigned int type);
+static int nfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
/****************************************************************************
* Public Data
****************************************************************************/
+#ifdef CONFIG_NFS_STATISTICS
+struct nfsstats nfsstats;
+#endif
+
/* nfs vfs operations. */
const struct mountpt_operations nfs_operations =
@@ -215,9 +197,27 @@ const struct mountpt_operations nfs_operations =
};
/****************************************************************************
- * Public Functions
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nfs_semtake
****************************************************************************/
+static void nfs_semtake(FAR struct nfsmount *nmp)
+{
+ nxsem_wait_uninterruptible(&nmp->nm_sem);
+}
+
+/****************************************************************************
+ * Name: nfs_semgive
+ ****************************************************************************/
+
+static void nfs_semgive(FAR struct nfsmount *nmp)
+{
+ nxsem_post(&nmp->nm_sem);
+}
+
/****************************************************************************
* Name: nfs_filecreate
*
@@ -226,7 +226,7 @@ const struct mountpt_operations nfs_operations =
* the user asks to create a file.
*
* Returned Value:
- * 0 on success; a positive errno value on failure.
+ * 0 on success; a negative errno value on failure.
*
****************************************************************************/
@@ -262,7 +262,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
reqlen += sizeof(uint32_t);
memcpy(ptr, &fhandle.handle, fhandle.length);
- reqlen += (int)fhandle.length;
+ reqlen += uint32_alignup(fhandle.length);
ptr += uint32_increment(fhandle.length);
/* Copy the variable-length file name */
@@ -278,84 +278,54 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
/* Set the creation mode */
- if ((mode & O_CREAT) != 0)
- {
-#ifdef USE_GUARDED_CREATE
- *ptr++ = HTONL(NFSV3CREATE_GUARDED);
-#else
- *ptr++ = HTONL(NFSV3CREATE_EXCLUSIVE);
-#endif
- }
- else
- {
- *ptr++ = HTONL(NFSV3CREATE_UNCHECKED);
- }
-
+ *ptr++ = HTONL(NFSV3CREATE_GUARDED);
reqlen += sizeof(uint32_t);
- /* Mode information is not provided if EXCLUSIVE creation is used.
- * in this case, we must call SETATTR after successfully creating
- * the file.
+ /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS
+ * bit settings are the same (at least for the bits of interest).
*/
-#ifndef USE_GUARDED_CREATE
- if ((mode & O_CREAT) == 0)
-#endif
- {
- /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS
- * bit settings are the same (at least for the bits of interest).
- */
-
- *ptr++ = nfs_true; /* True: mode value follows */
- reqlen += sizeof(uint32_t);
+ *ptr++ = nfs_true; /* True: mode value follows */
+ reqlen += sizeof(uint32_t);
- tmp = mode & (NFSMODE_IWOTH | NFSMODE_IROTH | NFSMODE_IWGRP |
- NFSMODE_IRGRP | NFSMODE_IWUSR | NFSMODE_IRUSR);
- *ptr++ = txdr_unsigned(tmp);
- reqlen += sizeof(uint32_t);
+ tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
+ NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
+ NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR |
+ NFSMODE_SAVETEXT | NFSMODE_ISGID | NFSMODE_ISUID);
+ *ptr++ = txdr_unsigned(tmp);
+ reqlen += sizeof(uint32_t);
- /* Set the user ID to zero */
+ /* Set the user ID to zero */
- *ptr++ = nfs_true; /* True: Uid value follows */
- *ptr++ = 0; /* UID = 0 (nobody) */
- reqlen += 2*sizeof(uint32_t);
+ *ptr++ = nfs_true; /* True: Uid value follows */
+ *ptr++ = 0; /* UID = 0 (nobody) */
+ reqlen += 2*sizeof(uint32_t);
- /* Set the group ID to one */
+ /* Set the group ID to one */
- *ptr++ = nfs_true; /* True: Gid value follows */
- *ptr++ = HTONL(1); /* GID = 1 (nogroup) */
- reqlen += 2*sizeof(uint32_t);
+ *ptr++ = nfs_true; /* True: Gid value follows */
+ *ptr++ = HTONL(1); /* GID = 1 (nogroup) */
+ reqlen += 2*sizeof(uint32_t);
- /* Set the size to zero */
+ /* Set the size to zero */
- *ptr++ = nfs_true; /* True: Size value follows */
- *ptr++ = 0; /* Size = 0 */
- *ptr++ = 0;
- reqlen += 3*sizeof(uint32_t);
+ *ptr++ = nfs_true; /* True: Size value follows */
+ *ptr++ = 0; /* Size = 0 */
+ *ptr++ = 0;
+ reqlen += 3*sizeof(uint32_t);
- /* Don't change times */
+ /* Don't change times */
- *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */
- *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */
- reqlen += 2*sizeof(uint32_t);
- }
+ *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */
+ *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */
+ reqlen += 2*sizeof(uint32_t);
- /* Send the NFS request. Note there is special logic here to handle version 3
- * exclusive open semantics.
- */
+ /* Send the NFS request. */
- do
- {
- nfs_statistics(NFSPROC_CREATE);
- error = nfs_request(nmp, NFSPROC_CREATE,
- (FAR void *)&nmp->nm_msgbuffer.create, reqlen,
- (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen);
- }
-#ifdef USE_GUARDED_CREATE
- while (0);
-#else
- while (((mode & O_CREAT) != 0) && error == EOPNOTSUPP);
-#endif
+ nfs_statistics(NFSPROC_CREATE);
+ error = nfs_request(nmp, NFSPROC_CREATE,
+ (FAR void *)&nmp->nm_msgbuffer.create, reqlen,
+ (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen);
/* Check for success */
@@ -372,7 +342,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
if (!tmp)
{
ferr("ERROR: no file handle follows\n");
- return EINVAL;
+ return -EINVAL;
}
tmp = *ptr++;
@@ -385,7 +355,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
/* Save the attributes in the file data structure */
- tmp = *ptr; /* handle_follows */
+ tmp = *ptr; /* attributes_follows */
if (!tmp)
{
fwarn("WARNING: no file attributes\n");
@@ -404,14 +374,13 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
}
/****************************************************************************
- * Name: nfs_fileopen
+ * Name: nfs_filetruncate
*
* Description:
- * Truncate an open file to zero length. This is part of the file open
- * logic.
+ * Truncate an open file to length. This is part of the file open logic.
*
* Returned Value:
- * 0 on success; a positive errno value on failure.
+ * 0 on success; a negative errno value on failure.
*
****************************************************************************/
@@ -435,7 +404,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp,
reqlen += sizeof(uint32_t);
memcpy(ptr, &np->n_fhandle, np->n_fhsize);
- reqlen += (int)np->n_fhsize;
+ reqlen += uint32_alignup(np->n_fhsize);
ptr += uint32_increment(np->n_fhsize);
/* Copy the variable-length attributes */
@@ -444,8 +413,8 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp,
*ptr++ = nfs_false; /* Don't change uid */
*ptr++ = nfs_false; /* Don't change gid */
*ptr++ = nfs_true; /* Use the following size */
- *ptr++ = length; /* Truncate to the specified length */
*ptr++ = 0;
+ *ptr++ = txdr_unsigned(length); /* Truncate to the specified length */
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
*ptr++ = nfs_false; /* No guard value */
@@ -463,9 +432,29 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp,
return error;
}
- /* Indicate that the file now has zero length */
+ /* Get a pointer to the SETATTR reply data */
+
+ ptr = (FAR uint32_t *)&((FAR struct rpc_reply_setattr *)
+ nmp->nm_iobuffer)->setattr;
+
+ /* Parse file_wcc. First, check if WCC attributes follow. */
+
+ if (*ptr++ != 0)
+ {
+ /* Yes.. WCC attributes follow. But we just skip over them. */
+
+ ptr += uint32_increment(sizeof(struct wcc_attr));
+ }
+
+ /* Check if normal file attributes follow */
+
+ if (*ptr++ != 0)
+ {
+ /* Yes.. Update the cached file status in the file structure. */
+
+ nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr);
+ }
- np->n_size = 0;
return OK;
}
@@ -477,7 +466,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp,
* an existing file.
*
* Returned Value:
- * 0 on success; a positive errno value on failure.
+ * 0 on success; a negative errno value on failure.
*
****************************************************************************/
@@ -506,7 +495,7 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
/* Exit with EISDIR if we attempt to open a directory */
ferr("ERROR: Path is a directory\n");
- return EISDIR;
+ return -EISDIR;
}
/* Check if the caller has sufficient privileges to open the file */
@@ -522,7 +511,7 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
if ((tmp & (NFSMODE_IWOTH | NFSMODE_IWGRP | NFSMODE_IWUSR)) == 0)
{
ferr("ERROR: File is read-only: %08x\n", tmp);
- return EACCES;
+ return -EACCES;
}
}
@@ -533,7 +522,7 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
/* Already exists -- can't create it exclusively */
ferr("ERROR: File exists\n");
- return EEXIST;
+ return -EEXIST;
}
/* Initialize the file private data.
@@ -581,8 +570,8 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
static int nfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
- struct nfsmount *nmp;
- struct nfsnode *np;
+ FAR struct nfsmount *nmp;
+ FAR struct nfsnode *np;
int error;
/* Sanity checks */
@@ -598,22 +587,14 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
/* Pre-allocate the file private data to describe the opened file. */
- np = (struct nfsnode *)kmm_zalloc(sizeof(struct nfsnode));
+ np = (FAR struct nfsnode *)kmm_zalloc(sizeof(struct nfsnode));
if (!np)
{
ferr("ERROR: Failed to allocate private data\n");
return -ENOMEM;
}
- /* Check if the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Try to open an existing file at that path */
@@ -626,9 +607,9 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
* file.
*/
- if (error != ENOENT)
+ if (error != -ENOENT)
{
- ferr("ERROR: nfs_findnode failed: %d\n", error);
+ ferr("ERROR: nfs_fileopen failed: %d\n", error);
goto errout_with_semaphore;
}
@@ -644,7 +625,6 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
*/
ferr("ERROR: File does not exist\n");
- error = ENOENT;
goto errout_with_semaphore;
}
@@ -669,7 +649,7 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
filep->f_priv = np;
/* Then insert the new instance at the head of the list in the mountpoint
- * tructure. It needs to be there (1) to handle error conditions that effect
+ * structure. It needs to be there (1) to handle error conditions that effect
* all files, and (2) to inform the umount logic that we are busy. We
* cannot unmount the file system if this list is not empty!
*/
@@ -677,7 +657,6 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
np->n_next = nmp->nm_head;
nmp->nm_head = np;
- np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED);
nfs_semgive(nmp);
return OK;
@@ -688,7 +667,7 @@ errout_with_semaphore:
}
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -794,7 +773,7 @@ static int nfs_close(FAR struct file *filep)
*
****************************************************************************/
-static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
+static ssize_t nfs_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
{
FAR struct nfsmount *nmp;
FAR struct nfsnode *np;
@@ -818,15 +797,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
DEBUGASSERT(nmp != NULL);
- /* Make sure that the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Get the number of bytes left in the file and truncate read count so that
* it does not exceed the number of bytes left in the file.
@@ -870,8 +841,8 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
reqlen += sizeof(uint32_t);
memcpy(ptr, &np->n_fhandle, np->n_fhsize);
- reqlen += (int)np->n_fhsize;
- ptr += uint32_increment((int)np->n_fhsize);
+ reqlen += uint32_alignup(np->n_fhsize);
+ ptr += uint32_increment(np->n_fhsize);
/* Copy the file offset */
@@ -906,10 +877,11 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
/* Check if attributes are included in the responses */
tmp = *ptr++;
- if (*ptr != 0)
+ if (tmp != 0)
{
- /* Yes... just skip over the attributes for now */
+ /* Yes.. Update the cached file status in the file structure. */
+ nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr);
ptr += uint32_increment(sizeof(struct nfs_fattr));
}
@@ -954,7 +926,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -966,11 +938,11 @@ errout_with_semaphore:
*
****************************************************************************/
-static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
+static ssize_t nfs_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen)
{
- struct nfsmount *nmp;
- struct nfsnode *np;
+ FAR struct nfsmount *nmp;
+ FAR struct nfsnode *np;
ssize_t writesize;
ssize_t bufsize;
ssize_t byteswritten;
@@ -994,34 +966,25 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
DEBUGASSERT(nmp != NULL);
- /* Make sure that the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Check if the file size would exceed the range of off_t */
if (np->n_size + buflen < np->n_size)
{
- error = EFBIG;
+ error = -EFBIG;
goto errout_with_semaphore;
}
/* Now loop until we send the entire user buffer */
- writesize = 0;
for (byteswritten = 0; byteswritten < buflen; )
{
/* Make sure that the attempted write size does not exceed the RPC
* maximum.
*/
- writesize = buflen;
+ writesize = buflen - byteswritten;
if (writesize > nmp->nm_wsize)
{
writesize = nmp->nm_wsize;
@@ -1052,8 +1015,8 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
reqlen += sizeof(uint32_t);
memcpy(ptr, &np->n_fhandle, np->n_fhsize);
- reqlen += (int)np->n_fhsize;
- ptr += uint32_increment((int)np->n_fhsize);
+ reqlen += uint32_alignup(np->n_fhsize);
+ ptr += uint32_increment(np->n_fhsize);
/* Copy the file offset */
@@ -1063,13 +1026,13 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
/* Copy the count and stable values */
- *ptr++ = txdr_unsigned(buflen);
+ *ptr++ = txdr_unsigned(writesize);
*ptr++ = txdr_unsigned(committed);
reqlen += 2*sizeof(uint32_t);
/* Copy a chunk of the user data into the I/O buffer */
- *ptr++ = txdr_unsigned(buflen);
+ *ptr++ = txdr_unsigned(writesize);
reqlen += sizeof(uint32_t);
memcpy(ptr, buffer, writesize);
reqlen += uint32_alignup(writesize);
@@ -1119,7 +1082,7 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
if (tmp < 1 || tmp > writesize)
{
- error = EIO;
+ error = -EIO;
goto errout_with_semaphore;
}
@@ -1146,11 +1109,11 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
}
nfs_semgive(nmp);
- return writesize;
+ return byteswritten;
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -1163,9 +1126,8 @@ errout_with_semaphore:
static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp)
{
- struct nfsmount *nmp;
+ FAR struct nfsmount *nmp;
FAR struct nfsnode *np;
- int error;
finfo("Dup %p->%p\n", oldp, newp);
@@ -1180,16 +1142,7 @@ static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp)
DEBUGASSERT(nmp != NULL);
- /* Check if the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- nfs_semgive(nmp);
- return -error;
- }
/* Increment the reference count on the NFS node structure */
@@ -1200,15 +1153,6 @@ static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp)
newp->f_priv = np;
- /* Then insert the new instance at the head of the list in the mountpoint
- * tructure. It needs to be there (1) to handle error conditions that effect
- * all files, and (2) to inform the umount logic that we are busy. We
- * cannot unmount the file system if this list is not empty!
- */
-
- np->n_next = nmp->nm_head;
- nmp->nm_head = np;
-
nfs_semgive(nmp);
return OK;
}
@@ -1226,10 +1170,6 @@ static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct nfsmount *nmp;
FAR struct nfsnode *np;
- struct nfs_statinfo_s info;
- struct timespec ts;
- int error;
- int ret;
finfo("Buf %p\n", buf);
DEBUGASSERT(filep != NULL && buf != NULL);
@@ -1242,49 +1182,25 @@ static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
nmp = (FAR struct nfsmount *)filep->f_inode->i_private;
DEBUGASSERT(nmp != NULL);
- /* Make sure that the mount is still healthy */
+ memset(buf, 0, sizeof(*buf));
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Extract the file mode, file type, and file size from the nfsnode
* structure.
*/
- info.ns_mode = np->n_mode;
- info.ns_type = np->n_type;
- info.ns_size = (off_t)np->n_size;
+ buf->st_mode = nfs_stat_mode(np->n_mode, np->n_type);
+ buf->st_size = (off_t)np->n_size;
/* Extract time values as type time_t in units of seconds. */
- info.ns_mtime = np->n_mtime;
- info.ns_ctime = np->n_ctime;
-
- /* Use the current time for the time of last access. */
-
- ret = clock_gettime(CLOCK_REALTIME, &ts);
- if (ret < 0)
- {
- error = -get_errno();
- ferr("ERROR: clock_gettime failed: %d\n", error);
- goto errout_with_semaphore;
- }
-
- info.ns_atime = ts.tv_sec;
-
- /* Then update the stat buffer with this information */
-
- nfs_stat_common(&info, buf);
- ret = OK;
+ buf->st_atime = np->n_atime;
+ buf->st_mtime = np->n_mtime;
+ buf->st_ctime = np->n_ctime;
-errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return OK;
}
/****************************************************************************
@@ -1298,8 +1214,8 @@ errout_with_semaphore:
static int nfs_truncate(FAR struct file *filep, off_t length)
{
- struct nfsmount *nmp;
- struct nfsnode *np;
+ FAR struct nfsmount *nmp;
+ FAR struct nfsnode *np;
int error;
finfo("Truncate to %ld bytes\n", (long)length);
@@ -1312,23 +1228,14 @@ static int nfs_truncate(FAR struct file *filep, off_t length)
DEBUGASSERT(nmp != NULL);
- /* Make sure that the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Then perform the SETATTR RPC to set the new file size */
error = nfs_filetruncate(nmp, np, length);
-errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -1342,11 +1249,11 @@ errout_with_semaphore:
*
****************************************************************************/
-static int nfs_opendir(struct inode *mountpt, const char *relpath,
- struct fs_dirent_s *dir)
+static int nfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct fs_dirent_s *dir)
{
- struct nfsmount *nmp;
- struct file_handle fhandle;
+ FAR struct nfsmount *nmp;
+ FAR struct file_handle fhandle;
struct nfs_fattr obj_attributes;
uint32_t objtype;
int error;
@@ -1365,15 +1272,7 @@ static int nfs_opendir(struct inode *mountpt, const char *relpath,
memset(&dir->u.nfs, 0, sizeof(struct nfsdir_s));
- /* Make sure that the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Find the NFS node associate with the path */
@@ -1390,7 +1289,7 @@ static int nfs_opendir(struct inode *mountpt, const char *relpath,
if (objtype != NFDIR)
{
ferr("ERROR: Not a directory, type=%d\n", objtype);
- error = ENOTDIR;
+ error = -ENOTDIR;
goto errout_with_semaphore;
}
@@ -1401,12 +1300,12 @@ static int nfs_opendir(struct inode *mountpt, const char *relpath,
dir->u.nfs.nfs_fhsize = (uint8_t)fhandle.length;
DEBUGASSERT(fhandle.length <= DIRENT_NFS_MAXHANDLE);
- memcpy(dir->u.nfs.nfs_fhandle, &fhandle.handle, DIRENT_NFS_MAXHANDLE);
+ memcpy(dir->u.nfs.nfs_fhandle, &fhandle.handle, fhandle.length);
error = OK;
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -1419,15 +1318,15 @@ errout_with_semaphore:
*
****************************************************************************/
-static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
+static int nfs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
{
- struct nfsmount *nmp;
+ FAR struct nfsmount *nmp;
struct file_handle fhandle;
struct nfs_fattr obj_attributes;
uint32_t readsize;
uint32_t tmp;
- uint32_t *ptr;
- uint8_t *name;
+ FAR uint32_t *ptr;
+ FAR uint8_t *name;
unsigned int length;
int reqlen;
int error = 0;
@@ -1442,16 +1341,9 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
nmp = mountpt->i_private;
- /* Make sure that the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
+read_dir:
/* Request a block directory entries, copying directory information from
* the dirent structure.
*/
@@ -1465,8 +1357,8 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
reqlen += sizeof(uint32_t);
memcpy(ptr, dir->u.nfs.nfs_fhandle, dir->u.nfs.nfs_fhsize);
- reqlen += (int)dir->u.nfs.nfs_fhsize;
- ptr += uint32_increment((int)dir->u.nfs.nfs_fhsize);
+ reqlen += uint32_alignup(dir->u.nfs.nfs_fhsize);
+ ptr += uint32_increment(dir->u.nfs.nfs_fhsize);
/* Cookie and cookie verifier */
@@ -1513,7 +1405,7 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
* 4) Values follows indication - 4 bytes
*/
- ptr = (uint32_t *)&((FAR struct rpc_reply_readdir *)nmp->nm_iobuffer)->readdir;
+ ptr = (FAR uint32_t *)&((FAR struct rpc_reply_readdir *)nmp->nm_iobuffer)->readdir;
/* Check if attributes follow, if 0 so Skip over the attributes */
@@ -1530,6 +1422,7 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
memcpy(dir->u.nfs.nfs_verifier, ptr, DIRENT_NFS_VERFLEN);
ptr += uint32_increment(DIRENT_NFS_VERFLEN);
+next_entry:
/* Check if values follow. If no values follow, then the EOF indication
* will appear next.
*/
@@ -1545,7 +1438,8 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
if (tmp != 0)
{
finfo("End of directory\n");
- error = ENOENT;
+ error = -ENOENT;
+ goto errout_with_semaphore;
}
/* What would it mean if there were not data and we not at the end of
@@ -1555,10 +1449,8 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
else
{
finfo("No data but not end of directory???\n");
- error = EAGAIN;
+ goto read_dir;
}
-
- goto errout_with_semaphore;
}
/* If we are not at the end of the directory listing, then a set of entries
@@ -1592,8 +1484,6 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
dir->u.nfs.nfs_cookie[0] = *ptr++;
dir->u.nfs.nfs_cookie[1] = *ptr++;
- ptr++; /* Just skip over the nextentry for now */
-
/* Return the name of the node to the caller */
if (length > NAME_MAX)
@@ -1605,12 +1495,18 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
dir->fd_dir.d_name[length] = '\0';
finfo("name: \"%s\"\n", dir->fd_dir.d_name);
+ if (strcmp(dir->fd_dir.d_name, ".") == 0 ||
+ strcmp(dir->fd_dir.d_name, "..") == 0)
+ {
+ goto next_entry; /* Skip . and .. */
+ }
+
/* Get the file attributes associated with this name and return
* the file type.
*/
fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize;
- memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, DIRENT_NFS_MAXHANDLE);
+ memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, fhandle.length);
error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle, &obj_attributes, NULL);
if (error != OK)
@@ -1626,8 +1522,14 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
default:
case NFNON: /* Unknown type */
+ break;
+
case NFSOCK: /* Socket */
+ dir->fd_dir.d_type = DTYPE_SOCK;
+ break;
+
case NFLNK: /* Symbolic link */
+ dir->fd_dir.d_type = DTYPE_LINK;
break;
case NFREG: /* Regular file */
@@ -1643,6 +1545,9 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
break;
case NFFIFO: /* Named FIFO */
+ dir->fd_dir.d_type = DTYPE_FIFO;
+ break;
+
case NFCHR: /* Character special device file */
dir->fd_dir.d_type = DTYPE_CHR;
break;
@@ -1652,7 +1557,7 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -1702,17 +1607,18 @@ static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt,
if ((argp->flags & NFSMNT_TIMEO) != 0 && argp->timeo > 0)
{
- uint32_t tmp = ((uint32_t)argp->timeo * NFS_HZ + 5) / 10;
- if (tmp < NFS_MINTIMEO)
+ if (argp->timeo < NFS_MINTIMEO)
{
- tmp = NFS_MINTIMEO;
+ nprmt->timeo = NFS_MINTIMEO;
}
- else if (tmp > NFS_MAXTIMEO)
+ else if (argp->timeo > NFS_MAXTIMEO)
{
- tmp = NFS_MAXTIMEO;
+ nprmt->timeo = NFS_MAXTIMEO;
+ }
+ else
+ {
+ nprmt->timeo = argp->timeo;
}
-
- nprmt->timeo = tmp;
}
/* Get the selected retransmission count */
@@ -1840,9 +1746,7 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data,
{
FAR struct nfs_args *argp = (FAR struct nfs_args *)data;
FAR struct nfsmount *nmp;
- struct rpcclnt *rpc;
- struct rpc_call_fs getattr;
- struct rpc_reply_getattr resok;
+ FAR struct rpcclnt *rpc;
struct nfs_mount_parameters nprmt;
uint32_t buflen;
uint32_t tmp;
@@ -1895,7 +1799,7 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data,
if (!nmp)
{
ferr("ERROR: Failed to allocate mountpoint structure\n");
- return ENOMEM;
+ return -ENOMEM;
}
/* Save the allocated I/O buffer size */
@@ -1921,31 +1825,26 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data,
/* Set initial values of other fields */
- nmp->nm_timeo = nprmt.timeo;
- nmp->nm_retry = nprmt.retry;
nmp->nm_wsize = nprmt.wsize;
nmp->nm_rsize = nprmt.rsize;
nmp->nm_readdirsize = nprmt.readdirsize;
- nmp->nm_fhsize = NFSX_V3FHMAX;
strncpy(nmp->nm_path, argp->path, 90);
memcpy(&nmp->nm_nam, &argp->addr, argp->addrlen);
/* Set up the sockets and per-host congestion */
- nmp->nm_sotype = argp->sotype;
-
- if (nmp->nm_sotype == SOCK_DGRAM)
+ if (argp->sotype == SOCK_DGRAM)
{
/* Connection-less... connect now */
/* Create an instance of the rpc state structure */
- rpc = (struct rpcclnt *)kmm_zalloc(sizeof(struct rpcclnt));
+ rpc = (FAR struct rpcclnt *)kmm_zalloc(sizeof(struct rpcclnt));
if (!rpc)
{
ferr("ERROR: Failed to allocate rpc structure\n");
- return ENOMEM;
+ return -ENOMEM;
}
finfo("Connecting\n");
@@ -1954,8 +1853,9 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data,
rpc->rc_path = nmp->nm_path;
rpc->rc_name = &nmp->nm_nam;
- rpc->rc_sotype = nmp->nm_sotype;
- rpc->rc_retry = nmp->nm_retry;
+ rpc->rc_sotype = argp->sotype;
+ rpc->rc_timeo = nprmt.timeo;
+ rpc->rc_retry = nprmt.retry;
nmp->nm_rpcclnt = rpc;
@@ -1967,29 +1867,18 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data,
}
}
- nmp->nm_mounted = true;
- nmp->nm_so = nmp->nm_rpcclnt->rc_so;
nmp->nm_fhsize = nmp->nm_rpcclnt->rc_fhsize;
- memcpy(&nmp->nm_fh, &nmp->nm_rpcclnt->rc_fh, sizeof(nfsfh_t));
-
- /* Get the file attributes */
+ nmp->nm_fh = &nmp->nm_rpcclnt->rc_fh;
- getattr.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
- memcpy(&getattr.fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t));
+ /* Get the file sytem info */
- error = nfs_request(nmp, NFSPROC_GETATTR,
- (FAR void *)&getattr, sizeof(struct FS3args),
- (FAR void *)&resok, sizeof(struct rpc_reply_getattr));
+ error = nfs_fsinfo(nmp);
if (error)
{
- ferr("ERROR: nfs_request failed: %d\n", error);
+ ferr("ERROR: nfs_fsinfo failed: %d\n", error);
goto bad;
}
- /* Save the file attributes */
-
- memcpy(&nmp->nm_fattr, &resok.attr, sizeof(struct nfs_fattr));
-
/* Mounted! */
*handle = (FAR void *)nmp;
@@ -2003,21 +1892,15 @@ bad:
{
/* Disconnect from the server */
- rpcclnt_disconnect(nmp->nm_rpcclnt);
-
- /* Free connection-related resources */
-
- nxsem_destroy(&nmp->nm_sem);
- if (nmp->nm_so)
- {
- kmm_free(nmp->nm_so);
- }
-
if (nmp->nm_rpcclnt)
{
+ rpcclnt_disconnect(nmp->nm_rpcclnt);
kmm_free(nmp->nm_rpcclnt);
}
+ /* Free connection-related resources */
+
+ nxsem_destroy(&nmp->nm_sem);
kmm_free(nmp);
}
@@ -2062,7 +1945,7 @@ static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
* no open file references.
*/
- error = (flags != 0) ? ENOSYS : EBUSY;
+ error = (flags != 0) ? -ENOSYS : -EBUSY;
goto errout_with_semaphore;
}
@@ -2081,15 +1964,14 @@ static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
/* And free any allocated resources */
nxsem_destroy(&nmp->nm_sem);
- kmm_free(nmp->nm_so);
kmm_free(nmp->nm_rpcclnt);
kmm_free(nmp);
- return -error;
+ return error;
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -2099,30 +1981,32 @@ errout_with_semaphore:
* Return information about root directory.
*
* Returned Value:
- * 0 on success; positive errno value on failure
+ * 0 on success; negative errno value on failure
*
* Assumptions:
* The caller has exclusive access to the NFS mount structure
*
****************************************************************************/
-int nfs_fsinfo(FAR struct nfsmount *nmp)
+static int nfs_fsinfo(FAR struct nfsmount *nmp)
{
- struct rpc_call_fs fsinfo;
- struct rpc_reply_fsinfo fsp;
+ FAR struct rpc_call_fs *fsinfo;
+ FAR struct rpc_reply_getattr *attr;
+ FAR uint32_t *ptr;
uint32_t pref;
uint32_t max;
int error = 0;
- fsinfo.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
- fsinfo.fs.fsroot.handle = nmp->nm_fh;
+ fsinfo = &nmp->nm_msgbuffer.fsinfo;
+ fsinfo->fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
+ memcpy(&fsinfo->fs.fsroot.handle, nmp->nm_fh, nmp->nm_fhsize);
/* Request FSINFO from the server */
nfs_statistics(NFSPROC_FSINFO);
error = nfs_request(nmp, NFSPROC_FSINFO,
- (FAR void *)&fsinfo, sizeof(struct FS3args),
- (FAR void *)&fsp, sizeof(struct rpc_reply_fsinfo));
+ (FAR void *)fsinfo, sizeof(struct FS3args),
+ (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen);
if (error)
{
return error;
@@ -2130,33 +2014,21 @@ int nfs_fsinfo(FAR struct nfsmount *nmp)
/* Save the root file system attributes */
-#if 0
- memcpy(&nmp->nm_fattr. &fsp.obj_attributes, sizeof(struct nfs_fattr));
-#endif
-
- pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_wtpref);
- if (pref < nmp->nm_wsize)
+ ptr = (FAR uint32_t *)&((FAR struct rpc_reply_fsinfo *)nmp->nm_iobuffer)->fsinfo;
+ if (*ptr++ != 0)
{
- nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1);
+ memcpy(&nmp->nm_fattr, ptr, sizeof(struct nfs_fattr));
+ ptr += uint32_increment(sizeof(struct nfs_fattr));
}
- max = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_wtmax);
- if (max < nmp->nm_wsize)
- {
- nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
- if (nmp->nm_wsize == 0)
- {
- nmp->nm_wsize = max;
- }
- }
+ max = fxdr_unsigned(uint32_t, *ptr++);
+ pref = fxdr_unsigned(uint32_t, *ptr++);
+ ptr += 1; /* Skip fs_rtmult */
- pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_rtpref);
if (pref < nmp->nm_rsize)
{
nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1);
}
-
- max = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_rtmax);
if (max < nmp->nm_rsize)
{
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
@@ -2166,19 +2038,44 @@ int nfs_fsinfo(FAR struct nfsmount *nmp)
}
}
- pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_dtpref);
+ max = fxdr_unsigned(uint32_t, *ptr++);
+ pref = fxdr_unsigned(uint32_t, *ptr++);
+ ptr += 1; /* Skip fs_wtmult */
+
+ if (pref < nmp->nm_wsize)
+ {
+ nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1);
+ }
+ if (max < nmp->nm_wsize)
+ {
+ nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
+ if (nmp->nm_wsize == 0)
+ {
+ nmp->nm_wsize = max;
+ }
+ }
+
+ pref = fxdr_unsigned(uint32_t, *ptr++);
if (pref < nmp->nm_readdirsize)
{
nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1);
}
- if (max < nmp->nm_readdirsize)
+ /* Get the file attributes if needed */
+
+ if (nmp->nm_fattr.fa_type == 0)
{
- nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
- if (nmp->nm_readdirsize == 0)
+ nfs_statistics(NFSPROC_GETATTR);
+ error = nfs_request(nmp, NFSPROC_GETATTR,
+ (FAR void *)fsinfo, sizeof(struct FS3args),
+ (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen);
+ if (error)
{
- nmp->nm_readdirsize = max;
+ return error;
}
+
+ attr = (FAR struct rpc_reply_getattr *)nmp->nm_iobuffer;
+ memcpy(&nmp->nm_fattr, &attr->attr, sizeof(struct nfs_fattr));
}
return OK;
@@ -2211,25 +2108,15 @@ static int nfs_statfs(FAR struct inode *mountpt, FAR struct statfs *sbp)
nmp = (FAR struct nfsmount *)mountpt->i_private;
- /* Check if the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Fill in the statfs info */
sbp->f_type = NFS_SUPER_MAGIC;
- nfs_fsinfo(nmp);
-
fsstat = &nmp->nm_msgbuffer.fsstat;
fsstat->fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
- memcpy(&fsstat->fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t));
+ memcpy(&fsstat->fs.fsroot.handle, nmp->nm_fh, nmp->nm_fhsize);
nfs_statistics(NFSPROC_FSSTAT);
error = nfs_request(nmp, NFSPROC_FSSTAT,
@@ -2256,7 +2143,7 @@ static int nfs_statfs(FAR struct inode *mountpt, FAR struct statfs *sbp)
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -2270,7 +2157,7 @@ errout_with_semaphore:
*
****************************************************************************/
-static int nfs_remove(struct inode *mountpt, const char *relpath)
+static int nfs_remove(FAR struct inode *mountpt, FAR const char *relpath)
{
FAR struct nfsmount *nmp;
struct file_handle fhandle;
@@ -2289,15 +2176,7 @@ static int nfs_remove(struct inode *mountpt, const char *relpath)
nmp = (FAR struct nfsmount *)mountpt->i_private;
- /* Check if the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Find the NFS node of the directory containing the file to be deleted */
@@ -2319,7 +2198,7 @@ static int nfs_remove(struct inode *mountpt, const char *relpath)
reqlen += sizeof(uint32_t);
memcpy(ptr, &fhandle.handle, fhandle.length);
- reqlen += (int)fhandle.length;
+ reqlen += uint32_alignup(fhandle.length);
ptr += uint32_increment(fhandle.length);
/* Copy the variable-length file name */
@@ -2341,7 +2220,7 @@ static int nfs_remove(struct inode *mountpt, const char *relpath)
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -2355,9 +2234,9 @@ errout_with_semaphore:
*
****************************************************************************/
-static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
+static int nfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, mode_t mode)
{
- struct nfsmount *nmp;
+ FAR struct nfsmount *nmp;
struct file_handle fhandle;
struct nfs_fattr fattr;
char dirname[NAME_MAX + 1];
@@ -2375,15 +2254,7 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
nmp = (FAR struct nfsmount *) mountpt->i_private;
- /* Check if the mount is still healthy */
-
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount: %d\n", error);
- goto errout_with_semaphore;
- }
/* Find the NFS node of the directory containing the directory to be created */
@@ -2391,7 +2262,7 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
if (error != OK)
{
ferr("ERROR: nfs_finddir returned: %d\n", error);
- return error;
+ goto errout_with_semaphore;
}
/* Format the MKDIR call message arguments */
@@ -2406,7 +2277,7 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
memcpy(ptr, &fhandle.handle, fhandle.length);
ptr += uint32_increment(fhandle.length);
- reqlen += (int)fhandle.length;
+ reqlen += uint32_alignup(fhandle.length);
/* Copy the variable-length directory name */
@@ -2428,7 +2299,8 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
- NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR);
+ NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR |
+ NFSMODE_SAVETEXT | NFSMODE_ISGID | NFSMODE_ISUID);
*ptr++ = txdr_unsigned(tmp);
reqlen += sizeof(uint32_t);
@@ -2468,7 +2340,7 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -2482,9 +2354,9 @@ errout_with_semaphore:
*
****************************************************************************/
-static int nfs_rmdir(struct inode *mountpt, const char *relpath)
+static int nfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath)
{
- struct nfsmount *nmp;
+ FAR struct nfsmount *nmp;
struct file_handle fhandle;
struct nfs_fattr fattr;
char dirname[NAME_MAX + 1];
@@ -2499,17 +2371,9 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath)
/* Get the mountpoint private data from the inode structure */
- nmp = (struct nfsmount *)mountpt->i_private;
-
- /* Check if the mount is still healthy */
+ nmp = (FAR struct nfsmount *)mountpt->i_private;
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Find the NFS node of the directory containing the directory to be removed */
@@ -2517,7 +2381,7 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath)
if (error != OK)
{
ferr("ERROR: nfs_finddir returned: %d\n", error);
- return error;
+ goto errout_with_semaphore;
}
/* Set up the RMDIR call message arguments */
@@ -2531,7 +2395,7 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath)
reqlen += sizeof(uint32_t);
memcpy(ptr, &fhandle.handle, fhandle.length);
- reqlen += (int)fhandle.length;
+ reqlen += uint32_alignup(fhandle.length);
ptr += uint32_increment(fhandle.length);
/* Copy the variable-length directory name */
@@ -2553,7 +2417,7 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath)
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
@@ -2567,10 +2431,10 @@ errout_with_semaphore:
*
****************************************************************************/
-static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
- const char *newrelpath)
+static int nfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath,
+ FAR const char *newrelpath)
{
- struct nfsmount *nmp;
+ FAR struct nfsmount *nmp;
struct file_handle from_handle;
struct file_handle to_handle;
char from_name[NAME_MAX + 1];
@@ -2587,17 +2451,9 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
/* Get the mountpoint private data from the inode structure */
- nmp = (struct nfsmount *)mountpt->i_private;
-
- /* Check if the mount is still healthy */
+ nmp = (FAR struct nfsmount *)mountpt->i_private;
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount returned: %d\n", error);
- goto errout_with_semaphore;
- }
/* Find the NFS node of the directory containing the 'from' object */
@@ -2605,16 +2461,16 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
if (error != OK)
{
ferr("ERROR: nfs_finddir returned: %d\n", error);
- return error;
+ goto errout_with_semaphore;
}
- /* Find the NFS node of the directory containing the 'from' object */
+ /* Find the NFS node of the directory containing the 'to' object */
error = nfs_finddir(nmp, newrelpath, &to_handle, &fattr, to_name);
if (error != OK)
{
ferr("ERROR: nfs_finddir returned: %d\n", error);
- return error;
+ goto errout_with_semaphore;
}
/* Format the RENAME RPC arguments */
@@ -2628,7 +2484,7 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
reqlen += sizeof(uint32_t);
memcpy(ptr, &from_handle.handle, from_handle.length);
- reqlen += (int)from_handle.length;
+ reqlen += uint32_alignup(from_handle.length);
ptr += uint32_increment(from_handle.length);
/* Copy the variable-length 'from' object name */
@@ -2649,7 +2505,7 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
memcpy(ptr, &to_handle.handle, to_handle.length);
ptr += uint32_increment(to_handle.length);
- reqlen += (int)to_handle.length;
+ reqlen += uint32_alignup(to_handle.length);
/* Copy the variable-length 'to' object name */
@@ -2670,49 +2526,34 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
/****************************************************************************
- * Name: nfs_stat_common
+ * Name: nfs_stat_mode
*
* Description:
- * Return information about the file system object described by 'info'
+ * Convert NFSv3's type and mode to NuttX's mode
*
* Returned Value:
- * None
+ * Return NuttX's mode
*
****************************************************************************/
-static void nfs_stat_common(FAR struct nfs_statinfo_s *info,
- FAR struct stat *buf)
+static mode_t nfs_stat_mode(unsigned int mode, unsigned int type)
{
- mode_t mode;
-
- /* Here we exploit the fact that most mode bits are the same in NuttX
+ /* Here we exploit the fact all mode bits are the same in NuttX
* as in the NFSv3 spec.
*/
- mode = info->ns_mode &
- (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
- NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
- NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR);
-
- /* Handle the cases that are not the same */
-
- if ((info->ns_mode & NFSMODE_ISGID) != 0)
- {
- mode |= S_ISGID;
- }
-
- if ((info->ns_mode & NFSMODE_ISUID) != 0)
- {
- mode |= S_ISUID;
- }
+ mode &= (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
+ NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
+ NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR |
+ NFSMODE_SAVETEXT | NFSMODE_ISGID | NFSMODE_ISUID);
/* Now OR in the file type */
- switch (info->ns_type)
+ switch (type)
{
default:
case NFNON: /* Unknown type */
@@ -2743,17 +2584,11 @@ static void nfs_stat_common(FAR struct nfs_statinfo_s *info,
break;
case NFFIFO: /* Named pipe */
- mode |= S_IFMT;
+ mode |= S_IFIFO;
break;
}
- buf->st_mode = mode;
- buf->st_size = (off_t)info->ns_size;
- buf->st_blksize = 0;
- buf->st_blocks = 0;
- buf->st_mtime = info->ns_mtime;
- buf->st_atime = info->ns_atime;
- buf->st_ctime = info->ns_ctime;
+ return mode;
}
/****************************************************************************
@@ -2767,13 +2602,12 @@ static void nfs_stat_common(FAR struct nfs_statinfo_s *info,
*
****************************************************************************/
-static int nfs_stat(struct inode *mountpt, const char *relpath,
- struct stat *buf)
+static int nfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf)
{
- struct nfsmount *nmp;
+ FAR struct nfsmount *nmp;
struct file_handle fhandle;
- struct nfs_fattr obj_attributes;
- struct nfs_statinfo_s info;
+ struct nfs_fattr attributes;
struct timespec ts;
int error;
@@ -2786,19 +2620,13 @@ static int nfs_stat(struct inode *mountpt, const char *relpath,
nmp = (FAR struct nfsmount *)mountpt->i_private;
DEBUGASSERT(nmp && buf);
- /* Check if the mount is still healthy */
+ memset(buf, 0, sizeof(*buf));
nfs_semtake(nmp);
- error = nfs_checkmount(nmp);
- if (error != OK)
- {
- ferr("ERROR: nfs_checkmount failed: %d\n", error);
- goto errout_with_semaphore;
- }
/* Get the file handle attributes of the requested node */
- error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL);
+ error = nfs_findnode(nmp, relpath, &fhandle, &attributes, NULL);
if (error != OK)
{
ferr("ERROR: nfs_findnode failed: %d\n", error);
@@ -2807,26 +2635,22 @@ static int nfs_stat(struct inode *mountpt, const char *relpath,
/* Extract the file mode, file type, and file size. */
- info.ns_mode = fxdr_unsigned(uint16_t, obj_attributes.fa_mode);
- info.ns_type = fxdr_unsigned(uint8_t, obj_attributes.fa_type);
- info.ns_size = fxdr_hyper(&obj_attributes.fa_size);
+ buf->st_mode = nfs_stat_mode(fxdr_unsigned(uint16_t, attributes.fa_mode),
+ fxdr_unsigned(uint8_t, attributes.fa_type));
+ buf->st_size = fxdr_hyper(&attributes.fa_size);
/* Extract time values as type time_t in units of seconds */
- fxdr_nfsv3time(&obj_attributes.fa_mtime, &ts);
- info.ns_mtime = ts.tv_sec;
-
- fxdr_nfsv3time(&obj_attributes.fa_atime, &ts);
- info.ns_atime = ts.tv_sec;
+ fxdr_nfsv3time(&attributes.fa_mtime, &ts);
+ buf->st_mtime = ts.tv_sec;
- fxdr_nfsv3time(&obj_attributes.fa_ctime, &ts);
- info.ns_ctime = ts.tv_sec;
+ fxdr_nfsv3time(&attributes.fa_atime, &ts);
+ buf->st_atime = ts.tv_sec;
- /* Then update the stat buffer with this information */
-
- nfs_stat_common(&info, buf);
+ fxdr_nfsv3time(&attributes.fa_ctime, &ts);
+ buf->st_ctime = ts.tv_sec;
errout_with_semaphore:
nfs_semgive(nmp);
- return -error;
+ return error;
}
diff --git a/fs/nfs/rpc.h b/fs/nfs/rpc.h
index d392474..1139338 100644
--- a/fs/nfs/rpc.h
+++ b/fs/nfs/rpc.h
@@ -75,6 +75,8 @@
****************************************************************************/
#include <sys/types.h>
+#include <nuttx/net/net.h>
+
#include "nfs_proto.h"
/****************************************************************************
@@ -161,25 +163,13 @@
* Public Types
****************************************************************************/
-/* Global RPC statistics */
-
-#ifdef CONFIG_NFS_STATISTICS
-struct rpcstats
-{
- int rpcretries;
- int rpcrequests;
- int rpctimeouts;
- int rpcinvalid;
-};
-#endif
-
/* PMAP headers */
struct call_args_pmap
{
uint32_t prog;
uint32_t vers;
- uint32_t proc;
+ uint32_t prot;
uint32_t port;
};
@@ -218,7 +208,7 @@ struct call_result_mount
uint32_t status;
struct file_handle fhandle;
uint32_t authlen;
- uint32_t autolist[AUTH_MAX];
+ uint32_t authlist[AUTH_MAX];
};
/* Generic RPC call headers */
@@ -231,11 +221,11 @@ struct rpc_auth_info
struct auth_unix
{
- int32_t stamp;
- uint8_t hostname; /* null */
- int32_t uid;
- int32_t gid;
- int32_t gidlist; /* null */
+ uint32_t stamp;
+ uint32_t hostname; /* null */
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t gidlist; /* null */
};
struct rpc_call_header
@@ -349,11 +339,7 @@ struct rpc_reply_header
struct nfs_reply_header
{
- uint32_t rp_xid; /* Request transaction id */
- uint32_t rp_direction; /* Call direction (1) */
- uint32_t type;
- struct rpc_auth_info rpc_verfi;
- uint32_t status;
+ struct rpc_reply_header rh;
uint32_t nfs_status;
};
@@ -376,115 +362,100 @@ struct rpc_reply_umount
struct rpc_reply_create
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct CREATE3resok create;
};
struct rpc_reply_lookup
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct LOOKUP3resok lookup;
};
struct rpc_reply_write
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct WRITE3resok write; /* Variable length */
};
struct rpc_reply_read
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct READ3resok read; /* Variable length */
};
#define SIZEOF_rpc_reply_read(n) \
- (sizeof(struct rpc_reply_header) + sizeof(uint32_t) + \
- SIZEOF_READ3resok(n))
+ (sizeof(struct nfs_reply_header) + SIZEOF_READ3resok(n))
struct rpc_reply_remove
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct REMOVE3resok remove;
};
struct rpc_reply_rename
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct RENAME3resok rename;
};
struct rpc_reply_mkdir
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct MKDIR3resok mkdir;
};
struct rpc_reply_rmdir
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct RMDIR3resok rmdir;
};
struct rpc_reply_readdir
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct READDIR3resok readdir;
};
#define SIZEOF_rpc_reply_readdir(n) \
- (sizeof(struct rpc_reply_header) + sizeof(uint32_t) + \
- SIZEOF_READDIR3resok(n))
+ (sizeof(struct nfs_reply_header) + SIZEOF_READDIR3resok(n))
struct rpc_reply_fsinfo
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct nfsv3_fsinfo fsinfo;
};
struct rpc_reply_fsstat
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct nfs_statfs fsstat;
};
struct rpc_reply_getattr
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct nfs_fattr attr;
};
struct rpc_reply_setattr
{
- struct rpc_reply_header rh;
- uint32_t status;
+ struct nfs_reply_header rh;
struct SETATTR3resok setattr;
};
-struct rpcclnt
+struct rpcclnt
{
- nfsfh_t rc_fh; /* File handle of the root directory */
- uint8_t rc_fhsize; /* File size of the root directory */
- char *rc_path; /* Server's path of the mounted directory */
+ nfsfh_t rc_fh; /* File handle of the root directory */
+ uint8_t rc_fhsize; /* File size of the root directory */
+ FAR char *rc_path; /* Server's path of the mounted directory */
- struct sockaddr *rc_name;
- struct socket *rc_so; /* RPC socket */
+ FAR struct sockaddr *rc_name;
+ struct socket rc_so; /* RPC socket */
- bool rc_timeout; /* Receipt of reply timed out */
- uint8_t rc_sotype; /* Type of socket */
- uint8_t rc_retry; /* Max retries */
+ uint8_t rc_sotype; /* Type of socket */
+ uint8_t rc_timeo; /* Timeout value (in deciseconds) */
+ uint8_t rc_retry; /* Max retries */
};
/****************************************************************************
@@ -493,12 +464,10 @@ struct rpcclnt
void rpcclnt_init(void);
int rpcclnt_connect(FAR struct rpcclnt *rpc);
-int rpcclnt_reconnect(FAR struct rpcclnt *rpc);
void rpcclnt_disconnect(FAR struct rpcclnt *rpc);
int rpcclnt_umount(FAR struct rpcclnt *rpc);
-void rpcclnt_safedisconnect(FAR struct rpcclnt *rpc);
-int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, int version,
- FAR void *request, size_t reqlen,
+int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
+ int version, FAR void *request, size_t reqlen,
FAR void *response, size_t resplen);
#endif /* __FS_NFS_RPC_H */
diff --git a/fs/nfs/rpc_clnt.c b/fs/nfs/rpc_clnt.c
index 180c234..aa40e46 100644
--- a/fs/nfs/rpc_clnt.c
+++ b/fs/nfs/rpc_clnt.c
@@ -89,7 +89,6 @@
#include <stdlib.h>
#include <string.h>
#include <debug.h>
-#include <nuttx/kmalloc.h>
#include "xdr_subs.h"
#include "nfs_proto.h"
@@ -108,6 +107,22 @@
#endif
/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Global RPC statistics */
+
+#ifdef CONFIG_NFS_STATISTICS
+struct rpcstats
+{
+ int rpcretries;
+ int rpcrequests;
+ int rpctimeouts;
+ int rpcinvalid;
+};
+#endif
+
+/****************************************************************************
* Private Data
****************************************************************************/
@@ -116,11 +131,6 @@
static uint32_t rpc_reply;
static uint32_t rpc_call;
static uint32_t rpc_vers;
-static uint32_t rpc_msgdenied;
-static uint32_t rpc_mismatch;
-static uint32_t rpc_auth_unix;
-static uint32_t rpc_msgaccepted;
-static uint32_t rpc_autherr;
static uint32_t rpc_auth_null;
/* Global statics for all client instances. Cleared by NuttX on boot-up. */
@@ -133,12 +143,12 @@ static struct rpcstats rpcstats;
* Private Function Prototypes
****************************************************************************/
-static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog,
+static int rpcclnt_send(FAR struct rpcclnt *rpc,
FAR void *call, int reqlen);
-static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname,
- int proc, int program, void *reply, size_t resplen);
-static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
- void *reply, size_t resplen);
+static int rpcclnt_receive(FAR struct rpcclnt *rpc,
+ FAR void *reply, size_t resplen);
+static int rpcclnt_reply(FAR struct rpcclnt *rpc,
+ FAR void *reply, size_t resplen);
static uint32_t rpcclnt_newxid(void);
static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
uint32_t xid, int procid, int prog, int vers);
@@ -154,11 +164,11 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
* This is the nfs send routine.
*
* Returned Value:
- * Returns zero on success or a (positive) errno value on failure.
+ * Returns zero on success or a (negative) errno value on failure.
*
****************************************************************************/
-static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog,
+static int rpcclnt_send(FAR struct rpcclnt *rpc,
FAR void *call, int reqlen)
{
ssize_t nbytes;
@@ -170,13 +180,13 @@ static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog,
* On failure, it returns a negated errno value.
*/
- nbytes = psock_send(rpc->rc_so, call, reqlen, 0);
+ nbytes = psock_send(&rpc->rc_so, call, reqlen, 0);
if (nbytes < 0)
{
/* psock_sendto failed */
- ret = (int)-nbytes;
+ ret = nbytes;
ferr("ERROR: psock_sendto failed: %d\n", ret);
}
@@ -187,24 +197,21 @@ static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog,
* Name: rpcclnt_receive
*
* Description:
- * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all done
- * by psock_recvfrom().
+ * Receive a Sun RPC Request/Reply.
*
****************************************************************************/
-static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname,
- int proc, int program, FAR void *reply,
- size_t resplen)
+static int rpcclnt_receive(FAR struct rpcclnt *rpc,
+ FAR void *reply, size_t resplen)
{
ssize_t nbytes;
int error = 0;
- socklen_t fromlen = sizeof(struct sockaddr);
- nbytes = psock_recvfrom(rpc->rc_so, reply, resplen, 0, aname, &fromlen);
+ nbytes = psock_recv(&rpc->rc_so, reply, resplen, 0);
if (nbytes < 0)
{
- error = (int)-nbytes;
- ferr("ERROR: psock_recvfrom failed: %d\n", error);
+ error = nbytes;
+ ferr("ERROR: psock_recv failed: %d\n", error);
}
return error;
@@ -218,26 +225,17 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname,
*
****************************************************************************/
-static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
+static int rpcclnt_reply(FAR struct rpcclnt *rpc,
FAR void *reply, size_t resplen)
{
int error;
/* Get the next RPC reply from the socket */
- error = rpcclnt_receive(rpc, rpc->rc_name, procid, prog, reply, resplen);
+ error = rpcclnt_receive(rpc, reply, resplen);
if (error != 0)
{
ferr("ERROR: rpcclnt_receive returned: %d\n", error);
-
- /* If we failed because of a timeout, then try sending the CALL
- * message again.
- */
-
- if (error == EAGAIN || error == ETIMEDOUT)
- {
- rpc->rc_timeout = true;
- }
}
/* Get the xid and check that it is an RPC replysvr */
@@ -251,7 +249,7 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
{
ferr("ERROR: Different RPC REPLY returned\n");
rpc_statistics(rpcinvalid);
- error = EPROTO;
+ error = -EPROTO;
}
}
@@ -271,9 +269,9 @@ static uint32_t rpcclnt_newxid(void)
static uint32_t rpcclnt_xid = 0;
static uint32_t rpcclnt_xid_touched = 0;
- srand(time(NULL));
if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0))
{
+ srand(time(NULL));
rpcclnt_xid = rand();
rpcclnt_xid_touched = 1;
}
@@ -342,11 +340,6 @@ void rpcclnt_init(void)
rpc_reply = txdr_unsigned(RPC_REPLY);
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
- rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
- rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
- rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
- rpc_autherr = txdr_unsigned(RPC_AUTHERR);
- rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
rpc_auth_null = txdr_unsigned(RPCAUTH_NULL);
finfo("RPC initialized\n");
@@ -361,13 +354,12 @@ void rpcclnt_init(void)
*
****************************************************************************/
-int rpcclnt_connect(struct rpcclnt *rpc)
+int rpcclnt_connect(FAR struct rpcclnt *rpc)
{
- struct socket *so;
int error;
- struct sockaddr *saddr;
+ FAR struct sockaddr *saddr;
struct sockaddr_in sin;
- struct sockaddr_in *sa;
+ FAR struct sockaddr_in *sa;
union
{
@@ -383,7 +375,6 @@ int rpcclnt_connect(struct rpcclnt *rpc)
struct timeval tv;
uint16_t tport;
- int errval;
finfo("Connecting\n");
@@ -391,38 +382,25 @@ int rpcclnt_connect(struct rpcclnt *rpc)
saddr = rpc->rc_name;
- /* Create an instance of the socket state structure */
-
- so = (struct socket *)kmm_zalloc(sizeof(struct socket));
- if (!so)
- {
- ferr("ERROR: Failed to allocate socket structure\n");
- return ENOMEM;
- }
-
- error = psock_socket(saddr->sa_family, rpc->rc_sotype, IPPROTO_UDP, so);
+ error = psock_socket(saddr->sa_family, rpc->rc_sotype, IPPROTO_UDP, &rpc->rc_so);
if (error < 0)
{
- errval = -error;
- ferr("ERROR: psock_socket failed: %d", errval);
- return errval;
+ ferr("ERROR: psock_socket failed: %d", error);
+ return error;
}
- rpc->rc_so = so;
-
/* Always set receive timeout to detect server crash and reconnect.
* Otherwise, we can get stuck in psock_receive forever.
*/
- tv.tv_sec = 1;
- tv.tv_usec = 0;
+ tv.tv_sec = rpc->rc_timeo / 10;
+ tv.tv_usec = (rpc->rc_timeo % 10) * 100000;
- error = psock_setsockopt(rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO,
- (const void *)&tv, sizeof(tv));
+ error = psock_setsockopt(&rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO,
+ (FAR const void *)&tv, sizeof(tv));
if (error < 0)
{
- errval = -error;
- ferr("ERROR: psock_setsockopt failed: %d\n", errval);
+ ferr("ERROR: psock_setsockopt failed: %d\n", error);
goto bad;
}
@@ -435,24 +413,22 @@ int rpcclnt_connect(struct rpcclnt *rpc)
sin.sin_addr.s_addr = INADDR_ANY;
tport = 1024;
- errval = 0;
do
{
tport--;
sin.sin_port = htons(tport);
- error = psock_bind(rpc->rc_so, (struct sockaddr *)&sin, sizeof(sin));
+ error = psock_bind(&rpc->rc_so, (struct sockaddr *)&sin, sizeof(sin));
if (error < 0)
{
- errval = -error;
- ferr("ERROR: psock_bind failed: %d\n", errval);
+ ferr("ERROR: psock_bind failed: %d\n", error);
}
}
- while (errval == EADDRINUSE && tport > 1024 / 2);
+ while (error == -EADDRINUSE && tport > 1024 / 2);
if (error)
{
- ferr("ERROR: psock_bind failed: %d\n", errval);
+ ferr("ERROR: psock_bind failed: %d\n", error);
goto bad;
}
@@ -461,11 +437,10 @@ int rpcclnt_connect(struct rpcclnt *rpc)
* the NFS_PORT.
*/
- error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
+ error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr));
if (error < 0)
{
- errval = -error;
- ferr("ERROR: psock_connect to PMAP port failed: %d", errval);
+ ferr("ERROR: psock_connect to PMAP port failed: %d", error);
goto bad;
}
@@ -475,7 +450,7 @@ int rpcclnt_connect(struct rpcclnt *rpc)
request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT);
request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER3);
- request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP);
+ request.sdata.pmap.prot = txdr_unsigned(IPPROTO_UDP);
request.sdata.pmap.port = 0;
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
@@ -490,11 +465,10 @@ int rpcclnt_connect(struct rpcclnt *rpc)
sa = (FAR struct sockaddr_in *)saddr;
sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port));
- error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
+ error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr));
if (error < 0)
{
- errval = -error;
- ferr("ERROR: psock_connect MOUNTD port failed: %d\n", errval);
+ ferr("ERROR: psock_connect MOUNTD port failed: %d\n", error);
goto bad;
}
@@ -530,17 +504,16 @@ int rpcclnt_connect(struct rpcclnt *rpc)
sa->sin_port = htons(PMAPPORT);
- error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
+ error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr));
if (error < 0)
{
- errval = -error;
- ferr("ERROR: psock_connect PMAP port failed: %d\n", errval);
+ ferr("ERROR: psock_connect PMAP port failed: %d\n", error);
goto bad;
}
request.sdata.pmap.prog = txdr_unsigned(NFS_PROG);
request.sdata.pmap.vers = txdr_unsigned(NFS_VER3);
- request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP);
+ request.sdata.pmap.prot = txdr_unsigned(IPPROTO_UDP);
request.sdata.pmap.port = 0;
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
@@ -556,10 +529,9 @@ int rpcclnt_connect(struct rpcclnt *rpc)
sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port));
- error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
+ error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr));
if (error < 0)
{
- error = -error;
ferr("ERROR: psock_connect NFS port returns %d\n", error);
goto bad;
}
@@ -579,12 +551,9 @@ bad:
*
****************************************************************************/
-void rpcclnt_disconnect(struct rpcclnt *rpc)
+void rpcclnt_disconnect(FAR struct rpcclnt *rpc)
{
- if (rpc->rc_so != NULL)
- {
- psock_close(rpc->rc_so);
- }
+ psock_close(&rpc->rc_so);
}
/****************************************************************************
@@ -595,10 +564,10 @@ void rpcclnt_disconnect(struct rpcclnt *rpc)
*
****************************************************************************/
-int rpcclnt_umount(struct rpcclnt *rpc)
+int rpcclnt_umount(FAR struct rpcclnt *rpc)
{
- struct sockaddr *saddr;
- struct sockaddr_in *sa;
+ FAR struct sockaddr *saddr;
+ FAR struct sockaddr_in *sa;
union
{
@@ -613,7 +582,6 @@ int rpcclnt_umount(struct rpcclnt *rpc)
} response;
int error;
- int ret;
saddr = rpc->rc_name;
sa = (FAR struct sockaddr_in *)saddr;
@@ -624,10 +592,9 @@ int rpcclnt_umount(struct rpcclnt *rpc)
sa->sin_port = htons(PMAPPORT);
- ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
- if (ret < 0)
+ error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr));
+ if (error < 0)
{
- error = -ret;
ferr("ERROR: psock_connect failed [port=%d]: %d\n",
ntohs(sa->sin_port), error);
goto bad;
@@ -635,7 +602,7 @@ int rpcclnt_umount(struct rpcclnt *rpc)
request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT);
request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER3);
- request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP);
+ request.sdata.pmap.prot = txdr_unsigned(IPPROTO_UDP);
request.sdata.pmap.port = 0;
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
@@ -651,10 +618,9 @@ int rpcclnt_umount(struct rpcclnt *rpc)
sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port));
- ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
- if (ret < 0)
+ error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr));
+ if (error < 0)
{
- error = -ret;
ferr("ERROR: psock_connect failed [port=%d]: %d\n",
ntohs(sa->sin_port), error);
goto bad;
@@ -693,7 +659,7 @@ bad:
* certain errors.
*
* On successful receipt, it verifies the RPC level of the returned values.
- * (There may still be be NFS layer errors that will be deted by calling
+ * (There may still be be NFS layer errors that will be detected by calling
* logic).
*
****************************************************************************/
@@ -702,10 +668,10 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
int version, FAR void *request, size_t reqlen,
FAR void *response, size_t resplen)
{
- struct rpc_reply_header *replymsg;
+ FAR struct rpc_reply_header *replymsg;
uint32_t tmp;
uint32_t xid;
- int retries;
+ int retries = 0;
int error = 0;
/* Get a new (non-zero) xid */
@@ -728,17 +694,15 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
* timeouts.
*/
- retries = 0;
- do
+ for (; ; )
{
/* Do the client side RPC. */
rpc_statistics(rpcrequests);
- rpc->rc_timeout = false;
/* Send the RPC CALL message */
- error = rpcclnt_send(rpc, procnum, prog, request, reqlen);
+ error = rpcclnt_send(rpc, request, reqlen);
if (error != OK)
{
finfo("ERROR rpcclnt_send failed: %d\n", error);
@@ -748,16 +712,29 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
else
{
- error = rpcclnt_reply(rpc, procnum, prog, response, resplen);
+ error = rpcclnt_reply(rpc, response, resplen);
if (error != OK)
{
finfo("ERROR rpcclnt_reply failed: %d\n", error);
}
}
- retries++;
+ /* If we failed because of a timeout, then try sending the CALL
+ * message again.
+ */
+
+ if (error != -EAGAIN && error != -ETIMEDOUT)
+ {
+ break;
+ }
+
+ rpc_statistics(rpctimeouts);
+ if (++retries >= rpc->rc_retry)
+ {
+ break;
+ }
+ rpc_statistics(rpcretries);
}
- while (rpc->rc_timeout && retries <= rpc->rc_retry);
if (error != OK)
{
@@ -770,26 +747,9 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
replymsg = (FAR struct rpc_reply_header *)response;
tmp = fxdr_unsigned(uint32_t, replymsg->type);
- if (tmp == RPC_MSGDENIED)
+ if (tmp != RPC_MSGACCEPTED)
{
- tmp = fxdr_unsigned(uint32_t, replymsg->status);
- switch (tmp)
- {
- case RPC_MISMATCH:
- ferr("ERROR: RPC_MSGDENIED: RPC_MISMATCH error\n");
- return EOPNOTSUPP;
-
- case RPC_AUTHERR:
- ferr("ERROR: RPC_MSGDENIED: RPC_AUTHERR error\n");
- return EACCES;
-
- default:
- return EOPNOTSUPP;
- }
- }
- else if (tmp != RPC_MSGACCEPTED)
- {
- return EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
tmp = fxdr_unsigned(uint32_t, replymsg->status);
@@ -797,15 +757,10 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
{
finfo("RPC_SUCCESS\n");
}
- else if (tmp == RPC_PROGMISMATCH)
- {
- ferr("ERROR: RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n");
- return EOPNOTSUPP;
- }
- else if (tmp > 5)
+ else
{
ferr("ERROR: Unsupported RPC type: %d\n", tmp);
- return EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
return OK;
diff --git a/fs/nfs/xdr_subs.h b/fs/nfs/xdr_subs.h
index f3f3c58..a1117a1 100644
--- a/fs/nfs/xdr_subs.h
+++ b/fs/nfs/xdr_subs.h
@@ -68,47 +68,18 @@
#define fxdr_unsigned(t, v) ((t)ntohl(v))
#define txdr_unsigned(v) (htonl(v))
-#define fxdr_nfsv2time(f, t) \
-{ \
- (t)->tv_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \
- if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \
- (t)->tv_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \
- else \
- (t)->tv_nsec = 0; \
-}
-
-#define txdr_nfsv2time(f, t) \
-{ \
- ((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->tv_sec); \
- if ((f)->tv_nsec != -1) \
- ((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->tv_nsec / 1000); \
- else \
- ((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \
-}
-
#define fxdr_nfsv3time(f, t) \
{ \
(t)->tv_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
(t)->tv_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
}
-#define fxdr_nfsv3time2(f, t) { \
- (t)->nfsv3_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
- (t)->nfsv3_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
-}
-
#define txdr_nfsv3time(f, t) \
{ \
((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->tv_sec); \
((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->tv_nsec); \
}
-#define txdr_nfsv3time2(f, t) \
-{ \
- ((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->nfsv3_sec); \
- ((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->nfsv3_nsec); \
-}
-
#define fxdr_hyper(f) \
((((uint64_t)ntohl(((uint32_t *)(f))[0])) << 32) | \
(uint64_t)(ntohl(((uint32_t *)(f))[1])))