Commit d9d762e7 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: clean up the FSINFO XDR code to conform to the new scheme for GETATTR.

parent ea6cacaf
......@@ -72,7 +72,7 @@ static inline int nfs4_map_errors(int err)
/*
* This is our standard bitmap for GETATTR requests.
*/
u32 nfs4_fattr_bitmap[2] = {
const u32 nfs4_fattr_bitmap[2] = {
FATTR4_WORD0_TYPE
| FATTR4_WORD0_CHANGE
| FATTR4_WORD0_SIZE
......@@ -89,7 +89,7 @@ u32 nfs4_fattr_bitmap[2] = {
| FATTR4_WORD1_TIME_MODIFY
};
u32 nfs4_statfs_bitmap[2] = {
const u32 nfs4_statfs_bitmap[2] = {
FATTR4_WORD0_FILES_AVAIL
| FATTR4_WORD0_FILES_FREE
| FATTR4_WORD0_FILES_TOTAL,
......@@ -104,6 +104,13 @@ u32 nfs4_pathconf_bitmap[2] = {
0
};
const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
| FATTR4_WORD0_MAXREAD
| FATTR4_WORD0_MAXWRITE
| FATTR4_WORD0_LEASE_TIME,
0
};
static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
struct nfs4_readdir_arg *readdir)
{
......@@ -1198,9 +1205,13 @@ static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *fsinfo)
{
struct nfs4_fsinfo_arg args = {
.fh = fhandle,
.bitmask = nfs4_fsinfo_bitmap,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
.rpc_argp = fhandle,
.rpc_argp = &args,
.rpc_resp = fsinfo,
};
......
......@@ -624,12 +624,12 @@ static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
bitmask[1] & nfs4_fattr_bitmap[1]);
}
static int encode_fsinfo(struct xdr_stream *xdr)
static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
{
return encode_getattr_one(xdr, FATTR4_WORD0_MAXFILESIZE
| FATTR4_WORD0_MAXREAD
| FATTR4_WORD0_MAXWRITE
| FATTR4_WORD0_LEASE_TIME);
extern u32 nfs4_fsinfo_bitmap[];
return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
bitmask[1] & nfs4_fsinfo_bitmap[1]);
}
static int encode_getfh(struct xdr_stream *xdr)
......@@ -1577,7 +1577,7 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri
/*
* FSINFO request
*/
static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, void *fhandle)
static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fsinfo_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
......@@ -1587,9 +1587,9 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, void *fhandle)
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, fhandle);
status = encode_putfh(&xdr, args->fh);
if (!status)
status = encode_fsinfo(&xdr);
status = encode_fsinfo(&xdr, args->bitmask);
return status;
}
......@@ -1675,6 +1675,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
struct compound_hdr hdr = {
.nops = 3,
};
const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
......@@ -1683,7 +1684,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
if (!status)
status = encode_putrootfh(&xdr);
if (!status)
status = encode_fsinfo(&xdr);
status = encode_fsinfo(&xdr, lease_bitmap);
return status;
}
......@@ -1857,6 +1858,22 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs
return 0;
}
static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
{
uint32_t *p;
*res = 60;
if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
READ_BUF(4);
READ32(*res);
bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
}
dprintk("%s: file size=%u\n", __FUNCTION__, (unsigned int)*res);
return 0;
}
static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
{
uint32_t *p;
......@@ -1924,6 +1941,23 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin
return status;
}
static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
{
uint32_t *p;
int status = 0;
*res = 0;
if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
READ_BUF(8);
READ64(*res);
bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
}
dprintk("%s: maxfilesize=%Lu\n", __FUNCTION__, (unsigned long long)*res);
return status;
}
static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
{
uint32_t *p;
......@@ -1958,6 +1992,48 @@ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
return status;
}
static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
{
uint32_t *p;
int status = 0;
*res = 1024;
if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
uint64_t maxread;
READ_BUF(8);
READ64(maxread);
if (maxread > 0x7FFFFFFF)
maxread = 0x7FFFFFFF;
*res = (uint32_t)maxread;
bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
}
dprintk("%s: maxread=%lu\n", __FUNCTION__, (unsigned long)*res);
return status;
}
static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
{
uint32_t *p;
int status = 0;
*res = 1024;
if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
uint64_t maxwrite;
READ_BUF(8);
READ64(maxwrite);
if (maxwrite > 0x7FFFFFFF)
maxwrite = 0x7FFFFFFF;
*res = (uint32_t)maxwrite;
bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
}
dprintk("%s: maxwrite=%lu\n", __FUNCTION__, (unsigned long)*res);
return status;
}
static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *mode)
{
uint32_t *p;
......@@ -2403,69 +2479,35 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
{
uint32_t *p;
uint32_t len, attrlen, bmlen, bmval0 = 0, bmval1 = 0;
uint32_t *savep;
uint32_t attrlen, bitmap[2];
int status;
status = decode_op_hdr(xdr, OP_GETATTR);
if (status)
return status;
READ_BUF(4);
READ32(bmlen);
if (bmlen < 1)
return -EIO;
READ_BUF(bmlen << 2);
READ32(bmval0);
if (bmval0 & ~(FATTR4_WORD0_MAXFILESIZE|FATTR4_WORD0_MAXREAD|
FATTR4_WORD0_MAXWRITE|FATTR4_WORD0_LEASE_TIME))
goto out_bad_bitmap;
if (bmlen > 1) {
READ32(bmval1);
if (bmval1 != 0 || bmlen > 2)
goto out_bad_bitmap;
}
READ_BUF(4);
READ32(attrlen);
READ_BUF(attrlen);
if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
goto xdr_error;
if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
goto xdr_error;
if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
goto xdr_error;
fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */
fsinfo->lease_time = 60;
len = attrlen;
if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
len -= 4;
READ32(fsinfo->lease_time);
dprintk("read_attrs: lease_time=%d\n", fsinfo->lease_time);
}
if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
len -= 8;
READ64(fsinfo->maxfilesize);
dprintk("read_attrs: maxfilesize=0x%Lx\n", (long long) fsinfo->maxfilesize);
}
if (bmval0 & FATTR4_WORD0_MAXREAD) {
len -= 8;
READ64(fsinfo->rtmax);
fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
dprintk("read_attrs: maxread=%d\n", fsinfo->rtmax);
}
if (bmval0 & FATTR4_WORD0_MAXWRITE) {
len -= 8;
READ64(fsinfo->wtmax);
fsinfo->wtpref = fsinfo->wtmax;
dprintk("read_attrs: maxwrite=%d\n", fsinfo->wtmax);
}
if (len != 0)
goto out_bad_attrlen;
return 0;
out_bad_attrlen:
printk(KERN_NOTICE "%s: server attribute length %u does not match bitmap 0x%x/0x%x\n",
__FUNCTION__, (unsigned int)attrlen,
(unsigned int) bmval0, (unsigned int)bmval1);
return -EIO;
out_bad_bitmap:
printk(KERN_NOTICE "%s: server returned bad attribute bitmap 0x%x/0x%x\n",
__FUNCTION__,
(unsigned int)bmval0, (unsigned int)bmval1);
return -EIO;
if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
goto xdr_error;
if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
goto xdr_error;
if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
goto xdr_error;
fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
goto xdr_error;
fsinfo->wtpref = fsinfo->wtmax;
status = verify_attr_len(xdr, savep, attrlen);
xdr_error:
if (status != 0)
printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
return status;
}
static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
......
......@@ -517,6 +517,11 @@ struct nfs4_create_res {
struct nfs4_change_info dir_cinfo;
};
struct nfs4_fsinfo_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
};
struct nfs4_getattr_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment