diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index 2001e2b6b5124..a17750c9fc241 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 bb43f442eb468..4bab6155fa3c1 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 cb5925f3b7e0f..cedd8840a354c 100644 --- a/fs/nfs/nfs_node.h +++ b/fs/nfs/nfs_node.h @@ -50,15 +50,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 185dc6ed44704..7b63d00cc35b8 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 594f6f2e3c6ef..abfa796660c32 100644 --- a/fs/nfs/nfs_util.c +++ b/fs/nfs/nfs_util.c @@ -42,18 +42,14 @@ #include #include -#include #include #include #include #include #include #include -#include #include -#include - #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 { @@ -121,78 +117,26 @@ static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer, * Public Functions ****************************************************************************/ -/**************************************************************************** - * 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 @@ int nfs_request(struct nfsmount *nmp, int procnum, { 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 @@ int nfs_request(struct nfsmount *nmp, int procnum, * ****************************************************************************/ -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 f9c55d4303cdd..59670c49a30e4 100644 --- a/fs/nfs/nfs_vfsops.c +++ b/fs/nfs/nfs_vfsops.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include @@ -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 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath, } 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 @@ 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_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 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, 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 @@ static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf) 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 @@ 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_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 @@ static int nfs_opendir(struct inode *mountpt, const char *relpath, * ****************************************************************************/ -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 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, { /* 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 @@ static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver, * 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 @@ static int nfs_statfs(FAR struct inode *mountpt, FAR struct statfs *sbp) * ****************************************************************************/ -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 @@ static int nfs_remove(struct inode *mountpt, const char *relpath) * ****************************************************************************/ -static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) +static int nfs_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 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) * ****************************************************************************/ -static int nfs_rmdir(struct inode *mountpt, const char *relpath) +static int nfs_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 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath) * ****************************************************************************/ -static int nfs_rename(struct inode *mountpt, const char *oldrelpath, - const char *newrelpath) +static int nfs_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 d3924745f3b60..1139338604f09 100644 --- a/fs/nfs/rpc.h +++ b/fs/nfs/rpc.h @@ -75,6 +75,8 @@ ****************************************************************************/ #include +#include + #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 180c234098139..aa40e468539a0 100644 --- a/fs/nfs/rpc_clnt.c +++ b/fs/nfs/rpc_clnt.c @@ -89,7 +89,6 @@ #include #include #include -#include #include "xdr_subs.h" #include "nfs_proto.h" @@ -107,6 +106,22 @@ # define rpc_statistics(n) #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 @@ int rpcclnt_connect(struct rpcclnt *rpc) * ****************************************************************************/ -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 @@ int rpcclnt_umount(struct rpcclnt *rpc) * 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 f3f3c58cc0a46..a1117a1dc1b78 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])))