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) ...@@ -72,7 +72,7 @@ static inline int nfs4_map_errors(int err)
/* /*
* This is our standard bitmap for GETATTR requests. * This is our standard bitmap for GETATTR requests.
*/ */
u32 nfs4_fattr_bitmap[2] = { const u32 nfs4_fattr_bitmap[2] = {
FATTR4_WORD0_TYPE FATTR4_WORD0_TYPE
| FATTR4_WORD0_CHANGE | FATTR4_WORD0_CHANGE
| FATTR4_WORD0_SIZE | FATTR4_WORD0_SIZE
...@@ -89,7 +89,7 @@ u32 nfs4_fattr_bitmap[2] = { ...@@ -89,7 +89,7 @@ u32 nfs4_fattr_bitmap[2] = {
| FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY
}; };
u32 nfs4_statfs_bitmap[2] = { const u32 nfs4_statfs_bitmap[2] = {
FATTR4_WORD0_FILES_AVAIL FATTR4_WORD0_FILES_AVAIL
| FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_FREE
| FATTR4_WORD0_FILES_TOTAL, | FATTR4_WORD0_FILES_TOTAL,
...@@ -104,6 +104,13 @@ u32 nfs4_pathconf_bitmap[2] = { ...@@ -104,6 +104,13 @@ u32 nfs4_pathconf_bitmap[2] = {
0 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, static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
struct nfs4_readdir_arg *readdir) struct nfs4_readdir_arg *readdir)
{ {
...@@ -1198,9 +1205,13 @@ static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -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, static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *fsinfo) struct nfs_fsinfo *fsinfo)
{ {
struct nfs4_fsinfo_arg args = {
.fh = fhandle,
.bitmask = nfs4_fsinfo_bitmap,
};
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
.rpc_argp = fhandle, .rpc_argp = &args,
.rpc_resp = fsinfo, .rpc_resp = fsinfo,
}; };
......
...@@ -624,12 +624,12 @@ static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask) ...@@ -624,12 +624,12 @@ static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
bitmask[1] & nfs4_fattr_bitmap[1]); 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 extern u32 nfs4_fsinfo_bitmap[];
| FATTR4_WORD0_MAXREAD
| FATTR4_WORD0_MAXWRITE return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
| FATTR4_WORD0_LEASE_TIME); bitmask[1] & nfs4_fsinfo_bitmap[1]);
} }
static int encode_getfh(struct xdr_stream *xdr) 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 ...@@ -1577,7 +1577,7 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri
/* /*
* FSINFO request * 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 xdr_stream xdr;
struct compound_hdr hdr = { struct compound_hdr hdr = {
...@@ -1587,9 +1587,9 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, void *fhandle) ...@@ -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); xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr); encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, fhandle); status = encode_putfh(&xdr, args->fh);
if (!status) if (!status)
status = encode_fsinfo(&xdr); status = encode_fsinfo(&xdr, args->bitmask);
return status; return status;
} }
...@@ -1675,6 +1675,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s ...@@ -1675,6 +1675,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
struct compound_hdr hdr = { struct compound_hdr hdr = {
.nops = 3, .nops = 3,
}; };
const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
int status; int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p); 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 ...@@ -1683,7 +1684,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
if (!status) if (!status)
status = encode_putrootfh(&xdr); status = encode_putrootfh(&xdr);
if (!status) if (!status)
status = encode_fsinfo(&xdr); status = encode_fsinfo(&xdr, lease_bitmap);
return status; return status;
} }
...@@ -1857,6 +1858,22 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs ...@@ -1857,6 +1858,22 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs
return 0; 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) static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
{ {
uint32_t *p; uint32_t *p;
...@@ -1924,6 +1941,23 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin ...@@ -1924,6 +1941,23 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin
return status; 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) static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
{ {
uint32_t *p; uint32_t *p;
...@@ -1958,6 +1992,48 @@ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ ...@@ -1958,6 +1992,48 @@ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
return status; 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) static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *mode)
{ {
uint32_t *p; uint32_t *p;
...@@ -2403,69 +2479,35 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons ...@@ -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) static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
{ {
uint32_t *p; uint32_t *savep;
uint32_t len, attrlen, bmlen, bmval0 = 0, bmval1 = 0; uint32_t attrlen, bitmap[2];
int status; int status;
status = decode_op_hdr(xdr, OP_GETATTR); if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
if (status) goto xdr_error;
return status; if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
READ_BUF(4); goto xdr_error;
READ32(bmlen); if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
if (bmlen < 1) goto xdr_error;
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);
fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */ fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */
fsinfo->lease_time = 60;
len = attrlen; if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
goto xdr_error;
if (bmval0 & FATTR4_WORD0_LEASE_TIME) { if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
len -= 4; goto xdr_error;
READ32(fsinfo->lease_time); if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
dprintk("read_attrs: lease_time=%d\n", fsinfo->lease_time); goto xdr_error;
}
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; fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
dprintk("read_attrs: maxread=%d\n", fsinfo->rtmax); if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
} goto xdr_error;
if (bmval0 & FATTR4_WORD0_MAXWRITE) {
len -= 8;
READ64(fsinfo->wtmax);
fsinfo->wtpref = fsinfo->wtmax; fsinfo->wtpref = fsinfo->wtmax;
dprintk("read_attrs: maxwrite=%d\n", fsinfo->wtmax);
} status = verify_attr_len(xdr, savep, attrlen);
if (len != 0) xdr_error:
goto out_bad_attrlen; if (status != 0)
return 0; printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
out_bad_attrlen: return status;
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;
} }
static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
......
...@@ -517,6 +517,11 @@ struct nfs4_create_res { ...@@ -517,6 +517,11 @@ struct nfs4_create_res {
struct nfs4_change_info dir_cinfo; struct nfs4_change_info dir_cinfo;
}; };
struct nfs4_fsinfo_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
};
struct nfs4_getattr_arg { struct nfs4_getattr_arg {
const struct nfs_fh * fh; const struct nfs_fh * fh;
const u32 * bitmask; 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