From: Trond Myklebust NFSv4: Convert SETCLIENTID and SETCLIENTID_CONFIRM to be standalone operations. Ensure that SETCLIENTID_CONFIRM always returns the lease timeout length. --- fs/nfs/nfs4proc.c | 127 +++++++++++++++++++++----------------------- fs/nfs/nfs4xdr.c | 136 ++++++++++++++++++++++++++++++++++++++++++------ include/linux/nfs4.h | 2 include/linux/nfs_fs.h | 2 include/linux/nfs_xdr.h | 2 5 files changed, 186 insertions(+), 83 deletions(-) diff -puN fs/nfs/nfs4proc.c~nfs-21-setclientid_xdr fs/nfs/nfs4proc.c --- 25/fs/nfs/nfs4proc.c~nfs-21-setclientid_xdr 2004-01-14 02:09:52.000000000 -0800 +++ 25-akpm/fs/nfs/nfs4proc.c 2004-01-14 02:09:52.000000000 -0800 @@ -56,9 +56,6 @@ extern struct rpc_procinfo nfs4_procedur 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) @@ -398,41 +395,6 @@ nfs4_setup_savefh(struct nfs4_compound * } static void -nfs4_setup_setclientid(struct nfs4_compound *cp, u32 program, unsigned short port) -{ - struct nfs4_setclientid *setclientid = GET_OP(cp, setclientid); - struct nfs_server *server = cp->server; - struct timespec tv; - u32 *p; - - tv = CURRENT_TIME; - p = (u32 *)setclientid->sc_verifier.data; - *p++ = tv.tv_sec; - *p++ = tv.tv_nsec; - setclientid->sc_name = server->ip_addr; - sprintf(setclientid->sc_netid, "udp"); - sprintf(setclientid->sc_uaddr, "%s.%d.%d", server->ip_addr, port >> 8, port & 255); - setclientid->sc_prog = program; - setclientid->sc_cb_ident = 0; - setclientid->sc_state = server->nfs4_state; - - OPNUM(cp) = OP_SETCLIENTID; - cp->req_nops++; -} - -static void -nfs4_setup_setclientid_confirm(struct nfs4_compound *cp) -{ - struct nfs4_client **client_state = GET_OP(cp, setclientid_confirm); - - *client_state = cp->server->nfs4_state; - - OPNUM(cp) = OP_SETCLIENTID_CONFIRM; - cp->req_nops++; - cp->renew_index = cp->req_nops; -} - -static void renew_lease(struct nfs_server *server, unsigned long timestamp) { struct nfs4_client *clp = server->nfs4_state; @@ -701,51 +663,31 @@ nfs4_proc_get_root(struct nfs_server *se struct nfs4_client *clp; struct nfs4_compound compound; struct nfs4_op ops[4]; - struct nfs_fsinfo fsinfo; unsigned char * p; struct qstr q; - unsigned long last_renewed; int status; clp = server->nfs4_state; down_write(&clp->cl_sem); /* Has the clientid already been initialized? */ - if (clp->cl_state != NFS4CLNT_NEW) { + if (clp->cl_state != NFS4CLNT_NEW) /* Yep, so just read the root attributes and the lease time. */ - fattr->valid = 0; - nfs4_setup_compound(&compound, ops, server, "getrootfh"); - nfs4_setup_putrootfh(&compound); - nfs4_setup_getattr(&compound, fattr); - nfs4_setup_getfh(&compound, fhandle); - if ((status = nfs4_call_compound(&compound, NULL, 0))) - goto out_unlock; goto no_setclientid; - } /* * SETCLIENTID. * Until delegations are imported, we don't bother setting the program * number and port to anything meaningful. */ - nfs4_setup_compound(&compound, ops, server, "setclientid"); - nfs4_setup_setclientid(&compound, 0, 0); - last_renewed = jiffies; - if ((status = nfs4_call_compound(&compound, NULL, 0))) + if ((status = nfs4_proc_setclientid(clp, 0, 0))) goto out_unlock; /* * SETCLIENTID_CONFIRM, plus root filehandle. * We also get the lease time here. */ - fattr->valid = 0; - nfs4_setup_compound(&compound, ops, server, "setclientid_confirm"); - nfs4_setup_setclientid_confirm(&compound); - nfs4_setup_putrootfh(&compound); - nfs4_setup_getattr(&compound, fattr); - nfs4_setup_getfh(&compound, fhandle); - last_renewed = jiffies; - if ((status = nfs4_call_compound(&compound, NULL, 0))) + if ((status = nfs4_proc_setclientid_confirm(clp))) goto out_unlock; /* @@ -754,10 +696,6 @@ nfs4_proc_get_root(struct nfs_server *se * 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); clp->cl_state = NFS4CLNT_OK; @@ -770,6 +708,13 @@ no_setclientid: * catch an ERR_WRONGSEC if it occurs along the way... */ p = server->mnt_path; + fattr->valid = 0; + nfs4_setup_compound(&compound, ops, server, "getrootfh"); + nfs4_setup_putrootfh(&compound); + nfs4_setup_getattr(&compound, fattr); + nfs4_setup_getfh(&compound, fhandle); + if ((status = nfs4_call_compound(&compound, NULL, 0))) + goto out; for (;;) { while (*p == '/') p++; @@ -798,6 +743,7 @@ no_setclientid: return status; out_unlock: up_write(&clp->cl_sem); +out: return status; } @@ -1724,6 +1670,57 @@ nfs4_request_compatible(struct nfs_page return 1; } +int +nfs4_proc_setclientid(struct nfs4_client *clp, + u32 program, unsigned short port) +{ + u32 *p; + struct nfs4_setclientid setclientid; + struct timespec tv; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], + .rpc_argp = &setclientid, + .rpc_resp = clp, + .rpc_cred = clp->cl_cred, + }; + + tv = CURRENT_TIME; + p = (u32*)setclientid.sc_verifier.data; + *p++ = (u32)tv.tv_sec; + *p = (u32)tv.tv_nsec; + setclientid.sc_name = clp->cl_ipaddr; + sprintf(setclientid.sc_netid, "tcp"); + sprintf(setclientid.sc_uaddr, "%s.%d.%d", clp->cl_ipaddr, port >> 8, port & 255); + setclientid.sc_prog = htonl(program); + setclientid.sc_cb_ident = 0; + + return rpc_call_sync(clp->cl_rpcclient, &msg, 0); +} + +int +nfs4_proc_setclientid_confirm(struct nfs4_client *clp) +{ + struct nfs_fsinfo fsinfo; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM], + .rpc_argp = clp, + .rpc_resp = &fsinfo, + .rpc_cred = clp->cl_cred, + }; + unsigned long now; + int status; + + now = jiffies; + status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); + if (status == 0) { + spin_lock(&clp->cl_lock); + clp->cl_lease_time = fsinfo.lease_time * HZ; + clp->cl_last_renewal = now; + spin_unlock(&clp->cl_lock); + } + return status; +} + struct nfs_rpc_ops nfs_v4_clientops = { .version = 4, /* protocol version */ .getroot = nfs4_proc_get_root, diff -puN fs/nfs/nfs4xdr.c~nfs-21-setclientid_xdr fs/nfs/nfs4xdr.c --- 25/fs/nfs/nfs4xdr.c~nfs-21-setclientid_xdr 2004-01-14 02:09:52.000000000 -0800 +++ 25-akpm/fs/nfs/nfs4xdr.c 2004-01-14 02:09:52.000000000 -0800 @@ -73,6 +73,8 @@ extern int nfs_stat_to_errno(int); #define encode_putfh_maxsz op_encode_hdr_maxsz + 1 + \ (NFS4_FHSIZE >> 2) #define decode_putfh_maxsz op_decode_hdr_maxsz +#define encode_putrootfh_maxsz op_encode_hdr_maxsz +#define decode_putrootfh_maxsz op_decode_hdr_maxsz #define encode_getfh_maxsz op_encode_hdr_maxsz #define decode_getfh_maxsz op_decode_hdr_maxsz + 1 + \ (NFS4_FHSIZE >> 2) @@ -94,6 +96,21 @@ extern int nfs_stat_to_errno(int); #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 +#define encode_setclientid_maxsz \ + op_encode_hdr_maxsz + \ + 4 /*server->ip_addr*/ + \ + 1 /*Netid*/ + \ + 6 /*uaddr*/ + \ + 6 + (NFS4_VERIFIER_SIZE >> 2) +#define decode_setclientid_maxsz \ + op_decode_hdr_maxsz + \ + 2 + \ + 1024 /* large value for CLID_INUSE */ +#define encode_setclientid_confirm_maxsz \ + op_encode_hdr_maxsz + \ + 3 + (NFS4_VERIFIER_SIZE >> 2) +#define decode_setclientid_confirm_maxsz \ + op_decode_hdr_maxsz #define NFS4_enc_compound_sz 1024 /* XXX: large enough? */ #define NFS4_dec_compound_sz 1024 /* XXX: large enough? */ @@ -173,6 +190,20 @@ extern int nfs_stat_to_errno(int); encode_renew_maxsz #define NFS4_dec_renew_sz compound_decode_hdr_maxsz + \ decode_renew_maxsz +#define NFS4_enc_setclientid_sz compound_encode_hdr_maxsz + \ + encode_setclientid_maxsz +#define NFS4_dec_setclientid_sz compound_decode_hdr_maxsz + \ + decode_setclientid_maxsz +#define NFS4_enc_setclientid_confirm_sz \ + compound_encode_hdr_maxsz + \ + encode_setclientid_confirm_maxsz + \ + encode_putrootfh_maxsz + \ + encode_fsinfo_maxsz +#define NFS4_dec_setclientid_confirm_sz \ + compound_decode_hdr_maxsz + \ + decode_setclientid_confirm_maxsz + \ + decode_putrootfh_maxsz + \ + decode_fsinfo_maxsz static struct { @@ -918,12 +949,6 @@ encode_compound(struct xdr_stream *xdr, case OP_SAVEFH: status = encode_savefh(xdr); break; - case OP_SETCLIENTID: - status = encode_setclientid(xdr, &cp->ops[i].u.setclientid); - break; - case OP_SETCLIENTID_CONFIRM: - status = encode_setclientid_confirm(xdr, cp->ops[i].u.setclientid_confirm); - break; default: BUG(); } @@ -1188,6 +1213,46 @@ nfs4_xdr_enc_renew(struct rpc_rqst *req, } /* + * a SETCLIENTID request + */ +static int +nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, + struct nfs4_setclientid *sc) +{ + struct xdr_stream xdr; + struct compound_hdr hdr = { + .nops = 1, + }; + + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + encode_compound_hdr(&xdr, &hdr); + return encode_setclientid(&xdr, sc); +} + +/* + * a SETCLIENTID_CONFIRM request + */ +static int +nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, + struct nfs4_client *clp) +{ + struct xdr_stream xdr; + struct compound_hdr hdr = { + .nops = 3, + }; + int status; + + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + encode_compound_hdr(&xdr, &hdr); + status = encode_setclientid_confirm(&xdr, clp); + if (!status) + status = encode_putrootfh(&xdr); + if (!status) + status = encode_fsinfo(&xdr); + return status; +} + +/* * START OF "GENERIC" DECODE ROUTINES. * These may look a little ugly since they are imported from a "generic" * set of XDR encode/decode routines which are intended to be shared by @@ -2098,7 +2163,7 @@ decode_setattr(struct xdr_stream *xdr, s } static int -decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid *setclientid) +decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp) { uint32_t *p; uint32_t opnum; @@ -2114,9 +2179,9 @@ decode_setclientid(struct xdr_stream *xd } READ32(nfserr); if (nfserr == NFS_OK) { - READ_BUF(8 + sizeof(setclientid->sc_state->cl_confirm.data)); - READ64(setclientid->sc_state->cl_clientid); - COPYMEM(setclientid->sc_state->cl_confirm.data, sizeof(setclientid->sc_state->cl_confirm.data)); + READ_BUF(8 + sizeof(clp->cl_confirm.data)); + READ64(clp->cl_clientid); + COPYMEM(clp->cl_confirm.data, sizeof(clp->cl_confirm.data)); } else if (nfserr == NFSERR_CLID_INUSE) { uint32_t len; @@ -2231,12 +2296,6 @@ decode_compound(struct xdr_stream *xdr, case OP_SAVEFH: status = decode_savefh(xdr); break; - case OP_SETCLIENTID: - status = decode_setclientid(xdr, &op->u.setclientid); - break; - case OP_SETCLIENTID_CONFIRM: - status = decode_setclientid_confirm(xdr); - break; default: BUG(); return -EIO; @@ -2513,6 +2572,49 @@ nfs4_xdr_dec_renew(struct rpc_rqst *rqst return status; } +/* + * a SETCLIENTID request + */ +static int +nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, + struct nfs4_client *clp) +{ + 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_setclientid(&xdr, clp); + if (!status) + status = -nfs_stat_to_errno(hdr.status); + return status; +} + +/* + * a SETCLIENTID_CONFIRM request + */ +static int +nfs4_xdr_dec_setclientid_confirm(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_setclientid_confirm(&xdr); + if (!status) + status = decode_putrootfh(&xdr); + if (!status) + status = decode_fsinfo(&xdr, fsinfo); + if (!status) + status = -nfs_stat_to_errno(hdr.status); + return status; +} + uint32_t * nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) { @@ -2571,6 +2673,8 @@ struct rpc_procinfo nfs4_procedures[] = PROC(SETATTR, enc_setattr, dec_setattr), PROC(FSINFO, enc_fsinfo, dec_fsinfo), PROC(RENEW, enc_renew, dec_renew), + PROC(SETCLIENTID, enc_setclientid, dec_setclientid), + PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), }; struct rpc_version nfs_version4 = { diff -puN include/linux/nfs4.h~nfs-21-setclientid_xdr include/linux/nfs4.h --- 25/include/linux/nfs4.h~nfs-21-setclientid_xdr 2004-01-14 02:09:52.000000000 -0800 +++ 25-akpm/include/linux/nfs4.h 2004-01-14 02:09:52.000000000 -0800 @@ -223,6 +223,8 @@ enum { NFSPROC4_CLNT_SETATTR, NFSPROC4_CLNT_FSINFO, NFSPROC4_CLNT_RENEW, + NFSPROC4_CLNT_SETCLIENTID, + NFSPROC4_CLNT_SETCLIENTID_CONFIRM, }; #endif diff -puN include/linux/nfs_fs.h~nfs-21-setclientid_xdr include/linux/nfs_fs.h --- 25/include/linux/nfs_fs.h~nfs-21-setclientid_xdr 2004-01-14 02:09:52.000000000 -0800 +++ 25-akpm/include/linux/nfs_fs.h 2004-01-14 02:09:52.000000000 -0800 @@ -552,6 +552,8 @@ struct nfs4_state { /* nfs4proc.c */ +extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short); +extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); extern int nfs4_proc_async_renew(struct nfs4_client *); extern int nfs4_do_close(struct inode *, struct nfs4_state *); diff -puN include/linux/nfs_xdr.h~nfs-21-setclientid_xdr include/linux/nfs_xdr.h --- 25/include/linux/nfs_xdr.h~nfs-21-setclientid_xdr 2004-01-14 02:09:52.000000000 -0800 +++ 25-akpm/include/linux/nfs_xdr.h 2004-01-14 02:09:52.000000000 -0800 @@ -555,8 +555,6 @@ struct nfs4_op { struct nfs4_rename rename; struct nfs4_client * renew; struct nfs4_setattr setattr; - struct nfs4_setclientid setclientid; - struct nfs4_client * setclientid_confirm; } u; }; _