From bd8ecb86d024eee0bdef1687b582f64879354c36 Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 11 Jun 2012 21:16:35 +0000 Subject: NFS update git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4829 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/fs/nfs/nfs_mount.h | 2 +- nuttx/fs/nfs/nfs_proto.h | 10 +- nuttx/fs/nfs/nfs_socket.c | 59 +++-- nuttx/fs/nfs/nfs_util.c | 6 +- nuttx/fs/nfs/nfs_vfsops.c | 559 +++++++++++++++++++++++++--------------------- nuttx/fs/nfs/rpc.h | 26 ++- nuttx/fs/nfs/rpc_clnt.c | 54 ++--- 7 files changed, 389 insertions(+), 327 deletions(-) diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h index 7e548fe34..8fee14507 100644 --- a/nuttx/fs/nfs/nfs_mount.h +++ b/nuttx/fs/nfs/nfs_mount.h @@ -88,7 +88,7 @@ struct nfsmount uint32_t nm_sent; /* Request send count */ uint32_t nm_cwnd; /* Request send window */ uint32_t nm_timeouts; /* Request timeouts */ - uint32_t nm_deadthresh; /* Threshold of timeouts-->dead server */ +//uint32_t nm_deadthresh; /* Threshold of timeouts-->dead server */ uint32_t nm_rsize; /* Max size of read rpc */ uint32_t nm_wsize; /* Max size of write rpc */ uint32_t nm_readdirsize; /* Size of a readdir rpc */ diff --git a/nuttx/fs/nfs/nfs_proto.h b/nuttx/fs/nfs/nfs_proto.h index 2ee908e54..afc99ccff 100644 --- a/nuttx/fs/nfs/nfs_proto.h +++ b/nuttx/fs/nfs/nfs_proto.h @@ -334,7 +334,6 @@ struct nfsfh typedef struct nfsfh nfsfh_t; #define SIZEOF_nfsfh_t(n) (n) - struct nfsv3_time { uint32_t nfsv3_sec; @@ -590,14 +589,15 @@ struct RENAME3resok struct MKDIR3args { struct diropargs3 where; - struct nfsv3_sattr attributes; + struct nfsv3_sattr how; }; struct MKDIR3resok { - struct file_handle fhandle; - uint32_t obj_attributesfalse; - struct nfs_fattr obj_attributes; + uint32_t handle_follows; /* True, handle follows */ + struct file_handle fhandle; /* Variable length */ + uint32_t attributes_follows; /* True, attributes follows */ + struct nfs_fattr attributes; /* Directory attributes */ struct wcc_data dir_wcc; }; diff --git a/nuttx/fs/nfs/nfs_socket.c b/nuttx/fs/nfs/nfs_socket.c index 998287b79..0eb13777a 100644 --- a/nuttx/fs/nfs/nfs_socket.c +++ b/nuttx/fs/nfs/nfs_socket.c @@ -141,28 +141,24 @@ int nfs_connect(struct nfsmount *nmp) nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, NOCONN); nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, DUMBTIMR); -//rpc->rc_flag |= RPCCLNT_REDIRECT; /* Make this a mount option. */ - -//rpc->rc_authtype = RPCAUTH_NULL; /* for now */ - rpc->rc_path = nmp->nm_path; - rpc->rc_name = &nmp->nm_nam; -//rpc->rc_fh = nmp->nm_fh; - - rpc->rc_sotype = nmp->nm_sotype; - rpc->rc_soproto = nmp->nm_soproto; - rpc->rc_rsize = (nmp->nm_rsize > nmp->nm_readdirsize) ? - nmp->nm_rsize : nmp->nm_readdirsize; - rpc->rc_wsize = nmp->nm_wsize; + rpc->rc_authtype = RPCAUTH_NULL; /* for now */ + rpc->rc_path = nmp->nm_path; + rpc->rc_name = &nmp->nm_nam; + + rpc->rc_sotype = nmp->nm_sotype; + rpc->rc_soproto = nmp->nm_soproto; + rpc->rc_rsize = (nmp->nm_rsize > nmp->nm_readdirsize) ? nmp->nm_rsize : nmp->nm_readdirsize; + rpc->rc_wsize = nmp->nm_wsize; //rpc->rc_deadthresh = nmp->nm_deadthresh; - rpc->rc_timeo = nmp->nm_timeo; - rpc->rc_retry = nmp->nm_retry; + rpc->rc_timeo = nmp->nm_timeo; + rpc->rc_retry = nmp->nm_retry; - /* v3 need to use this */ + /* v3 needs to use this */ - rpc->rc_proctlen = 0; - rpc->rc_proct = NULL; + rpc->rc_proctlen = 0; + rpc->rc_proct = NULL; - nmp->nm_rpcclnt = rpc; + nmp->nm_rpcclnt = rpc; return rpcclnt_connect(rpc); } @@ -185,14 +181,14 @@ int nfs_request(struct nfsmount *nmp, int procnum, FAR const void *request, size_t reqlen, FAR void *response, size_t resplen) { - struct rpcclnt *clnt= nmp->nm_rpcclnt; - struct rpc_reply_header replyh; + struct rpcclnt *clnt = nmp->nm_rpcclnt; + struct nfs_reply_header replyh; int trylater_delay; int error; tryagain: - memset(&replyh, 0, sizeof(struct rpc_reply_header)); + memset(&replyh, 0, sizeof(struct nfs_reply_header)); error = rpcclnt_request(clnt, procnum, nmp->nm_rpcclnt->rc_prog->prog_id, nmp->nm_rpcclnt->rc_prog->prog_version, request, reqlen, @@ -203,7 +199,23 @@ tryagain: goto out; } - memcpy(&replyh, response, sizeof(struct rpc_reply_header)); + memcpy(&replyh, response, sizeof(struct nfs_reply_header)); + + if (replyh.nfs_status != 0) + { + if (fxdr_unsigned(uint32_t, replyh.nfs_status) > 32) + { + error = EOPNOTSUPP; + } + else + { + /* NFS_ERRORS are the same as NuttX errno values */ + + error = fxdr_unsigned(uint32_t, replyh.nfs_status); + } + + goto out; + } if (replyh.rpc_verfi.authtype != 0) { @@ -239,7 +251,8 @@ tryagain: goto out; } - return 0; + fvdbg("NFS_SUCCESS\n"); + return OK; out: return error; diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c index 0d61ed3d9..8a3a1e579 100644 --- a/nuttx/fs/nfs/nfs_util.c +++ b/nuttx/fs/nfs/nfs_util.c @@ -380,7 +380,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, value = *ptr++; value = fxdr_unsigned(uint32_t, value); - if (value > NFSX_V2FH) + if (value > NFSX_V3FHMAX) { fdbg("ERROR: Bad file handle length: %d\n", value); return EIO; @@ -444,7 +444,7 @@ 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, sizeof(nfsfh_t)); + 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. @@ -560,7 +560,7 @@ int nfs_finddir(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, sizeof(nfsfh_t)); + 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. */ diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c index ee6be0f21..ea40e02ee 100644 --- a/nuttx/fs/nfs/nfs_vfsops.c +++ b/nuttx/fs/nfs/nfs_vfsops.c @@ -201,7 +201,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, { struct file_handle fhandle; char filename[NAME_MAX + 1]; - struct CREATE3args create; + struct CREATE3args request; struct rpc_reply_create resok; FAR uint32_t *ptr; uint32_t tmp; @@ -220,7 +220,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, /* Create the CREATE RPC call arguments */ - ptr = (FAR uint32_t *)&create; + ptr = (FAR uint32_t *)&request; reqlen = 0; /* Copy the variable length, directory file handle */ @@ -240,6 +240,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, reqlen += sizeof(uint32_t); memcpy(ptr, filename, namelen); + ptr += uint32_increment(namelen); reqlen += uint32_alignup(namelen); /* Set the creation mode */ @@ -320,7 +321,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, { nfsstats.rpccnt[NFSPROC_CREATE]++; error = nfs_request(nmp, NFSPROC_CREATE, - (FAR const void *)&create, reqlen, + (FAR const void *)&request, reqlen, (FAR void *)&resok, sizeof(struct rpc_reply_create)); } #ifdef USE_GUARDED_CREATE @@ -696,7 +697,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) ssize_t tmp; ssize_t bytesread; size_t reqlen; - struct READ3args read; + struct READ3args request; FAR uint32_t *ptr; int error = 0; @@ -756,7 +757,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) /* Initialize the request */ - ptr = (FAR uint32_t*)&read; + ptr = (FAR uint32_t*)&request; reqlen = 0; /* Copy the variable length, directory file handle */ @@ -784,7 +785,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) fvdbg("Reading %d bytes\n", readsize); nfsstats.rpccnt[NFSPROC_READ]++; error = nfs_request(nmp, NFSPROC_READ, - (FAR const void *)&read, reqlen, + (FAR const void *)&request, reqlen, (FAR void *)np->n_iobuffer, np->n_buflen); if (error) { @@ -1089,8 +1090,8 @@ errout_with_semaphore: static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) { struct nfsmount *nmp; - uint32_t buffer[64]; /* Needs to go into struct fs_dirent_s nuttx/dirent.h */ - struct READDIR3args rddir; + uint32_t buffer[64]; + struct READDIR3args request; struct rpc_reply_readdir *resok; struct file_handle fhandle; struct nfs_fattr obj_attributes; @@ -1098,8 +1099,6 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) uint32_t *ptr; uint8_t *name; unsigned int length; - bool more; - bool eod; int reqlen; int error = 0; @@ -1123,121 +1122,110 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) goto errout_with_semaphore; } - /* Check in 'dir' if we are have directories entries? - * 1) have data, and - * 2) Index of the last returned entry has nextentry != 0 - * - * If we have returned entries then read more entries if: - * 3) EOF = 0 - */ - - more = false; /* Set 'more' to true if we have buffered entries to be processed */ - eod = false; /* Set 'eod' if we are at the end of the directory */ - - /* Loop while we need more data (!more) and we are not at the end of - * the directory (!eod) + /* Request a block directory entries, copying directory information from + * the dirent structure. */ - while (!more && !eod) - { - /* Request a block directory entries, copying directory information from - * the dirent structure. - */ - - memset(&rddir, 0, sizeof(struct READDIR3args)); - - /* Initialize the request */ - - ptr = (FAR uint32_t*)&rddir; - reqlen = 0; + ptr = (FAR uint32_t*)&request; + reqlen = 0; - /* Copy the variable length, directory file handle */ + /* Copy the variable length, directory file handle */ - *ptr++ = txdr_unsigned((uint32_t)dir->u.nfs.nfs_fhsize); - reqlen += sizeof(uint32_t); + *ptr++ = txdr_unsigned((uint32_t)dir->u.nfs.nfs_fhsize); + 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); + 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); - /* Cookie and cookie verifier */ + /* Cookie and cookie verifier */ - ptr[0] = dir->u.nfs.nfs_cookie[0]; - ptr[1] = dir->u.nfs.nfs_cookie[1]; - ptr += 2; - reqlen += 2*sizeof(uint32_t); + ptr[0] = dir->u.nfs.nfs_cookie[0]; + ptr[1] = dir->u.nfs.nfs_cookie[1]; + ptr += 2; + reqlen += 2*sizeof(uint32_t); - memcpy(ptr, dir->u.nfs.nfs_verifier, DIRENT_NFS_VERFLEN); - ptr += uint32_increment(DIRENT_NFS_VERFLEN); - reqlen += DIRENT_NFS_VERFLEN; + memcpy(ptr, dir->u.nfs.nfs_verifier, DIRENT_NFS_VERFLEN); + ptr += uint32_increment(DIRENT_NFS_VERFLEN); + reqlen += DIRENT_NFS_VERFLEN; - /* Number of directory entries (We currently only process one entry at a time) */ + /* Number of directory entries (We currently only process one entry at a time) */ - *ptr = txdr_unsigned(nmp->nm_readdirsize); - reqlen += sizeof(uint32_t); + *ptr = txdr_unsigned(nmp->nm_readdirsize); + reqlen += sizeof(uint32_t); - /* And read the directory */ + /* And read the directory */ - nfsstats.rpccnt[NFSPROC_READDIR]++; - error = nfs_request(nmp, NFSPROC_READDIR, - (FAR const void *)&rddir, reqlen, - (FAR void *)buffer, sizeof(buffer)); - if (error != OK) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - goto errout_with_semaphore; - } + nfsstats.rpccnt[NFSPROC_READDIR]++; + error = nfs_request(nmp, NFSPROC_READDIR, + (FAR const void *)&request, reqlen, + (FAR void *)buffer, sizeof(buffer)); + if (error != OK) + { + fdbg("ERROR: nfs_request failed: %d\n", error); + goto errout_with_semaphore; + } - /* A new group of entries was successfully read. Process the - * information contained in the response header. This information - * includes: - * - * 1) Attributes follow indication - 4 bytes - * 2) Directory attributes - sizeof(struct nfs_fattr) - * 3) Cookie verifier - NFSX_V3COOKIEVERF bytes - * 4) Values follows indication - 4 bytes - */ + /* A new group of entries was successfully read. Process the + * information contained in the response header. This information + * includes: + * + * 1) Attributes follow indication - 4 bytes + * 2) Directory attributes - sizeof(struct nfs_fattr) + * 3) Cookie verifier - NFSX_V3COOKIEVERF bytes + * 4) Values follows indication - 4 bytes + */ - resok = (struct rpc_reply_readdir *)buffer; + resok = (struct rpc_reply_readdir *)buffer; - /* Start with the first entry */ + /* Start with the first entry */ - ptr = (uint32_t*)&resok->readdir; + ptr = (uint32_t*)&resok->readdir; - /* Check if attributes follow, if 0 so Skip over the attributes */ + /* Check if attributes follow, if 0 so Skip over the attributes */ - if (resok->readdir.attributes_follow == 1) - { - /* Attributes are not currently used */ - } -#warning "Won't the structure format be wrong if there are no attributes -- this will need to be parsed too" + tmp = *ptr++; + if (tmp != 0) + { + /* Attributes are not currently used */ - /* Save the verification cookie */ + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } - memcpy(dir->u.nfs.nfs_verifier, &resok->readdir.cookieverf, DIRENT_NFS_VERFLEN); + /* Save the verification cookie */ - /* Get a pointer to the diretory entries (if any) */ + memcpy(dir->u.nfs.nfs_verifier, ptr, DIRENT_NFS_VERFLEN); + ptr += uint32_increment(DIRENT_NFS_VERFLEN); - ptr = (uint32_t*)&resok->readdir.reply; + /* Check if values follow. If no values follow, then the EOF indication + * will appear next. + */ - /* Check if values follow. If no values follow, then the EOF indication - * will appear next. + tmp = *ptr++; + if (tmp == 0) + { + /* No values follow, then the reply should consist only of a 4-byte + * end-of-directory indication. */ - if (resok->readdir.value_follows == 0) + tmp = *ptr++; + if (tmp != 0) { - /* No values follow, then the reply should consist only of a 4-byte - * end-of-directory indication. - */ - - more = false; /* No entries follow */ - eod = (*ptr != 0); /* We are (probably) at the end of the directory */ + fvdbg("End of directory\n"); + error = ENOENT; } - else - { - more = true; /* Assume that entries follow */ - eod = false; /* Assume that we are not at the end of the directory */ + + /* What would it mean if there were not data and we not at the end of + * file? + */ + + else + { + fvdbg("No data but not end of directory???\n"); + error = EAGAIN; } + + goto errout_with_semaphore; } /* If we are not at the end of the directory listing, then a set of entries @@ -1248,108 +1236,85 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) * Name string (varaiable size but in multiples of 4 bytes) * Cookie (8 bytes) * next entry (4 bytes) - * - * If 'more' is true, then we have more directory entries to process. */ - if (more) - { - /* There is an entry. Get the file ID and point to the length */ - /* Missing logic to get the file ID */ - - ptr += 2; + /* There is an entry. Skip over the file ID and point to the length */ - /* Get the length and point to the name */ + ptr += 2; - tmp = *ptr++; - length = fxdr_unsigned(uint32_t, tmp); - name = (uint8_t*)ptr; + /* Get the length and point to the name */ - /* Increment the pointer past the name (allowing for padding). ptr - * now points to the cookie. - */ + tmp = *ptr++; + length = fxdr_unsigned(uint32_t, tmp); + name = (uint8_t*)ptr; - ptr += uint32_increment(length); + /* Increment the pointer past the name (allowing for padding). ptr + * now points to the cookie. + */ - /* Save the cookie and increment the pointer to the next entry */ + ptr += uint32_increment(length); - dir->u.nfs.nfs_cookie[0] = *ptr++; - dir->u.nfs.nfs_cookie[1] = *ptr++; + /* Save the cookie and increment the pointer to the next entry */ - ptr++; /* Just skip over the nextentry for now */ + dir->u.nfs.nfs_cookie[0] = *ptr++; + dir->u.nfs.nfs_cookie[1] = *ptr++; - /* Return the name of the node to the caller */ + ptr++; /* Just skip over the nextentry for now */ - if (length > NAME_MAX) - { - length = NAME_MAX; - } - memcpy(dir->fd_dir.d_name, name, length); - dir->fd_dir.d_name[length] = '\0'; - fvdbg("name: \"%s\"\n", dir->fd_dir.d_name); + /* Return the name of the node to the caller */ - /* Get the file attributes associated with this name and return - * the file type. - */ + if (length > NAME_MAX) + { + length = NAME_MAX; + } - fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize; - memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, DIRENT_NFS_MAXHANDLE); + memcpy(dir->fd_dir.d_name, name, length); + dir->fd_dir.d_name[length] = '\0'; + fvdbg("name: \"%s\"\n", dir->fd_dir.d_name); - error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle, &obj_attributes, NULL); - if (error != OK) - { - fdbg("nfs_lookup failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Set the dirent file type */ + /* Get the file attributes associated with this name and return + * the file type. + */ - tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); - switch (tmp) - { - default: - case NFNON: /* Unknown type */ - case NFSOCK: /* Socket */ - case NFLNK: /* Symbolic link */ - break; + fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize; + memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, DIRENT_NFS_MAXHANDLE); - case NFREG: /* Regular file */ - dir->fd_dir.d_type = DTYPE_FILE; - break; + error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle, &obj_attributes, NULL); + if (error != OK) + { + fdbg("nfs_lookup failed: %d\n", error); + goto errout_with_semaphore; + } - case NFDIR: /* Directory */ - dir->fd_dir.d_type = DTYPE_DIRECTORY; - break; + /* Set the dirent file type */ - case NFBLK: /* Block special device file */ - dir->fd_dir.d_type = DTYPE_BLK; - break; + tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); + switch (tmp) + { + default: + case NFNON: /* Unknown type */ + case NFSOCK: /* Socket */ + case NFLNK: /* Symbolic link */ + break; - case NFFIFO: /* Named FIFO */ - case NFCHR: /* Character special device file */ - dir->fd_dir.d_type = DTYPE_CHR; - break; - } - fvdbg("type: %d->%d\n", (int)tmp, dir->fd_dir.d_type); - } + case NFREG: /* Regular file */ + dir->fd_dir.d_type = DTYPE_FILE; + break; - /* We are at the end of the directory. If 'eod' is true then we all of the - * directory entries have been processed and we are at the end of the - * directory. - */ + case NFDIR: /* Directory */ + dir->fd_dir.d_type = DTYPE_DIRECTORY; + break; - if (eod) - { - /* We signal the end of the directory by returning the - * special error -ENOENT - */ + case NFBLK: /* Block special device file */ + dir->fd_dir.d_type = DTYPE_BLK; + break; - fvdbg("End of directory\n"); - error = ENOENT; - goto errout_with_semaphore; + case NFFIFO: /* Named FIFO */ + case NFCHR: /* Character special device file */ + dir->fd_dir.d_type = DTYPE_CHR; + break; } - - error = 0; + fvdbg("type: %d->%d\n", (int)tmp, dir->fd_dir.d_type); errout_with_semaphore: nfs_semgive(nmp); @@ -1866,7 +1831,7 @@ static int nfs_statfs(struct inode *mountpt, struct statfs *sbp) error = nfs_checkmount(nmp); if (error != OK) { - fdbg("nfs_checkmount failed: %d\n", error); + fdbg("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_semaphore; } @@ -1933,7 +1898,6 @@ static int nfs_remove(struct inode *mountpt, const char *relpath) struct REMOVE3args remove; struct rpc_reply_remove resok; FAR uint32_t *ptr; - uint32_t tmp; int namelen; int reqlen; int error; @@ -1967,9 +1931,8 @@ static int nfs_remove(struct inode *mountpt, const char *relpath) /* We found something at this path. Make sure that it is not a directory. */ -#if 0 /* We don't have the attributes of the object to be deleted */ - tmp = fxdr_unsigned(uint32_t, fattr.fa_type); - if (tmp == NFDIR) +#if 0 /* We have the attributes of the directory, not of the object to be deleted */ + if (fxdr_unsigned(uint32_t, fattr.fa_type) == NFDIR) { fdbg("ERROR: \"%s\" is a directory\n", relpath); error = EISDIR; @@ -2013,9 +1976,9 @@ static int nfs_remove(struct inode *mountpt, const char *relpath) #ifdef CONFIG_NFS_TCPIP if (error == ENOENT) { - /* Kludge City: If the first reply to the remove rpc is lost, the reply - * to the retransmitted request will be ENOENT since the file was in - * fact removed. Therefore, we cheat and return success. + /* If the first reply to the remove rpc is lost, the reply to the + * retransmitted request may be ENOENT if the file was in fact removed. + * Therefore, we cheat and return success. */ error = OK; @@ -2040,12 +2003,17 @@ errout_with_semaphore: static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) { - struct nfsv3_sattr sp; - struct nfsmount *nmp; - struct nfsnode *np; - struct MKDIR3args mkir; + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr fattr; + char dirname[NAME_MAX + 1]; + struct MKDIR3args request; struct rpc_reply_mkdir resok; - int error = 0; + FAR uint32_t *ptr; + uint32_t tmp; + int namelen; + int reqlen; + int error; /* Sanity checks */ @@ -2054,7 +2022,6 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) /* Get the mountpoint private data from the inode structure */ nmp = (struct nfsmount*) mountpt->i_private; - np = nmp->nm_head; /* Check if the mount is still healthy */ @@ -2062,46 +2029,97 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) error = nfs_checkmount(nmp); if (error != OK) { + fdbg("ERROR: nfs_checkmount: %d\n", error); goto errout_with_semaphore; } - nfsstats.rpccnt[NFSPROC_MKDIR]++; - memset(&mkir, 0, sizeof(struct MKDIR3args)); - memset(&resok, 0, sizeof(struct rpc_reply_mkdir)); - mkir.where.fhandle.length = txdr_unsigned(np->n_fhsize); - memcpy(&mkir.where.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t)); - mkir.where.length = txdr_unsigned(64); - strncpy((FAR char *)mkir.where.name, relpath, 64); - - sp.sa_modefollows = nfs_true; - sp.sa_mode = txdr_unsigned(mode); - sp.sa_uidfollows = 0; - sp.sa_gidfollows = 0; - sp.sa_sizefollows = 0; - sp.sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); - sp.sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); - -//memset(&sp.sa_atime, 0, sizeof(nfstime3)); -//memset(&sp.sa_mtime, 0, sizeof(nfstime3)); - - memcpy(&mkir.attributes, &sp, sizeof(struct nfsv3_sattr)); + /* Find the NFS node of the directory containing the directory to be created */ + + error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Format the MKDIR call message arguments */ + + ptr = (FAR uint32_t *)&request; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(fhandle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle.handle, fhandle.length); + ptr += uint32_increment(fhandle.length); + reqlen += (int)fhandle.length; + + /* Copy the variable-length directory name */ + + namelen = strlen(dirname); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, dirname, namelen); + ptr += uint32_increment(namelen); + reqlen += uint32_alignup(namelen); + + /* 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); + tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH | + NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP | + NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); + *ptr++ = txdr_unsigned(tmp); + reqlen += sizeof(uint32_t); + + /* Set the user ID to zero */ + + *ptr++ = nfs_true; /* True: Uid value follows */ + reqlen += sizeof(uint32_t); + + *ptr++ = 0; + reqlen += sizeof(uint32_t); + + /* Set the group ID to one */ + + *ptr++ = nfs_true; /* True: Gid value follows */ + reqlen += sizeof(uint32_t); + + *ptr++ = HTONL(1); + reqlen += sizeof(uint32_t); + + /* No size */ + + *ptr++ = nfs_false; /* False: No size value follows */ + reqlen += sizeof(uint32_t); + + /* Don't change times */ + + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ + reqlen += sizeof(uint32_t); + + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ + reqlen += sizeof(uint32_t); + + /* Perform the MKDIR RPC */ + + nfsstats.rpccnt[NFSPROC_MKDIR]++; error = nfs_request(nmp, NFSPROC_MKDIR, - (FAR const void *)&mkir, sizeof(struct MKDIR3args), + (FAR const void *)&request, reqlen, (FAR void *)&resok, sizeof(struct rpc_reply_mkdir)); if (error) { - goto errout_with_semaphore; + fdbg("ERROR: nfs_request failed: %d\n", error); } - np->n_type = fxdr_unsigned(uint32_t, resok.mkdir.obj_attributes.fa_type); - memcpy(&np->n_fhandle, &resok.mkdir.fhandle.handle, sizeof(nfsfh_t)); - np->n_size = fxdr_hyper(&resok.mkdir.obj_attributes.fa_size); - memcpy(&np->n_fattr, &resok.mkdir.obj_attributes, sizeof(struct nfs_fattr)); - fxdr_nfsv3time(&resok.mkdir.obj_attributes.fa_mtime, &np->n_mtime) - np->n_ctime = fxdr_hyper(&resok.mkdir.obj_attributes.fa_ctime); - np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED); - errout_with_semaphore: nfs_semgive(nmp); return -error; @@ -2120,11 +2138,16 @@ errout_with_semaphore: static int nfs_rmdir(struct inode *mountpt, const char *relpath) { - struct nfsmount *nmp; - struct nfsnode *np; - struct RMDIR3args rmdir; + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr fattr; + char dirname[NAME_MAX + 1]; + struct RMDIR3args request; struct rpc_reply_rmdir resok; - int error = 0; + FAR uint32_t *ptr; + int namelen; + int reqlen; + int error; /* Sanity checks */ @@ -2133,48 +2156,69 @@ 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; - np = nmp->nm_head; /* Check if the mount is still healthy */ nfs_semtake(nmp); error = nfs_checkmount(nmp); - if (error == OK) + if (error != OK) { - /* Remove the directory */ + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } - if (np->n_type != NFDIR) - { - error = EPERM; - goto errout_with_semaphore; - } + /* Find the NFS node of the directory containing the directory to be removed */ - /* Do the rpc */ + error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Set up the RMDIR call message arguments */ - nfsstats.rpccnt[NFSPROC_RMDIR]++; - memset(&rmdir, 0, sizeof(struct RMDIR3args)); - memset(&resok, 0, sizeof(struct rpc_reply_rmdir)); - rmdir.object.fhandle.length = txdr_unsigned(np->n_fhsize); - memcpy(&rmdir.object.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t)); - rmdir.object.length = txdr_unsigned(64); - strncpy((FAR char *)rmdir.object.name, relpath, 64); + ptr = (FAR uint32_t *)&request; + reqlen = 0; + + /* Copy the variable length, directory file handle */ - error = nfs_request(nmp, NFSPROC_RMDIR, - (FAR const void *)&rmdir, sizeof(struct RMDIR3args), + *ptr++ = txdr_unsigned(fhandle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle.handle, fhandle.length); + reqlen += (int)fhandle.length; + ptr += uint32_increment(fhandle.length); + + /* Copy the variable-length directory name */ + + namelen = strlen(dirname); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, dirname, namelen); + reqlen += uint32_alignup(namelen); + + /* Perform the RMDIR RPC */ + + nfsstats.rpccnt[NFSPROC_RMDIR]++; + error = nfs_request(nmp, NFSPROC_RMDIR, + (FAR const void *)&request, reqlen, (FAR void *)&resok, sizeof(struct rpc_reply_rmdir)); - if (error == ENOENT) - { - error = 0; - } - if (error) - { - goto errout_with_semaphore; - } + /* Check if the removal was successful */ - memcpy(&np->n_fattr, &resok.rmdir.dir_wcc.after, sizeof(struct nfs_fattr)); - np->n_flags |= NFSNODE_MODIFIED; +#ifdef CONFIG_NFS_TCPIP + if (error == ENOENT) + { + /* If the first reply to the remove rpc is lost, the reply to the + * retransmitted request may be ENOENT if the file was in fact removed. + * Therefore, we cheat and return success. + */ + error = 0; } +#endif errout_with_semaphore: nfs_semgive(nmp); @@ -2242,12 +2286,19 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath, (FAR const void *)&rename, sizeof(struct RENAME3args), (FAR void *)&resok, sizeof(struct rpc_reply_rename)); - /* ENOENT => 0 assuming that it is a reply to a retry. */ + /* Check if the rename was successful */ +#ifdef CONFIG_NFS_TCPIP if (error == ENOENT) { + /* If the first reply to the remove rpc is lost, the reply to the + * retransmitted request may be ENOENT if the file was in fact removed. + * Therefore, we cheat and return success. + */ + error = 0; } +#endif if (error) { @@ -2302,7 +2353,7 @@ static int nfs_stat(struct inode *mountpt, const char *relpath, goto errout_with_semaphore; } - /* Get the attributes of the requested node */ + /* Get the file handle attributes of the requested node */ error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); if (error != OK) diff --git a/nuttx/fs/nfs/rpc.h b/nuttx/fs/nfs/rpc.h index 73b6a5eca..2aa01a69a 100644 --- a/nuttx/fs/nfs/rpc.h +++ b/nuttx/fs/nfs/rpc.h @@ -281,7 +281,7 @@ enum auth_flavor struct rpc_auth_info { - enum auth_flavor authtype; /* auth type */ + uint32_t authtype; /* auth type */ uint32_t authlen; /* auth length */ }; @@ -394,6 +394,16 @@ struct rpc_reply_header uint32_t status; }; +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; + uint32_t nfs_status; +}; + struct rpc_reply_pmap { struct rpc_reply_header rh; @@ -538,27 +548,23 @@ struct rpcclnt int rc_sent; /* Request send count */ int rc_cwnd; /* Request send window */ int rc_timeouts; /* Request timeouts */ - + int rc_authtype; /* Authenticator type */ //int rc_deadthresh; /* Threshold of timeouts-->dead server*/ /* authentication: */ /* currently can be RPCAUTH_NULL, RPCAUTH_KERBV4, RPCAUTH_UNIX */ /* should be kept in XDR form */ -// int rc_authtype; /* Authenticator type */ + /* RPCAUTH_UNIX */ #ifdef CONFIG_NFS_UNIX_AUTH - /* RPCAUTH_UNIX*/ - struct rpc_auth_info rc_oldauth; /* authentication */ + void *rc_auth; #endif -//void *rc_auth; struct rpc_program *rc_prog; -//char *rc_servername; - - int rc_proctlen; /* if == 0 then rc_proct == NULL */ - int *rc_proct; + int rc_proctlen; /* if == 0 then rc_proct == NULL */ + int *rc_proct; }; /**************************************************************************** diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c index bb213288d..ff7fcfdfc 100644 --- a/nuttx/fs/nfs/rpc_clnt.c +++ b/nuttx/fs/nfs/rpc_clnt.c @@ -1206,15 +1206,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve case NFSPROC_REMOVE: { - /* Copy the variable, caller-provided data into the call message structure */ + /* Copy the variable length, caller-provided data into the call + * message structure. + */ struct rpc_call_remove *callmsg = (struct rpc_call_remove *)msgbuf; memcpy(&callmsg->remove, request, *reqlen); - /* Return the full size of the message (including messages headers) */ + /* Return the full size of the message (the size of variable data + * plus the size of the messages header). + */ - DEBUGASSERT(*reqlen == sizeof(struct REMOVE3args)); - *reqlen = sizeof(struct rpc_call_remove); + *reqlen += sizeof(struct rpc_call_header); /* Format the message header */ @@ -1244,15 +1247,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve case NFSPROC_MKDIR: { - /* Copy the variable, caller-provided data into the call message structure */ + /* Copy the variable length, caller-provided data into the call + * message structure. + */ struct rpc_call_mkdir *callmsg = (struct rpc_call_mkdir *)msgbuf; memcpy(&callmsg->mkdir, request, *reqlen); - /* Return the full size of the message (including messages headers) */ + /* Return the full size of the message (the size of variable data + * plus the size of the messages header). + */ - DEBUGASSERT(*reqlen == sizeof(struct MKDIR3args)); - *reqlen = sizeof(struct rpc_call_mkdir); + *reqlen += sizeof(struct rpc_call_header); /* Format the message header */ @@ -1263,15 +1269,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve case NFSPROC_RMDIR: { - /* Copy the variable, caller-provided data into the call message structure */ + /* Copy the variable length, caller-provided data into the call + * message structure. + */ struct rpc_call_rmdir *callmsg = (struct rpc_call_rmdir *)msgbuf; memcpy(&callmsg->rmdir, request, *reqlen); - /* Return the full size of the message (including messages headers) */ + /* Return the full size of the message (the size of variable data + * plus the size of the messages header). + */ - DEBUGASSERT(*reqlen == sizeof(struct RMDIR3args)); - *reqlen = sizeof(struct rpc_call_rmdir); + *reqlen += sizeof(struct rpc_call_header); /* Format the message header */ @@ -1922,6 +1931,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, memset(&replymgs, 0, sizeof(replymgs)); memcpy(&replyheader, response, sizeof(struct rpc_reply_header)); + replymgs.type = fxdr_unsigned(uint32_t, replyheader.type); if (replymgs.type == RPC_MSGDENIED) { @@ -1929,16 +1939,11 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, switch (replymgs.status) { case RPC_MISMATCH: - /*replymgs.stat.mismatch_info.low = - fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.low); - replymgs.stat.mismatch_info.high = - fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.high);*/ fdbg("RPC_MSGDENIED: RPC_MISMATCH error\n"); error = EOPNOTSUPP; break; case RPC_AUTHERR: - //replymgs.stat.autherr = fxdr_unsigned(uint32_t, replyheader.stat.autherr); fdbg("RPC_MSGDENIED: RPC_AUTHERR error\n"); error = EACCES; break; @@ -1947,6 +1952,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, error = EOPNOTSUPP; break; } + goto rpcmout; } else if (replymgs.type != RPC_MSGACCEPTED) @@ -1955,24 +1961,12 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, goto rpcmout; } - /* Verifier */ - -/*replymgs.rpc_verfi.authtype = - fxdr_unsigned(enum auth_flavor, replyheader.rpc_verfi.authtype); - replymgs.rpc_verfi.authlen = - fxdr_unsigned(uint32_t, replyheader.rpc_verfi.authlen);*/ - if (replymgs.status == RPC_SUCCESS) { fvdbg("RPC_SUCCESS\n"); } else if (replymgs.status == RPC_PROGMISMATCH) { - /*replymgs.stat.mismatch_info.low = - fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.low); - replymgs.stat.mismatch_info.high = - fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.high);*/ - fdbg("RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n"); error = EOPNOTSUPP; } @@ -2123,9 +2117,7 @@ void rpcclnt_timer(void *arg, struct rpc_call *call) // rpcclnt_timer_handle = timeout(rpcclnt_timer, NULL, rpcclnt_ticks); } -#endif -#ifdef COMP int rpcclnt_cancelreqs(struct rpcclnt *rpc) { struct rpctask *task; -- cgit v1.2.3