#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
#include <linux/nfsacl.h>
+#include "internal.h"
#define NFSDBG_FACILITY NFSDBG_XDR
/* Mapping from NFS error code to "errno" error code. */
#define errno_NFSERR_IO EIO
-extern int nfs_stat_to_errno(int);
-
/*
* Declare the space requirements for NFS arguments and replies as
* number of 32bit-words
#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
+#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
#define NFS3_accessargs_sz (NFS3_fh_sz+1)
#define NFS3_readlinkargs_sz (NFS3_fh_sz)
#define NFS3_readargs_sz (NFS3_fh_sz+3)
#define NFS3_writeargs_sz (NFS3_fh_sz+5)
#define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
-#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz)
+#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
#define NFS3_attrstat_sz (1+NFS3_fattr_sz)
#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
+#define NFS3_removeres_sz (NFS3_wccstat_sz)
#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
-#define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3))
-#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
+#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
+ XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
+#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
+ XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
/*
* Map file type to S_IFMT bits
*/
-static struct {
- unsigned int mode;
- unsigned int nfs2type;
-} nfs_type2fmt[] = {
- { 0, NFNON },
- { S_IFREG, NFREG },
- { S_IFDIR, NFDIR },
- { S_IFBLK, NFBLK },
- { S_IFCHR, NFCHR },
- { S_IFLNK, NFLNK },
- { S_IFSOCK, NFSOCK },
- { S_IFIFO, NFFIFO },
- { 0, NFBAD }
+static const umode_t nfs_type2fmt[] = {
+ [NF3BAD] = 0,
+ [NF3REG] = S_IFREG,
+ [NF3DIR] = S_IFDIR,
+ [NF3BLK] = S_IFBLK,
+ [NF3CHR] = S_IFCHR,
+ [NF3LNK] = S_IFLNK,
+ [NF3SOCK] = S_IFSOCK,
+ [NF3FIFO] = S_IFIFO,
};
/*
* Common NFS XDR functions as inlines
*/
-static inline u32 *
-xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
+static inline __be32 *
+xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
{
return xdr_encode_array(p, fh->data, fh->size);
}
-static inline u32 *
-xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
+static inline __be32 *
+xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
{
if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
memcpy(fh->data, p, fh->size);
/*
* Encode/decode time.
*/
-static inline u32 *
-xdr_encode_time3(u32 *p, struct timespec *timep)
+static inline __be32 *
+xdr_encode_time3(__be32 *p, struct timespec *timep)
{
*p++ = htonl(timep->tv_sec);
*p++ = htonl(timep->tv_nsec);
return p;
}
-static inline u32 *
-xdr_decode_time3(u32 *p, struct timespec *timep)
+static inline __be32 *
+xdr_decode_time3(__be32 *p, struct timespec *timep)
{
timep->tv_sec = ntohl(*p++);
timep->tv_nsec = ntohl(*p++);
return p;
}
-static u32 *
-xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
+static __be32 *
+xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
{
unsigned int type, major, minor;
- int fmode;
+ umode_t fmode;
type = ntohl(*p++);
- if (type >= NF3BAD)
- type = NF3BAD;
- fmode = nfs_type2fmt[type].mode;
- fattr->type = nfs_type2fmt[type].nfs2type;
+ if (type > NF3FIFO)
+ type = NF3NON;
+ fmode = nfs_type2fmt[type];
fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
fattr->nlink = ntohl(*p++);
fattr->uid = ntohl(*p++);
if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
fattr->rdev = 0;
- p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3);
+ p = xdr_decode_hyper(p, &fattr->fsid.major);
+ fattr->fsid.minor = 0;
p = xdr_decode_hyper(p, &fattr->fileid);
p = xdr_decode_time3(p, &fattr->atime);
p = xdr_decode_time3(p, &fattr->mtime);
p = xdr_decode_time3(p, &fattr->ctime);
/* Update the mode bits */
- fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
+ fattr->valid |= NFS_ATTR_FATTR_V3;
return p;
}
-static inline u32 *
-xdr_encode_sattr(u32 *p, struct iattr *attr)
+static inline __be32 *
+xdr_encode_sattr(__be32 *p, struct iattr *attr)
{
if (attr->ia_valid & ATTR_MODE) {
*p++ = xdr_one;
return p;
}
-static inline u32 *
-xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
{
p = xdr_decode_hyper(p, &fattr->pre_size);
p = xdr_decode_time3(p, &fattr->pre_mtime);
p = xdr_decode_time3(p, &fattr->pre_ctime);
- fattr->valid |= NFS_ATTR_WCC;
+ fattr->valid |= NFS_ATTR_FATTR_PRESIZE
+ | NFS_ATTR_FATTR_PREMTIME
+ | NFS_ATTR_FATTR_PRECTIME;
return p;
}
-static inline u32 *
-xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
{
if (*p++)
p = xdr_decode_fattr(p, fattr);
return p;
}
-static inline u32 *
-xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
{
if (*p++)
return xdr_decode_wcc_attr(p, fattr);
}
-static inline u32 *
-xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
{
p = xdr_decode_pre_op_attr(p, fattr);
return xdr_decode_post_op_attr(p, fattr);
* Encode file handle argument
*/
static int
-nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
+nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
{
p = xdr_encode_fhandle(p, fh);
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
* Encode SETATTR arguments
*/
static int
-nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args)
+nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_sattr(p, args->sattr);
* Encode directory ops argument
*/
static int
-nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args)
+nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name, args->len);
}
/*
+ * Encode REMOVE argument
+ */
+static int
+nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
+{
+ p = xdr_encode_fhandle(p, args->fh);
+ p = xdr_encode_array(p, args->name.name, args->name.len);
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+ return 0;
+}
+
+/*
* Encode access() argument
*/
static int
-nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args)
+nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
*p++ = htonl(args->access);
* exactly to the page we want to fetch.
*/
static int
-nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
+nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
u32 count = args->count;
replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
xdr_inline_pages(&req->rq_rcv_buf, replen,
args->pages, args->pgbase, count);
+ req->rq_rcv_buf.flags |= XDRBUF_READ;
return 0;
}
* Write arguments. Splice the buffer to be written into the iovec.
*/
static int
-nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
+nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
{
struct xdr_buf *sndbuf = &req->rq_snd_buf;
u32 count = args->count;
/* Copy the page array */
xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
+ sndbuf->flags |= XDRBUF_WRITE;
return 0;
}
* Encode CREATE arguments
*/
static int
-nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args)
+nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name, args->len);
* Encode MKDIR arguments
*/
static int
-nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args)
+nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name, args->len);
* Encode SYMLINK arguments
*/
static int
-nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args)
+nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
{
p = xdr_encode_fhandle(p, args->fromfh);
p = xdr_encode_array(p, args->fromname, args->fromlen);
p = xdr_encode_sattr(p, args->sattr);
- p = xdr_encode_array(p, args->topath, args->tolen);
+ *p++ = htonl(args->pathlen);
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+
+ /* Copy the page */
+ xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
return 0;
}
* Encode MKNOD arguments
*/
static int
-nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
+nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name, args->len);
* Encode RENAME arguments
*/
static int
-nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
+nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
{
p = xdr_encode_fhandle(p, args->fromfh);
p = xdr_encode_array(p, args->fromname, args->fromlen);
* Encode LINK arguments
*/
static int
-nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
+nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
{
p = xdr_encode_fhandle(p, args->fromfh);
p = xdr_encode_fhandle(p, args->tofh);
* Encode arguments to readdir call
*/
static int
-nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
+nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
u32 count = args->count;
* We just check for syntactical correctness.
*/
static int
-nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
+nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
{
struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
struct kvec *iov = rcvbuf->head;
struct page **page;
- int hdrlen, recvd;
- int status, nr;
- unsigned int len, pglen;
- u32 *entry, *end, *kaddr;
+ size_t hdrlen;
+ u32 len, recvd, pglen;
+ int status, nr = 0;
+ __be32 *entry, *end, *kaddr;
status = ntohl(*p++);
/* Decode post_op_attrs */
p = xdr_decode_post_op_attr(p, res->dir_attr);
if (status)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
/* Decode verifier cookie */
if (res->verf) {
res->verf[0] = *p++;
hdrlen = (u8 *) p - (u8 *) iov->iov_base;
if (iov->iov_len < hdrlen) {
- printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
- "length %d > %Zu\n", hdrlen, iov->iov_len);
+ dprintk("NFS: READDIR reply header overflowed:"
+ "length %Zu > %Zu\n", hdrlen, iov->iov_len);
return -errno_NFSERR_IO;
} else if (iov->iov_len != hdrlen) {
dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
if (pglen > recvd)
pglen = recvd;
page = rcvbuf->pages;
- kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
- end = (u32 *)((char *)p + pglen);
+ kaddr = p = kmap_atomic(*page, KM_USER0);
+ end = (__be32 *)((char *)p + pglen);
entry = p;
- for (nr = 0; *p++; nr++) {
+
+ /* Make sure the packet actually has a value_follows and EOF entry */
+ if ((entry + 1) > end)
+ goto short_pkt;
+
+ for (; *p++; nr++) {
if (p + 3 > end)
goto short_pkt;
p += 2; /* inode # */
len = ntohl(*p++); /* string length */
p += XDR_QUADLEN(len) + 2; /* name + cookie */
if (len > NFS3_MAXNAMLEN) {
- printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
+ dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
len);
goto err_unmap;
}
goto short_pkt;
len = ntohl(*p++);
if (len > NFS3_FHSIZE) {
- printk(KERN_WARNING "NFS: giant filehandle in "
- "readdir (len %x)!\n", len);
+ dprintk("NFS: giant filehandle in "
+ "readdir (len 0x%x)!\n", len);
goto err_unmap;
}
p += XDR_QUADLEN(len);
goto short_pkt;
entry = p;
}
- if (!nr && (entry[0] != 0 || entry[1] == 0))
- goto short_pkt;
+
+ /*
+ * Apparently some server sends responses that are a valid size, but
+ * contain no entries, and have value_follows==0 and EOF==0. For
+ * those, just set the EOF marker.
+ */
+ if (!nr && entry[1] == 0) {
+ dprintk("NFS: readdir reply truncated!\n");
+ entry[1] = 1;
+ }
out:
kunmap_atomic(kaddr, KM_USER0);
return nr;
short_pkt:
+ /*
+ * When we get a short packet there are 2 possibilities. We can
+ * return an error, or fix up the response to look like a valid
+ * response and return what we have so far. If there are no
+ * entries and the packet was short, then return -EIO. If there
+ * are valid entries in the response, return them and pretend that
+ * the call was successful, but incomplete. The caller can retry the
+ * readdir starting at the last cookie.
+ */
entry[0] = entry[1] = 0;
- /* truncate listing ? */
- if (!nr) {
- printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
- entry[1] = 1;
- }
+ if (!nr)
+ nr = -errno_NFSERR_IO;
goto out;
err_unmap:
nr = -errno_NFSERR_IO;
goto out;
}
-u32 *
-nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
+__be32 *
+nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
{
struct nfs_entry old = *entry;
* Encode COMMIT arguments
*/
static int
-nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
+nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_hyper(p, args->offset);
* Encode GETACL arguments
*/
static int
-nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
+nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
struct nfs3_getaclargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
p = xdr_encode_fhandle(p, args->fh);
* Encode SETACL arguments
*/
static int
-nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
+nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
struct nfs3_setaclargs *args)
{
struct xdr_buf *buf = &req->rq_snd_buf;
- unsigned int base, len_in_head, len = nfsacl_size(
- (args->mask & NFS_ACL) ? args->acl_access : NULL,
- (args->mask & NFS_DFACL) ? args->acl_default : NULL);
- int count, err;
+ unsigned int base;
+ int err;
p = xdr_encode_fhandle(p, NFS_FH(args->inode));
*p++ = htonl(args->mask);
- base = (char *)p - (char *)buf->head->iov_base;
- /* put as much of the acls into head as possible. */
- len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
- len -= len_in_head;
- req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
-
- for (count = 0; (count << PAGE_SHIFT) < len; count++) {
- args->pages[count] = alloc_page(GFP_KERNEL);
- if (!args->pages[count]) {
- while (count)
- __free_page(args->pages[--count]);
- return -ENOMEM;
- }
- }
- xdr_encode_pages(buf, args->pages, 0, len);
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+ base = req->rq_slen;
+
+ if (args->npages != 0)
+ xdr_encode_pages(buf, args->pages, 0, args->len);
+ else
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec,
+ p + XDR_QUADLEN(args->len));
err = nfsacl_encode(buf, base, args->inode,
(args->mask & NFS_ACL) ?
* Decode attrstat reply.
*/
static int
-nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
{
int status;
if ((status = ntohl(*p++)))
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
xdr_decode_fattr(p, fattr);
return 0;
}
* SATTR, REMOVE, RMDIR
*/
static int
-nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
{
int status;
if ((status = ntohl(*p++)))
- status = -nfs_stat_to_errno(status);
+ status = nfs_stat_to_errno(status);
xdr_decode_wcc_data(p, fattr);
return status;
}
+static int
+nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
+{
+ return nfs3_xdr_wccstat(req, p, &res->dir_attr);
+}
+
/*
* Decode LOOKUP reply
*/
static int
-nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
+nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
{
int status;
if ((status = ntohl(*p++))) {
- status = -nfs_stat_to_errno(status);
+ status = nfs_stat_to_errno(status);
} else {
if (!(p = xdr_decode_fhandle(p, res->fh)))
return -errno_NFSERR_IO;
* Decode ACCESS reply
*/
static int
-nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
+nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
{
int status = ntohl(*p++);
p = xdr_decode_post_op_attr(p, res->fattr);
if (status)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
res->access = ntohl(*p++);
return 0;
}
static int
-nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
+nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
p = xdr_encode_fhandle(p, args->fh);
* Decode READLINK reply
*/
static int
-nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
{
struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
struct kvec *iov = rcvbuf->head;
- int hdrlen, len, recvd;
+ size_t hdrlen;
+ u32 len, recvd;
char *kaddr;
int status;
p = xdr_decode_post_op_attr(p, fattr);
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
/* Convert length of symlink */
len = ntohl(*p++);
- if (len >= rcvbuf->page_len || len <= 0) {
- dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+ if (len >= rcvbuf->page_len) {
+ dprintk("nfs: server returned giant symlink!\n");
return -ENAMETOOLONG;
}
hdrlen = (u8 *) p - (u8 *) iov->iov_base;
if (iov->iov_len < hdrlen) {
- printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
- "length %d > %Zu\n", hdrlen, iov->iov_len);
+ dprintk("NFS: READLINK reply header overflowed:"
+ "length %Zu > %Zu\n", hdrlen, iov->iov_len);
return -errno_NFSERR_IO;
} else if (iov->iov_len != hdrlen) {
- dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
+ dprintk("NFS: READLINK header is short. "
+ "iovec will be shifted.\n");
xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
}
recvd = req->rq_rcv_buf.len - hdrlen;
if (recvd < len) {
- printk(KERN_WARNING "NFS: server cheating in readlink reply: "
+ dprintk("NFS: server cheating in readlink reply: "
"count %u > recvd %u\n", len, recvd);
return -EIO;
}
* Decode READ reply
*/
static int
-nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
+nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
{
struct kvec *iov = req->rq_rcv_buf.head;
- int status, count, ocount, recvd, hdrlen;
+ size_t hdrlen;
+ u32 count, ocount, recvd;
+ int status;
status = ntohl(*p++);
p = xdr_decode_post_op_attr(p, res->fattr);
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
- /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
+ /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
* in that it puts the count both in the res struct and in the
* opaque data count. */
count = ntohl(*p++);
ocount = ntohl(*p++);
if (ocount != count) {
- printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
+ dprintk("NFS: READ count doesn't match RPC opaque count.\n");
return -errno_NFSERR_IO;
}
hdrlen = (u8 *) p - (u8 *) iov->iov_base;
if (iov->iov_len < hdrlen) {
- printk(KERN_WARNING "NFS: READ reply header overflowed:"
- "length %d > %Zu\n", hdrlen, iov->iov_len);
+ dprintk("NFS: READ reply header overflowed:"
+ "length %Zu > %Zu\n", hdrlen, iov->iov_len);
return -errno_NFSERR_IO;
} else if (iov->iov_len != hdrlen) {
dprintk("NFS: READ header is short. iovec will be shifted.\n");
recvd = req->rq_rcv_buf.len - hdrlen;
if (count > recvd) {
- printk(KERN_WARNING "NFS: server cheating in read reply: "
- "count %d > recvd %d\n", count, recvd);
+ dprintk("NFS: server cheating in read reply: "
+ "count %u > recvd %u\n", count, recvd);
count = recvd;
res->eof = 0;
}
* Decode WRITE response
*/
static int
-nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
+nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
{
int status;
p = xdr_decode_wcc_data(p, res->fattr);
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
res->count = ntohl(*p++);
res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
* Decode a CREATE response
*/
static int
-nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
+nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
{
int status;
res->fattr->valid = 0;
}
} else {
- status = -nfs_stat_to_errno(status);
+ status = nfs_stat_to_errno(status);
}
p = xdr_decode_wcc_data(p, res->dir_attr);
return status;
* Decode RENAME reply
*/
static int
-nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
+nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
{
int status;
if ((status = ntohl(*p++)) != 0)
- status = -nfs_stat_to_errno(status);
+ status = nfs_stat_to_errno(status);
p = xdr_decode_wcc_data(p, res->fromattr);
p = xdr_decode_wcc_data(p, res->toattr);
return status;
* Decode LINK reply
*/
static int
-nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
+nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
{
int status;
if ((status = ntohl(*p++)) != 0)
- status = -nfs_stat_to_errno(status);
+ status = nfs_stat_to_errno(status);
p = xdr_decode_post_op_attr(p, res->fattr);
p = xdr_decode_wcc_data(p, res->dir_attr);
return status;
* Decode FSSTAT reply
*/
static int
-nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res)
+nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
{
int status;
p = xdr_decode_post_op_attr(p, res->fattr);
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
p = xdr_decode_hyper(p, &res->tbytes);
p = xdr_decode_hyper(p, &res->fbytes);
* Decode FSINFO reply
*/
static int
-nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
+nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
{
int status;
p = xdr_decode_post_op_attr(p, res->fattr);
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
res->rtmax = ntohl(*p++);
res->rtpref = ntohl(*p++);
* Decode PATHCONF reply
*/
static int
-nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res)
+nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
{
int status;
p = xdr_decode_post_op_attr(p, res->fattr);
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
res->max_link = ntohl(*p++);
res->max_namelen = ntohl(*p++);
* Decode COMMIT reply
*/
static int
-nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
+nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
{
int status;
status = ntohl(*p++);
p = xdr_decode_wcc_data(p, res->fattr);
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
res->verf->verifier[0] = *p++;
res->verf->verifier[1] = *p++;
* Decode GETACL reply
*/
static int
-nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
+nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
struct nfs3_getaclres *res)
{
struct xdr_buf *buf = &req->rq_rcv_buf;
int err, base;
if (status != 0)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
p = xdr_decode_post_op_attr(p, res->fattr);
res->mask = ntohl(*p++);
if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
* Decode setacl reply.
*/
static int
-nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
{
int status = ntohl(*p++);
if (status)
- return -nfs_stat_to_errno(status);
+ return nfs_stat_to_errno(status);
xdr_decode_post_op_attr(p, fattr);
return 0;
}
#endif /* CONFIG_NFS_V3_ACL */
-#ifndef MAX
-# define MAX(a, b) (((a) > (b))? (a) : (b))
-#endif
-
#define PROC(proc, argtype, restype, timer) \
[NFS3PROC_##proc] = { \
.p_proc = NFS3PROC_##proc, \
.p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
.p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
- .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
- .p_timer = timer \
+ .p_arglen = NFS3_##argtype##_sz, \
+ .p_replen = NFS3_##restype##_sz, \
+ .p_timer = timer, \
+ .p_statidx = NFS3PROC_##proc, \
+ .p_name = #proc, \
}
struct rpc_procinfo nfs3_procedures[] = {
PROC(MKDIR, mkdirargs, createres, 0),
PROC(SYMLINK, symlinkargs, createres, 0),
PROC(MKNOD, mknodargs, createres, 0),
- PROC(REMOVE, diropargs, wccstat, 0),
+ PROC(REMOVE, removeargs, removeres, 0),
PROC(RMDIR, diropargs, wccstat, 0),
PROC(RENAME, renameargs, renameres, 0),
PROC(LINK, linkargs, linkres, 0),
struct rpc_version nfs_version3 = {
.number = 3,
- .nrprocs = sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
+ .nrprocs = ARRAY_SIZE(nfs3_procedures),
.procs = nfs3_procedures
};
.p_proc = ACLPROC3_GETACL,
.p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
.p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
- .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
+ .p_arglen = ACL3_getaclargs_sz,
+ .p_replen = ACL3_getaclres_sz,
.p_timer = 1,
+ .p_name = "GETACL",
},
[ACLPROC3_SETACL] = {
.p_proc = ACLPROC3_SETACL,
.p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
.p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
- .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
+ .p_arglen = ACL3_setaclargs_sz,
+ .p_replen = ACL3_setaclres_sz,
.p_timer = 0,
+ .p_name = "SETACL",
},
};