Commit f414757e authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Split out the code for retrieving static server

information out of the GETATTR compound.
parent 7cf3d8b7
......@@ -56,6 +56,9 @@ extern struct rpc_procinfo nfs4_procedures[];
extern nfs4_stateid zero_stateid;
static int nfs4_proc_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static void
nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops,
struct nfs_server *server, char *tag)
......@@ -177,44 +180,16 @@ u32 nfs4_statfs_bitmap[2] = {
| FATTR4_WORD1_SPACE_TOTAL
};
u32 nfs4_fsinfo_bitmap[2] = {
FATTR4_WORD0_MAXFILESIZE
| FATTR4_WORD0_MAXREAD
| FATTR4_WORD0_MAXWRITE
| FATTR4_WORD0_LEASE_TIME,
0
};
u32 nfs4_pathconf_bitmap[2] = {
FATTR4_WORD0_MAXLINK
| FATTR4_WORD0_MAXNAME,
0
};
/* mount bitmap: fattr bitmap + lease time */
u32 nfs4_mount_bitmap[2] = {
FATTR4_WORD0_TYPE
| FATTR4_WORD0_CHANGE
| FATTR4_WORD0_SIZE
| FATTR4_WORD0_FSID
| FATTR4_WORD0_FILEID
| FATTR4_WORD0_LEASE_TIME,
FATTR4_WORD1_MODE
| FATTR4_WORD1_NUMLINKS
| FATTR4_WORD1_OWNER
| FATTR4_WORD1_OWNER_GROUP
| FATTR4_WORD1_RAWDEV
| FATTR4_WORD1_SPACE_USED
| FATTR4_WORD1_TIME_ACCESS
| FATTR4_WORD1_TIME_METADATA
| FATTR4_WORD1_TIME_MODIFY
};
static inline void
__nfs4_setup_getattr(struct nfs4_compound *cp, u32 *bitmap,
struct nfs_fattr *fattr,
struct nfs_fsstat *fsstat,
struct nfs_fsinfo *fsinfo,
struct nfs_pathconf *pathconf)
{
struct nfs4_getattr *getattr = GET_OP(cp, getattr);
......@@ -222,7 +197,6 @@ __nfs4_setup_getattr(struct nfs4_compound *cp, u32 *bitmap,
getattr->gt_bmval = bitmap;
getattr->gt_attrs = fattr;
getattr->gt_fsstat = fsstat;
getattr->gt_fsinfo = fsinfo;
getattr->gt_pathconf = pathconf;
OPNUM(cp) = OP_GETATTR;
......@@ -234,16 +208,7 @@ nfs4_setup_getattr(struct nfs4_compound *cp,
struct nfs_fattr *fattr)
{
__nfs4_setup_getattr(cp, nfs4_fattr_bitmap, fattr,
NULL, NULL, NULL);
}
static void
nfs4_setup_getrootattr(struct nfs4_compound *cp,
struct nfs_fattr *fattr,
struct nfs_fsinfo *fsinfo)
{
__nfs4_setup_getattr(cp, nfs4_mount_bitmap,
fattr, NULL, fsinfo, NULL);
NULL, NULL);
}
static void
......@@ -251,15 +216,7 @@ nfs4_setup_statfs(struct nfs4_compound *cp,
struct nfs_fsstat *fsstat)
{
__nfs4_setup_getattr(cp, nfs4_statfs_bitmap,
NULL, fsstat, NULL, NULL);
}
static void
nfs4_setup_fsinfo(struct nfs4_compound *cp,
struct nfs_fsinfo *fsinfo)
{
__nfs4_setup_getattr(cp, nfs4_fsinfo_bitmap,
NULL, NULL, fsinfo, NULL);
NULL, fsstat, NULL);
}
static void
......@@ -267,7 +224,7 @@ nfs4_setup_pathconf(struct nfs4_compound *cp,
struct nfs_pathconf *pathconf)
{
__nfs4_setup_getattr(cp, nfs4_pathconf_bitmap,
NULL, NULL, NULL, pathconf);
NULL, NULL, pathconf);
}
static void
......@@ -759,7 +716,7 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
fattr->valid = 0;
nfs4_setup_compound(&compound, ops, server, "getrootfh");
nfs4_setup_putrootfh(&compound);
nfs4_setup_getrootattr(&compound, fattr, &fsinfo);
nfs4_setup_getattr(&compound, fattr);
nfs4_setup_getfh(&compound, fhandle);
if ((status = nfs4_call_compound(&compound, NULL, 0)))
goto out_unlock;
......@@ -785,7 +742,7 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
nfs4_setup_compound(&compound, ops, server, "setclientid_confirm");
nfs4_setup_setclientid_confirm(&compound);
nfs4_setup_putrootfh(&compound);
nfs4_setup_getrootattr(&compound, fattr, &fsinfo);
nfs4_setup_getattr(&compound, fattr);
nfs4_setup_getfh(&compound, fhandle);
last_renewed = jiffies;
if ((status = nfs4_call_compound(&compound, NULL, 0)))
......@@ -797,6 +754,8 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* server.
* FIXME: we only need one renewd daemon per server.
*/
if ((status = nfs4_proc_fsinfo(server, fhandle, &fsinfo)))
goto out_unlock;
clp->cl_lease_time = fsinfo.lease_time * HZ;
clp->cl_last_renewal = last_renewed;
nfs4_schedule_state_renewal(clp);
......@@ -1434,14 +1393,14 @@ static int
nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *fsinfo)
{
struct nfs4_compound compound;
struct nfs4_op ops[2];
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
.rpc_argp = fhandle,
.rpc_resp = fsinfo,
};
memset(fsinfo, 0, sizeof(*fsinfo));
nfs4_setup_compound(&compound, ops, server, "statfs");
nfs4_setup_putfh(&compound, fhandle);
nfs4_setup_fsinfo(&compound, fsinfo);
return nfs4_call_compound(&compound, NULL, 0);
return rpc_call_sync(server->client, &msg, 0);
}
static int
......
......@@ -90,6 +90,8 @@ extern int nfs_stat_to_errno(int);
#define decode_pre_write_getattr_maxsz op_decode_hdr_maxsz + 5
#define encode_post_write_getattr_maxsz op_encode_hdr_maxsz + 2
#define decode_post_write_getattr_maxsz op_decode_hdr_maxsz + 13
#define encode_fsinfo_maxsz op_encode_hdr_maxsz + 2
#define decode_fsinfo_maxsz op_decode_hdr_maxsz + 11
#define encode_renew_maxsz op_encode_hdr_maxsz + 3
#define decode_renew_maxsz op_decode_hdr_maxsz
......@@ -161,6 +163,12 @@ extern int nfs_stat_to_errno(int);
#define NFS4_dec_setattr_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 3
#define NFS4_enc_fsinfo_sz compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_fsinfo_maxsz
#define NFS4_dec_fsinfo_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_fsinfo_maxsz
#define NFS4_enc_renew_sz compound_encode_hdr_maxsz + \
encode_renew_maxsz
#define NFS4_dec_renew_sz compound_decode_hdr_maxsz + \
......@@ -506,6 +514,15 @@ encode_post_write_getattr(struct xdr_stream *xdr)
FATTR4_WORD1_TIME_MODIFY);
}
static int
encode_fsinfo(struct xdr_stream *xdr)
{
return encode_getattr_one(xdr, FATTR4_WORD0_MAXFILESIZE
| FATTR4_WORD0_MAXREAD
| FATTR4_WORD0_MAXWRITE
| FATTR4_WORD0_LEASE_TIME);
}
static int
encode_getfh(struct xdr_stream *xdr)
{
......@@ -1134,6 +1151,26 @@ nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *arg
return status;
}
/*
* FSINFO request
*/
static int
nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, void *fhandle)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
};
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, fhandle);
if (!status)
status = encode_fsinfo(&xdr);
return status;
}
/*
* a RENEW request
*/
......@@ -1312,7 +1349,6 @@ decode_create(struct xdr_stream *xdr, struct nfs4_create *create)
}
extern uint32_t nfs4_fattr_bitmap[2];
extern uint32_t nfs4_fsinfo_bitmap[2];
extern uint32_t nfs4_fsstat_bitmap[2];
extern uint32_t nfs4_pathconf_bitmap[2];
......@@ -1322,7 +1358,6 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
{
struct nfs_fattr *nfp = getattr->gt_attrs;
struct nfs_fsstat *fsstat = getattr->gt_fsstat;
struct nfs_fsinfo *fsinfo = getattr->gt_fsinfo;
struct nfs_pathconf *pathconf = getattr->gt_pathconf;
uint32_t attrlen, dummy32, bmlen,
bmval0 = 0,
......@@ -1368,11 +1403,6 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
nfp->nlink = 1;
nfp->timestamp = jiffies;
}
if (fsinfo) {
fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */
fsinfo->lease_time = 60;
}
if (bmval0 & FATTR4_WORD0_TYPE) {
READ_BUF(4);
len += 4;
......@@ -1406,12 +1436,6 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
(long long)nfp->fsid_u.nfs4.major,
(long long)nfp->fsid_u.nfs4.minor);
}
if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
READ_BUF(4);
len += 4;
READ32(fsinfo->lease_time);
dprintk("read_attrs: lease_time=%d\n", fsinfo->lease_time);
}
if (bmval0 & FATTR4_WORD0_FILEID) {
READ_BUF(8);
len += 8;
......@@ -1436,12 +1460,6 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
READ64(fsstat->tfiles);
dprintk("read_attrs: files_tot=0x%Lx\n", (long long) fsstat->tfiles);
}
if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
READ_BUF(8);
len += 8;
READ64(fsinfo->maxfilesize);
dprintk("read_attrs: maxfilesize=0x%Lx\n", (long long) fsinfo->maxfilesize);
}
if (bmval0 & FATTR4_WORD0_MAXLINK) {
READ_BUF(4);
len += 4;
......@@ -1454,20 +1472,6 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
READ32(pathconf->max_namelen);
dprintk("read_attrs: maxname=%d\n", pathconf->max_namelen);
}
if (bmval0 & FATTR4_WORD0_MAXREAD) {
READ_BUF(8);
len += 8;
READ64(fsinfo->rtmax);
fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
dprintk("read_attrs: maxread=%d\n", fsinfo->rtmax);
}
if (bmval0 & FATTR4_WORD0_MAXWRITE) {
READ_BUF(8);
len += 8;
READ64(fsinfo->wtmax);
fsinfo->wtpref = fsinfo->wtmax;
dprintk("read_attrs: maxwrite=%d\n", fsinfo->wtmax);
}
if (bmval1 & FATTR4_WORD1_MODE) {
READ_BUF(4);
......@@ -1709,6 +1713,74 @@ decode_post_write_getattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
}
static int
decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
{
uint32_t *p;
uint32_t len, attrlen, bmlen, bmval0 = 0, bmval1 = 0;
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);
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;
}
static int
decode_getfh(struct xdr_stream *xdr, struct nfs4_getfh *getfh)
{
......@@ -2403,6 +2475,27 @@ nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *re
return status;
}
/*
* FSINFO request
*/
static int
nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsinfo *fsinfo)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
status = decode_putfh(&xdr);
if (!status)
status = decode_fsinfo(&xdr, fsinfo);
if (!status)
status = -nfs_stat_to_errno(hdr.status);
return status;
}
/*
* Decode RENEW response
*/
......@@ -2476,6 +2569,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm),
PROC(CLOSE, enc_close, dec_close),
PROC(SETATTR, enc_setattr, dec_setattr),
PROC(FSINFO, enc_fsinfo, dec_fsinfo),
PROC(RENEW, enc_renew, dec_renew),
};
......
......@@ -221,6 +221,7 @@ enum {
NFSPROC4_CLNT_OPEN_CONFIRM,
NFSPROC4_CLNT_CLOSE,
NFSPROC4_CLNT_SETATTR,
NFSPROC4_CLNT_FSINFO,
NFSPROC4_CLNT_RENEW,
};
......
......@@ -449,7 +449,6 @@ struct nfs4_getattr {
u32 * gt_bmval; /* request */
struct nfs_fattr * gt_attrs; /* response */
struct nfs_fsstat * gt_fsstat; /* response */
struct nfs_fsinfo * gt_fsinfo; /* response */
struct nfs_pathconf * gt_pathconf; /* response */
};
......
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