NFS update

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4822 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-06-10 00:13:59 +00:00
parent 839e11d8eb
commit 686cf098e0
8 changed files with 685 additions and 811 deletions

View File

@ -363,10 +363,14 @@ EXTERN void nfs_semtake(struct nfsmount *nmp);
EXTERN void nfs_semgive(struct nfsmount *nmp);
EXTERN int nfs_checkmount(struct nfsmount *nmp);
EXTERN int nfs_fsinfo(struct nfsmount *nmp);
EXTERN int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes);
EXTERN int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes);
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes);
#undef EXTERN
#if defined(__cplusplus)

View File

@ -316,10 +316,10 @@ typedef enum
NFREG = 1, /* Regular file */
NFDIR = 2, /* Directory */
NFBLK = 3, /* Block special device file */
NFCHR = 4, /* Characgter special device file */
NFCHR = 4, /* Character special device file */
NFLNK = 5, /* Symbolic link */
NFSOCK = 6, /* Socket */
NFFIFO = 7
NFFIFO = 7 /* Named FIFO */
} nfstype;
typedef struct
@ -588,10 +588,12 @@ struct LOOKUP3args
{
struct file_handle dirhandle;
uint32_t namelen;
uint32_t name[1]; /* Actual size determined by namelen */
uint32_t name[(NAME_MAX+3) >> 2]; /* Actual size determined by namelen */
};
#define SIZEOF_LOOKUP3args(n) \
(sizeof(struct LOOKUP3args) + ((((n)+3) >> 2) - 1)*sizeof(uint32_t))
/* Actual size of LOOKUP3args */
#define SIZEOF_LOOKUP3args(n) (sizeof(struct file_handle) + sizeof(namelen) + (((n)+3) & ~3))
struct LOOKUP3resok
{

View File

@ -125,7 +125,7 @@ int nfs_connect(struct nfsmount *nmp)
if (!rpc)
{
fdbg("ERROR: Failed to allocate rpc structure\n");
return -ENOMEM;
return ENOMEM;
}
rpc->rc_prog = &nfs3_program;
@ -180,8 +180,9 @@ void nfs_safedisconnect(struct nfsmount *nmp)
}
#endif
int nfs_request(struct nfsmount *nmp, int procnum, FAR const void *datain,
FAR void *dataout, size_t len)
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;
@ -193,15 +194,15 @@ tryagain:
memset(&replyh, 0, sizeof(struct rpc_reply_header));
error = rpcclnt_request(clnt, procnum, nmp->nm_rpcclnt->rc_prog->prog_id,
nmp->nm_rpcclnt->rc_prog->prog_version, dataout,
datain, len);
nmp->nm_rpcclnt->rc_prog->prog_version, request, reqlen,
response, resplen);
if (error != 0)
{
fdbg("ERROR: rpcclnt_request failed: %d\n", error);
goto out;
}
memcpy(&replyh, dataout, sizeof(struct rpc_reply_header));
memcpy(&replyh, response, sizeof(struct rpc_reply_header));
if (replyh.rpc_verfi.authtype != 0)
{

View File

@ -55,16 +55,17 @@ extern "C" {
#endif
EXTERN void nfs_init(void);
EXTERN int nfs_connect(struct nfsmount *);
EXTERN void nfs_disconnect(struct nfsmount *);
EXTERN int nfs_connect(struct nfsmount *nmp);
EXTERN void nfs_disconnect(struct nfsmount *nmp);
#ifdef CONFIG_NFS_TCPIP
EXTERN int nfs_sigintr(struct nfsmount *, struct nfsreq *, cthread_t *);
EXTERN void nfs_safedisconnect(struct nfsmount *);
EXTERN void nfs_safedisconnect(struct nfsmount *nmp);
#endif
EXTERN int nfs_request(struct nfsmount *, int, FAR const void *, FAR void *, size_t);
EXTERN int nfs_request(struct nfsmount *nmp, int procnum,
FAR const void *request, size_t reqlen,
FAR void *response, size_t resplen);
#undef COMP
#ifdef COMP
EXTERN int nfs_nmcancelreqs(struct nfsmount *);
EXTERN int nfs_nmcancelreqs(struct nfsmount *nmp);
#endif
#undef EXTERN
#if defined(__cplusplus)

View File

@ -226,7 +226,8 @@ int nfs_fsinfo(FAR struct nfsmount *nmp)
/* Request FSINFO from the server */
error = nfs_request(nmp, NFSPROC_FSINFO, (FAR const void *)&fsinfo,
error = nfs_request(nmp, NFSPROC_FSINFO,
(FAR const void *)&fsinfo, sizeof(struct FS3args),
(FAR void *)&fsp, sizeof(struct rpc_reply_fsinfo));
if (error)
{
@ -290,6 +291,86 @@ int nfs_fsinfo(FAR struct nfsmount *nmp)
return 0;
}
/****************************************************************************
* Name: nfs_lookup
*
* Desciption:
* Given a directory file handle, and the path to file in the directory,
* return the file handle of the path and attributes of both the file and
* the directory containing the file.
*
* NOTE: The LOOKUP call differs from other RPC messages in that the
* call message is variable length, depending upon the size of the path
* name.
*
****************************************************************************/
int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes)
{
struct LOOKUP3args request;
struct rpc_reply_lookup response;
int namelen;
int error = 0;
DEBUGASSERT(nmp && filename && fhandle && obj_attributes && dir_attributes);
/* Set all of the buffers to a known state */
memset(&request, 0, sizeof(struct LOOKUP3args));
memset(&response, 0, sizeof(struct rpc_reply_lookup));
memset(&obj_attributes, 0, sizeof(struct nfs_fattr));
memset(&dir_attributes, 0, sizeof(struct nfs_fattr));
/* Get the length of the string to be sent */
namelen = strlen(filename);
if (namelen > NAME_MAX)
{
fdbg("Length of \"%s\%too big: %d\n", namelen);
return E2BIG;
}
/* Initialize the request */
nfsstats.rpccnt[NFSPROC_LOOKUP]++;
memcpy(&request.dirhandle, fhandle, sizeof(struct file_handle));
request.namelen = txdr_unsigned(namelen);
memcpy(request.name, filename, namelen);
/* Request LOOKUP from the server */
error = nfs_request(nmp, NFSPROC_LOOKUP,
(FAR const void *)&request, SIZEOF_LOOKUP3args(namelen),
(FAR void *)&response, sizeof(struct rpc_reply_lookup));
if (error)
{
fdbg("nfs_request failed: %d\n", error);
return error;
}
/* Return the data to the caller's buffers */
memcpy(fhandle, &response.lookup.fshandle, sizeof(struct file_handle));
if (response.lookup.obj_attributes_follow != 0)
{
memcpy(obj_attributes, &response.lookup.obj_attributes,
sizeof(struct nfs_fattr));
}
if (response.lookup.dir_attributes_follow != 0)
{
memcpy(dir_attributes, &response.lookup.dir_attributes,
sizeof(struct nfs_fattr));
}
return OK;
}
/****************************************************************************
* Name: nfs_findnode
*
@ -315,8 +396,6 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
fhandle->length = nmp->nm_fhsize;
memcpy(&fhandle->handle, &nmp->nm_fh, sizeof(nfsfh_t));
#warning "Where do we get the attributes of the root file system?"
memset(obj_attributes, 0, sizeof(struct nfs_fattr));
memset(dir_attributes, 0, sizeof(struct nfs_fattr));
@ -326,6 +405,7 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
if (*path == '\0' || strlen(path) == 0)
{
#warning "Where do we get the attributes of the root file system?"
return OK;
}
@ -349,12 +429,10 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
/* Look-up this path segment */
nfsstats.rpccnt[NFSPROC_LOOKUP]++;
error = rpcclnt_lookup(nmp->nm_rpcclnt, buffer, fhandle,
obj_attributes, dir_attributes);
error = nfs_lookup(nmp, buffer, fhandle, obj_attributes, dir_attributes);
if (error != 0)
{
fdbg("rpcclnt_lookup of \"%s\" failed at \"%s\": %d\n",
fdbg("nfs_lookup of \"%s\" failed at \"%s\": %d\n",
relpath, buffer, error);
return error;
}

View File

@ -53,7 +53,6 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue.h>
#include <string.h>
@ -210,8 +209,9 @@ static int nfs_create(FAR struct nfsmount *nmp, struct nfsnode *np,
create.where.length = txdr_unsigned(64);
strncpy(create.where.name, relpath, 64);
error = nfs_request(nmp, NFSPROC_CREATE, (FAR const void *)&create,
(void *)&resok, sizeof(struct rpc_reply_create));
error = nfs_request(nmp, NFSPROC_CREATE,
(FAR const void *)&create, sizeof(struct CREATE3args),
(FAR void *)&resok, sizeof(struct rpc_reply_create));
}
while (error == EOPNOTSUPP);
@ -552,8 +552,9 @@ again:
read.count = txdr_unsigned(buflen);
read.offset = txdr_unsigned(offset);
error = nfs_request(nmp, NFSPROC_READ, (FAR const void *)&read,
(void *)&resok, sizeof(struct rpc_reply_read));
error = nfs_request(nmp, NFSPROC_READ,
(FAR const void *)&read, sizeof(struct READ3args),
(FAR void *)&resok, sizeof(struct rpc_reply_read));
if (error)
{
goto errout_with_semaphore;
@ -587,8 +588,8 @@ errout_with_semaphore:
*
****************************************************************************/
static ssize_t
nfs_write(FAR struct file *filep, const char *buffer, size_t buflen)
static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
size_t buflen)
{
struct inode *inode;
struct nfsmount *nmp;
@ -651,7 +652,8 @@ nfs_write(FAR struct file *filep, const char *buffer, size_t buflen)
write.stable = txdr_unsigned(committed);
memcpy((void *)write.data, userbuffer, buflen);
error = nfs_request(nmp, NFSPROC_WRITE, (FAR const void *)&write,
error = nfs_request(nmp, NFSPROC_WRITE,
(FAR const void *)&write, sizeof(struct WRITE3args),
(FAR void *)&resok, sizeof(struct rpc_reply_write));
if (error)
{
@ -779,7 +781,7 @@ errout_with_semaphore:
* Name: nfs_readdirrpc
*
* Description:
* The function below stuff the cookies in after the name.
* Perform the READIR RPC call.
*
* Returned Value:
* 0 on success; a positive errno value on failure.
@ -793,6 +795,9 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np,
uint32_t buffer[64];
struct READDIR3args rddir;
struct rpc_reply_readdir *resok;
struct file_handle fhandle;
struct nfs_fattr obj_attributes;
struct nfs_fattr dir_attributes;
uint32_t tmp;
uint32_t *ptr; /* This goes in fs_dirent_s */
uint8_t *name;
@ -818,7 +823,7 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np,
while (!more && !eod)
{
/* Request a block directory enries */
/* Request a block directory entries */
nfsstats.rpccnt[NFSPROC_READDIR]++;
memset(&rddir, 0, sizeof(struct READDIR3args));
@ -839,7 +844,8 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np,
memcpy(&rddir.cookieverf, &np->n_cookieverf, NFSX_V3COOKIEVERF);
}
error = nfs_request(nmp, NFSPROC_READDIR, (FAR const void *)&rddir,
error = nfs_request(nmp, NFSPROC_READDIR,
(FAR const void *)&rddir, sizeof(struct READDIR3args),
(FAR void *)buffer, sizeof(buffer));
if (error)
{
@ -939,13 +945,6 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np,
ptr++; /* Just skip over the nextentry for now */
/* Return the directory entry to the caller. On subsequent calls to
* readdir(), we will return the next entry. And so on until all of
* the entries have been returned. Then read the next next block
* of entries until EOF is reported.
*/
#warning "Not implemented"
/* Return the name of the node to the caller */
if (length > NAME_MAX)
@ -959,50 +958,46 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np,
/* Get the file attributes associated with this name and return
* the file type.
*/
#if 0 /* There is no point in enabling until nfs_getfsinfo handles the relative path */
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
fhandle.length = txdr_unsigned(np->n_fhsize);
memcpy(&fhandle.handle, &np->n_fhp, sizeof(nfsfh_t));
error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle,
&obj_attributes, &dir_attributes);
if (error != 0)
{
struct stat buf;
char *path;
/* Construct the full path to the file */
asprintf(&path, "%s/%s", relpath, dir->fd_dir.d_name);
if (path)
{
/* Then stat the file */
int ret = nfs_getstat(nmp, path, &buf);
if (ret == OK)
{
if (S_ISREG(buf.st_mode))
{
dir->fd_dir.d_type = DTYPE_FILE;
}
else if (S_ISDIR(buf.st_mode))
{
dir->fd_dir.d_type = DTYPE_FILE;
}
else if (S_ISCHR(buf.st_mode) || S_ISFIFO(buf.st_mode))
{
dir->fd_dir.d_type = DTYPE_FILE;
}
else if (S_ISBLK(buf.st_mode))
{
dir->fd_dir.d_type = DTYPE_FILE;
}
else
{
#warning "Other types should be ignored ... go to the next entry"
}
}
/* Free the allocated string */
kfree(path);
}
fdbg("nfs_lookup failed: %d\n", error);
return error;
}
#endif
/* Set the dirent file type */
switch (obj_attributes.fa_type)
{
default:
case NFNON: /* Unknown type */
case NFSOCK: /* Socket */
case NFLNK: /* Symbolic link */
break;
case NFREG: /* Regular file */
dir->fd_dir.d_type = DTYPE_FILE;
break;
case NFDIR: /* Directory */
dir->fd_dir.d_type = DTYPE_DIRECTORY;
break;
case NFBLK: /* Block special device file */
dir->fd_dir.d_type = DTYPE_BLK;
break;
case NFFIFO: /* Named FIFO */
case NFCHR: /* Character special device file */
dir->fd_dir.d_type = DTYPE_CHR;
break;
}
error = 0;
}
@ -1445,7 +1440,8 @@ int mountnfs(struct nfs_args *argp, void **handle)
getattr.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
memcpy(&getattr.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t));
error = nfs_request(nmp, NFSPROC_GETATTR, (FAR const void *)&getattr,
error = nfs_request(nmp, NFSPROC_GETATTR,
(FAR const void *)&getattr, sizeof(struct FS3args),
(FAR void*)&resok, sizeof(struct rpc_reply_getattr));
if (error)
{
@ -1635,7 +1631,8 @@ static int nfs_statfs(struct inode *mountpt, struct statfs *sbp)
fsstat.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
fsstat.fsroot.handle = nmp->nm_fh;
error = nfs_request(nmp, NFSPROC_FSSTAT, (FAR const void *)&fsstat,
error = nfs_request(nmp, NFSPROC_FSSTAT,
(FAR const void *)&fsstat, sizeof(struct FS3args),
(FAR void *) &sfp, sizeof(struct rpc_reply_fsstat));
if (error)
{
@ -1718,7 +1715,8 @@ static int nfs_remove(struct inode *mountpt, const char *relpath)
remove.object.length = txdr_unsigned(64);
strncpy(remove.object.name, relpath, 64);
error = nfs_request(nmp, NFSPROC_REMOVE, (FAR const void *)&remove,
error = nfs_request(nmp, NFSPROC_REMOVE,
(FAR const void *)&remove, sizeof(struct REMOVE3args),
(FAR void*)&resok, sizeof(struct rpc_reply_remove));
/* Kludge City: If the first reply to the remove rpc is lost..
@ -1807,7 +1805,8 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
memcpy(&mkir.attributes, &sp, sizeof(struct nfsv3_sattr));
error = nfs_request(nmp, NFSPROC_MKDIR, (FAR const void *)&mkir,
error = nfs_request(nmp, NFSPROC_MKDIR,
(FAR const void *)&mkir, sizeof(struct MKDIR3args),
(FAR void *)&resok, sizeof(struct rpc_reply_mkdir));
if (error)
{
@ -1882,7 +1881,8 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath)
rmdir.object.length = txdr_unsigned(64);
strncpy(rmdir.object.name, relpath, 64);
error = nfs_request(nmp, NFSPROC_RMDIR, (FAR const void *)&rmdir,
error = nfs_request(nmp, NFSPROC_RMDIR,
(FAR const void *)&rmdir, sizeof(struct RMDIR3args),
(FAR void *)&resok, sizeof(struct rpc_reply_rmdir));
if (error == ENOENT)
{
@ -1962,7 +1962,8 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
rename.to.length = txdr_unsigned(64);
strncpy(rename.to.name, newrelpath, 64);
error = nfs_request(nmp, NFSPROC_RENAME, (FAR const void *)&rename,
error = nfs_request(nmp, NFSPROC_RENAME,
(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. */

View File

@ -331,6 +331,7 @@ struct rpc_call_lookup
struct rpc_call_header ch;
struct LOOKUP3args lookup;
};
#define SIZEOF_rpc_call_lookup(n) (sizeof(struct rpc_call_header) + SIZEOF_LOOKUP3args(n))
struct rpc_call_read
{
@ -410,6 +411,13 @@ struct rpc_reply_create
struct CREATE3resok create;
};
struct rpc_reply_lookup
{
struct rpc_reply_header rh;
uint32_t status;
struct LOOKUP3resok lookup;
};
struct rpc_reply_write
{
struct rpc_reply_header rh;
@ -555,17 +563,14 @@ struct rpcclnt
****************************************************************************/
void rpcclnt_init(void);
int rpcclnt_connect(struct rpcclnt *);
int rpcclnt_reconnect(struct rpctask *);
void rpcclnt_disconnect(struct rpcclnt *);
int rpcclnt_umount(struct rpcclnt *);
void rpcclnt_safedisconnect(struct rpcclnt *);
int rpcclnt_request(FAR struct rpcclnt *, int, int, int, void *,
FAR const void *, size_t);
int rpcclnt_lookup(FAR struct rpcclnt *rpc, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes);
int rpcclnt_connect(struct rpcclnt *rpc);
int rpcclnt_reconnect(struct rpctask *rep);
void rpcclnt_disconnect(struct rpcclnt *rpc);
int rpcclnt_umount(struct rpcclnt *rpc);
void rpcclnt_safedisconnect(struct rpcclnt *rpc);
int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, int version,
FAR const void *request, size_t reqlen,
FAR void *response, size_t resplen);
#undef COMP
#ifdef COMP

File diff suppressed because it is too large Load Diff