nfsclient: Add and use nfsEvaluateStatus()

The NFS status codes do not map directly to the corresponding errno
values.
This commit is contained in:
Sebastian Huber
2012-10-02 11:30:33 +02:00
parent 3becac2ca3
commit c69ef3b6a5

View File

@@ -703,6 +703,95 @@ static RpcUdpXactPool bigPool = 0;
Implementation Implementation
*****************************************/ *****************************************/
static int nfsEvaluateStatus(nfsstat nfsStatus)
{
static const uint8_t nfsStatusToErrno [71] = {
[NFS_OK] = 0,
[NFSERR_PERM] = EPERM,
[NFSERR_NOENT] = ENOENT,
[3] = EIO,
[4] = EIO,
[NFSERR_IO] = EIO,
[NFSERR_NXIO] = ENXIO,
[7] = EIO,
[8] = EIO,
[9] = EIO,
[10] = EIO,
[11] = EIO,
[12] = EIO,
[NFSERR_ACCES] = EACCES,
[14] = EIO,
[15] = EIO,
[16] = EIO,
[NFSERR_EXIST] = EEXIST,
[18] = EIO,
[NFSERR_NODEV] = ENODEV,
[NFSERR_NOTDIR] = ENOTDIR,
[NFSERR_ISDIR] = EISDIR,
[22] = EIO,
[24] = EIO,
[25] = EIO,
[26] = EIO,
[27] = EIO,
[NFSERR_FBIG] = EFBIG,
[NFSERR_NOSPC] = ENOSPC,
[29] = EIO,
[NFSERR_ROFS] = EROFS,
[31] = EIO,
[32] = EIO,
[34] = EIO,
[35] = EIO,
[36] = EIO,
[37] = EIO,
[38] = EIO,
[39] = EIO,
[40] = EIO,
[41] = EIO,
[42] = EIO,
[44] = EIO,
[45] = EIO,
[46] = EIO,
[47] = EIO,
[48] = EIO,
[49] = EIO,
[50] = EIO,
[51] = EIO,
[52] = EIO,
[54] = EIO,
[55] = EIO,
[56] = EIO,
[57] = EIO,
[58] = EIO,
[59] = EIO,
[60] = EIO,
[61] = EIO,
[62] = EIO,
[NFSERR_NAMETOOLONG] = ENAMETOOLONG,
[64] = EIO,
[65] = EIO,
[NFSERR_NOTEMPTY] = ENOTEMPTY,
[67] = EIO,
[68] = EIO,
[NFSERR_DQUOT] = EDQUOT,
[NFSERR_STALE] = ESTALE
};
size_t idx = (size_t) nfsStatus;
int eno = EIO;
int rv = 0;
if (idx < sizeof(nfsStatusToErrno) / sizeof(nfsStatusToErrno [0])) {
eno = nfsStatusToErrno [idx];
}
if (eno != 0) {
errno = eno;
rv = -1;
}
return rv;
}
/* Create a Nfs object. This is /* Create a Nfs object. This is
* per-mounted NFS information. * per-mounted NFS information.
* *
@@ -1126,27 +1215,30 @@ int rval = -1;
static int static int
updateAttr(NfsNode node, int force) updateAttr(NfsNode node, int force)
{ {
int rv = 0;
if (force if (force
#ifdef CONFIG_ATTR_LIFETIME #ifdef CONFIG_ATTR_LIFETIME
|| (nowSeconds() - node->age > CONFIG_ATTR_LIFETIME) || (nowSeconds() - node->age > CONFIG_ATTR_LIFETIME)
#endif #endif
) { ) {
if ( nfscall(node->nfs->server, rv = nfscall(
node->nfs->server,
NFSPROC_GETATTR, NFSPROC_GETATTR,
(xdrproc_t)xdr_nfs_fh, &SERP_FILE(node), (xdrproc_t) xdr_nfs_fh, &SERP_FILE(node),
(xdrproc_t)xdr_attrstat, &node->serporid) ) (xdrproc_t) xdr_attrstat, &node->serporid
return -1; );
if ( NFS_OK != node->serporid.status ) { if (rv == 0) {
errno = node->serporid.status; rv = nfsEvaluateStatus(node->serporid.status);
return -1;
}
if (rv == 0) {
node->age = nowSeconds(); node->age = nowSeconds();
} }
}
}
return 0; return rv;
} }
/* /*
@@ -1528,16 +1620,20 @@ char *dupname;
SERP_ARGS(tNode).linkarg.to.name = dupname; SERP_ARGS(tNode).linkarg.to.name = dupname;
if ( nfscall(tNode->nfs->server, rv = nfscall(
tNode->nfs->server,
NFSPROC_LINK, NFSPROC_LINK,
(xdrproc_t)xdr_linkargs, &SERP_FILE(tNode), (xdrproc_t)xdr_linkargs, &SERP_FILE(tNode),
(xdrproc_t)xdr_nfsstat, &status) (xdrproc_t)xdr_nfsstat, &status
|| (NFS_OK != (errno = status)) );
) {
if (rv == 0) {
rv = nfsEvaluateStatus(status);
#if DEBUG & DEBUG_SYSCALLS #if DEBUG & DEBUG_SYSCALLS
if (rv != 0) {
perror("nfs_link"); perror("nfs_link");
}
#endif #endif
rv = -1;
} }
free(dupname); free(dupname);
@@ -1552,6 +1648,7 @@ static int nfs_do_unlink(
int proc int proc
) )
{ {
int rv = 0;
nfsstat status; nfsstat status;
NfsNode node = loc->node_access; NfsNode node = loc->node_access;
Nfs nfs = node->nfs; Nfs nfs = node->nfs;
@@ -1571,19 +1668,23 @@ char *name = NFSPROC_REMOVE == proc ?
fprintf(stderr,"%s '%s'\n", name, node->args.name); fprintf(stderr,"%s '%s'\n", name, node->args.name);
#endif #endif
if ( nfscall(nfs->server, rv = nfscall(
nfs->server,
proc, proc,
(xdrproc_t)xdr_diropargs, &node->args, (xdrproc_t)xdr_diropargs, &node->args,
(xdrproc_t)xdr_nfsstat, &status) (xdrproc_t)xdr_nfsstat, &status
|| (NFS_OK != (errno = status)) );
) {
if (rv == 0) {
rv = nfsEvaluateStatus(status);
#if DEBUG & DEBUG_SYSCALLS #if DEBUG & DEBUG_SYSCALLS
if (rv != 0) {
perror(name); perror(name);
}
#endif #endif
return -1;
} }
return 0; return rv;
} }
static int nfs_chown( static int nfs_chown(
@@ -1926,15 +2027,20 @@ char *dupname;
SERP_ARGS(node).createarg.attributes.mtime.seconds = now.tv_sec; SERP_ARGS(node).createarg.attributes.mtime.seconds = now.tv_sec;
SERP_ARGS(node).createarg.attributes.mtime.useconds = now.tv_usec; SERP_ARGS(node).createarg.attributes.mtime.useconds = now.tv_usec;
if ( nfscall( nfs->server, rv = nfscall(
nfs->server,
(type == S_IFDIR) ? NFSPROC_MKDIR : NFSPROC_CREATE, (type == S_IFDIR) ? NFSPROC_MKDIR : NFSPROC_CREATE,
(xdrproc_t)xdr_createargs, &SERP_FILE(node), (xdrproc_t)xdr_createargs, &SERP_FILE(node),
(xdrproc_t)xdr_diropres, &res) (xdrproc_t)xdr_diropres, &res
|| (NFS_OK != (errno = res.status)) ) { );
if (rv == 0) {
rv = nfsEvaluateStatus(res.status);
#if DEBUG & DEBUG_SYSCALLS #if DEBUG & DEBUG_SYSCALLS
if (rv != 0) {
perror("nfs_mknod"); perror("nfs_mknod");
}
#endif #endif
rv = -1;
} }
free(dupname); free(dupname);
@@ -2017,15 +2123,18 @@ char *dupname;
SERP_ARGS(node).symlinkarg.attributes.mtime.seconds = now.tv_sec; SERP_ARGS(node).symlinkarg.attributes.mtime.seconds = now.tv_sec;
SERP_ARGS(node).symlinkarg.attributes.mtime.useconds = now.tv_usec; SERP_ARGS(node).symlinkarg.attributes.mtime.useconds = now.tv_usec;
if ( nfscall( nfs->server, rv = nfscall(
nfs->server,
NFSPROC_SYMLINK, NFSPROC_SYMLINK,
(xdrproc_t)xdr_symlinkargs, &SERP_FILE(node), (xdrproc_t)xdr_symlinkargs, &SERP_FILE(node),
(xdrproc_t)xdr_nfsstat, &status) (xdrproc_t)xdr_nfsstat, &status
|| (NFS_OK != (errno = status)) ) { );
if (rv == 0) {
rv = nfsEvaluateStatus(status);
#if DEBUG & DEBUG_SYSCALLS #if DEBUG & DEBUG_SYSCALLS
perror("nfs_symlink"); perror("nfs_symlink");
#endif #endif
rv = -1;
} }
free(dupname); free(dupname);
@@ -2039,24 +2148,33 @@ static ssize_t nfs_readlink_with_node(
size_t len size_t len
) )
{ {
ssize_t rv;
Nfs nfs = node->nfs; Nfs nfs = node->nfs;
readlinkres_strbuf rr; readlinkres_strbuf rr;
rr.strbuf.buf = buf; rr.strbuf.buf = buf;
rr.strbuf.max = len - 1; rr.strbuf.max = len - 1;
if ( nfscall(nfs->server, rv = nfscall(
nfs->server,
NFSPROC_READLINK, NFSPROC_READLINK,
(xdrproc_t)xdr_nfs_fh, &SERP_FILE(node), (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
(xdrproc_t)xdr_readlinkres_strbuf, &rr) (xdrproc_t)xdr_readlinkres_strbuf, &rr
|| (NFS_OK != (errno = rr.status)) ) { );
if (rv == 0) {
rv = nfsEvaluateStatus(rr.status);
if (rv == 0) {
rv = (ssize_t) strlen(rr.strbuf.buf);
} else {
#if DEBUG & DEBUG_SYSCALLS #if DEBUG & DEBUG_SYSCALLS
perror("nfs_readlink_with_node"); perror("nfs_readlink_with_node");
#endif #endif
return -1; }
} }
return (ssize_t) strlen(rr.strbuf.buf); return rv;
} }
static ssize_t nfs_readlink( static ssize_t nfs_readlink(
@@ -2102,8 +2220,9 @@ static int nfs_rename(
(xdrproc_t) xdr_nfsstat, (xdrproc_t) xdr_nfsstat,
&status &status
); );
if (rv == 0 && (errno = status) != NFS_OK) {
rv = -1; if (rv == 0) {
rv = nfsEvaluateStatus(status);
} }
free(dupname); free(dupname);
@@ -2277,6 +2396,7 @@ static ssize_t nfs_file_read_chunk(
size_t count size_t count
) )
{ {
ssize_t rv;
readres rr; readres rr;
Nfs nfs = node->nfs; Nfs nfs = node->nfs;
@@ -2286,17 +2406,18 @@ Nfs nfs = node->nfs;
rr.readres_u.reply.data.data_val = buffer; rr.readres_u.reply.data.data_val = buffer;
if ( nfscall( nfs->server, rv = nfscall(
nfs->server,
NFSPROC_READ, NFSPROC_READ,
(xdrproc_t)xdr_readargs, &SERP_FILE(node), (xdrproc_t)xdr_readargs, &SERP_FILE(node),
(xdrproc_t)xdr_readres, &rr) ) { (xdrproc_t)xdr_readres, &rr
return -1; );
}
if (rv == 0) {
rv = nfsEvaluateStatus(rr.status);
if (NFS_OK != rr.status) { if (rv == 0) {
rtems_set_errno_and_return_minus_one(rr.status); rv = rr.readres_u.reply.data.data_len;
}
#if DEBUG & DEBUG_SYSCALLS #if DEBUG & DEBUG_SYSCALLS
fprintf(stderr, fprintf(stderr,
@@ -2306,9 +2427,10 @@ Nfs nfs = node->nfs;
iop->offset, iop->offset,
rr.readres_u.reply.data.data_val); rr.readres_u.reply.data.data_val);
#endif #endif
}
}
return rv;
return rr.readres_u.reply.data.data_len;
} }
static ssize_t nfs_file_read( static ssize_t nfs_file_read(
@@ -2353,6 +2475,7 @@ static ssize_t nfs_dir_read(
size_t count size_t count
) )
{ {
ssize_t rv;
DirInfo di = iop->pathinfo.node_access_2; DirInfo di = iop->pathinfo.node_access_2;
RpcUdpServer server = ((Nfs)iop->pathinfo.mt_entry->fs_info)->server; RpcUdpServer server = ((Nfs)iop->pathinfo.mt_entry->fs_info)->server;
@@ -2388,20 +2511,22 @@ RpcUdpServer server = ((Nfs)iop->pathinfo.mt_entry->fs_info)->server;
count, di->len); count, di->len);
#endif #endif
if ( nfscall( rv = nfscall(
server, server,
NFSPROC_READDIR, NFSPROC_READDIR,
(xdrproc_t)xdr_readdirargs, &di->readdirargs, (xdrproc_t)xdr_readdirargs, &di->readdirargs,
(xdrproc_t)xdr_dir_info, di) ) { (xdrproc_t)xdr_dir_info, di
return -1; );
if (rv == 0) {
rv = nfsEvaluateStatus(di->status);
if (rv == 0) {
rv = (char*)di->ptr - (char*)buffer;
}
} }
return rv;
if (NFS_OK != di->status) {
rtems_set_errno_and_return_minus_one(di->status);
}
return (char*)di->ptr - (char*)buffer;
} }
static ssize_t nfs_file_write( static ssize_t nfs_file_write(
@@ -2410,9 +2535,9 @@ static ssize_t nfs_file_write(
size_t count size_t count
) )
{ {
ssize_t rv;
NfsNode node = iop->pathinfo.node_access; NfsNode node = iop->pathinfo.node_access;
Nfs nfs = node->nfs; Nfs nfs = node->nfs;
int e;
if (count > NFS_MAXDATA) if (count > NFS_MAXDATA)
count = NFS_MAXDATA; count = NFS_MAXDATA;
@@ -2435,25 +2560,28 @@ int e;
* on the PROC specifier * on the PROC specifier
*/ */
if ( nfscall( nfs->server, rv = nfscall(
nfs->server,
NFSPROC_WRITE, NFSPROC_WRITE,
(xdrproc_t)xdr_writeargs, &SERP_FILE(node), (xdrproc_t)xdr_writeargs, &SERP_FILE(node),
(xdrproc_t)xdr_attrstat, &node->serporid) ) { (xdrproc_t)xdr_attrstat, &node->serporid
return -1; );
}
if (rv == 0) {
rv = nfsEvaluateStatus(node->serporid.status);
if (NFS_OK != (e=node->serporid.status) ) { if (rv == 0) {
/* try at least to recover the current attributes */
updateAttr(node, 1 /* force */);
rtems_set_errno_and_return_minus_one(e);
}
node->age = nowSeconds(); node->age = nowSeconds();
iop->offset += count; iop->offset += count;
rv = count;
} else {
/* try at least to recover the current attributes */
updateAttr(node, 1 /* force */);
}
}
return count; return rv;
} }
static off_t nfs_dir_lseek( static off_t nfs_dir_lseek(
@@ -2590,10 +2718,9 @@ fattr *fa = &SERP_ATTR(node);
static int static int
nfs_sattr(NfsNode node, sattr *arg, u_long mask) nfs_sattr(NfsNode node, sattr *arg, u_long mask)
{ {
int rv;
struct timeval now; struct timeval now;
nfstime nfsnow, t; nfstime nfsnow, t;
int e;
u_int mode; u_int mode;
if (updateAttr(node, 0 /* only if old */)) if (updateAttr(node, 0 /* only if old */))
@@ -2642,31 +2769,35 @@ u_int mode;
node->serporid.status = NFS_OK; node->serporid.status = NFS_OK;
if ( nfscall( node->nfs->server, rv = nfscall(
node->nfs->server,
NFSPROC_SETATTR, NFSPROC_SETATTR,
(xdrproc_t)xdr_sattrargs, &SERP_FILE(node), (xdrproc_t)xdr_sattrargs, &SERP_FILE(node),
(xdrproc_t)xdr_attrstat, &node->serporid) ) { (xdrproc_t)xdr_attrstat, &node->serporid
);
if (rv == 0) {
rv = nfsEvaluateStatus(node->serporid.status);
if (rv == 0) {
node->age = nowSeconds();
} else {
#if DEBUG & DEBUG_SYSCALLS
fprintf(stderr,"nfs_sattr: %s\n",strerror(errno));
#endif
/* try at least to recover the current attributes */
updateAttr(node, 1 /* force */);
}
} else {
#if DEBUG & DEBUG_SYSCALLS #if DEBUG & DEBUG_SYSCALLS
fprintf(stderr, fprintf(stderr,
"nfs_sattr (mask 0x%08x): %s", "nfs_sattr (mask 0x%08x): %s",
mask, mask,
strerror(errno)); strerror(errno));
#endif #endif
return -1;
} }
if (NFS_OK != (e=node->serporid.status) ) { return rv;
#if DEBUG & DEBUG_SYSCALLS
fprintf(stderr,"nfs_sattr: %s\n",strerror(e));
#endif
/* try at least to recover the current attributes */
updateAttr(node, 1 /* force */);
rtems_set_errno_and_return_minus_one(e);
}
node->age = nowSeconds();
return 0;
} }
/* just set the size attribute to 'length' /* just set the size attribute to 'length'