Commit 88e4b0f2 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Convert SETCLIENTID and SETCLIENTID_CONFIRM to be

standalone operations. Ensure that SETCLIENTID_CONFIRM always
returns the lease timeout length.
parent f414757e
...@@ -56,9 +56,6 @@ extern struct rpc_procinfo nfs4_procedures[]; ...@@ -56,9 +56,6 @@ extern struct rpc_procinfo nfs4_procedures[];
extern nfs4_stateid zero_stateid; extern nfs4_stateid zero_stateid;
static int nfs4_proc_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static void static void
nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops, nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops,
struct nfs_server *server, char *tag) struct nfs_server *server, char *tag)
...@@ -397,41 +394,6 @@ nfs4_setup_savefh(struct nfs4_compound *cp) ...@@ -397,41 +394,6 @@ nfs4_setup_savefh(struct nfs4_compound *cp)
cp->req_nops++; cp->req_nops++;
} }
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 static void
renew_lease(struct nfs_server *server, unsigned long timestamp) renew_lease(struct nfs_server *server, unsigned long timestamp)
{ {
...@@ -701,51 +663,31 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -701,51 +663,31 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs4_client *clp; struct nfs4_client *clp;
struct nfs4_compound compound; struct nfs4_compound compound;
struct nfs4_op ops[4]; struct nfs4_op ops[4];
struct nfs_fsinfo fsinfo;
unsigned char * p; unsigned char * p;
struct qstr q; struct qstr q;
unsigned long last_renewed;
int status; int status;
clp = server->nfs4_state; clp = server->nfs4_state;
down_write(&clp->cl_sem); down_write(&clp->cl_sem);
/* Has the clientid already been initialized? */ /* 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. */ /* 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; goto no_setclientid;
}
/* /*
* SETCLIENTID. * SETCLIENTID.
* Until delegations are imported, we don't bother setting the program * Until delegations are imported, we don't bother setting the program
* number and port to anything meaningful. * number and port to anything meaningful.
*/ */
nfs4_setup_compound(&compound, ops, server, "setclientid"); if ((status = nfs4_proc_setclientid(clp, 0, 0)))
nfs4_setup_setclientid(&compound, 0, 0);
last_renewed = jiffies;
if ((status = nfs4_call_compound(&compound, NULL, 0)))
goto out_unlock; goto out_unlock;
/* /*
* SETCLIENTID_CONFIRM, plus root filehandle. * SETCLIENTID_CONFIRM, plus root filehandle.
* We also get the lease time here. * We also get the lease time here.
*/ */
fattr->valid = 0; if ((status = nfs4_proc_setclientid_confirm(clp)))
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)))
goto out_unlock; goto out_unlock;
/* /*
...@@ -754,10 +696,6 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -754,10 +696,6 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* server. * server.
* FIXME: we only need one renewd daemon per 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); nfs4_schedule_state_renewal(clp);
clp->cl_state = NFS4CLNT_OK; clp->cl_state = NFS4CLNT_OK;
...@@ -770,6 +708,13 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -770,6 +708,13 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* catch an ERR_WRONGSEC if it occurs along the way... * catch an ERR_WRONGSEC if it occurs along the way...
*/ */
p = server->mnt_path; 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 (;;) { for (;;) {
while (*p == '/') while (*p == '/')
p++; p++;
...@@ -798,6 +743,7 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -798,6 +743,7 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
return status; return status;
out_unlock: out_unlock:
up_write(&clp->cl_sem); up_write(&clp->cl_sem);
out:
return status; return status;
} }
...@@ -1724,6 +1670,57 @@ nfs4_request_compatible(struct nfs_page *req, struct file *filp, struct page *pa ...@@ -1724,6 +1670,57 @@ nfs4_request_compatible(struct nfs_page *req, struct file *filp, struct page *pa
return 1; 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 = { struct nfs_rpc_ops nfs_v4_clientops = {
.version = 4, /* protocol version */ .version = 4, /* protocol version */
.getroot = nfs4_proc_get_root, .getroot = nfs4_proc_get_root,
......
...@@ -73,6 +73,8 @@ extern int nfs_stat_to_errno(int); ...@@ -73,6 +73,8 @@ extern int nfs_stat_to_errno(int);
#define encode_putfh_maxsz op_encode_hdr_maxsz + 1 + \ #define encode_putfh_maxsz op_encode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2) (NFS4_FHSIZE >> 2)
#define decode_putfh_maxsz op_decode_hdr_maxsz #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 encode_getfh_maxsz op_encode_hdr_maxsz
#define decode_getfh_maxsz op_decode_hdr_maxsz + 1 + \ #define decode_getfh_maxsz op_decode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2) (NFS4_FHSIZE >> 2)
...@@ -94,6 +96,21 @@ extern int nfs_stat_to_errno(int); ...@@ -94,6 +96,21 @@ extern int nfs_stat_to_errno(int);
#define decode_fsinfo_maxsz op_decode_hdr_maxsz + 11 #define decode_fsinfo_maxsz op_decode_hdr_maxsz + 11
#define encode_renew_maxsz op_encode_hdr_maxsz + 3 #define encode_renew_maxsz op_encode_hdr_maxsz + 3
#define decode_renew_maxsz op_decode_hdr_maxsz #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_enc_compound_sz 1024 /* XXX: large enough? */
#define NFS4_dec_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); ...@@ -173,6 +190,20 @@ extern int nfs_stat_to_errno(int);
encode_renew_maxsz encode_renew_maxsz
#define NFS4_dec_renew_sz compound_decode_hdr_maxsz + \ #define NFS4_dec_renew_sz compound_decode_hdr_maxsz + \
decode_renew_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 { static struct {
...@@ -918,12 +949,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -918,12 +949,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_SAVEFH: case OP_SAVEFH:
status = encode_savefh(xdr); status = encode_savefh(xdr);
break; 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: default:
BUG(); BUG();
} }
...@@ -1187,6 +1212,46 @@ nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp) ...@@ -1187,6 +1212,46 @@ nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp)
return encode_renew(&xdr, clp); return encode_renew(&xdr, clp);
} }
/*
* 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. * START OF "GENERIC" DECODE ROUTINES.
* These may look a little ugly since they are imported from a "generic" * These may look a little ugly since they are imported from a "generic"
...@@ -2098,7 +2163,7 @@ decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) ...@@ -2098,7 +2163,7 @@ decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res)
} }
static int 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 *p;
uint32_t opnum; uint32_t opnum;
...@@ -2114,9 +2179,9 @@ decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid *setclientid) ...@@ -2114,9 +2179,9 @@ decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid *setclientid)
} }
READ32(nfserr); READ32(nfserr);
if (nfserr == NFS_OK) { if (nfserr == NFS_OK) {
READ_BUF(8 + sizeof(setclientid->sc_state->cl_confirm.data)); READ_BUF(8 + sizeof(clp->cl_confirm.data));
READ64(setclientid->sc_state->cl_clientid); READ64(clp->cl_clientid);
COPYMEM(setclientid->sc_state->cl_confirm.data, sizeof(setclientid->sc_state->cl_confirm.data)); COPYMEM(clp->cl_confirm.data, sizeof(clp->cl_confirm.data));
} else if (nfserr == NFSERR_CLID_INUSE) { } else if (nfserr == NFSERR_CLID_INUSE) {
uint32_t len; uint32_t len;
...@@ -2231,12 +2296,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -2231,12 +2296,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_SAVEFH: case OP_SAVEFH:
status = decode_savefh(xdr); status = decode_savefh(xdr);
break; break;
case OP_SETCLIENTID:
status = decode_setclientid(xdr, &op->u.setclientid);
break;
case OP_SETCLIENTID_CONFIRM:
status = decode_setclientid_confirm(xdr);
break;
default: default:
BUG(); BUG();
return -EIO; return -EIO;
...@@ -2513,6 +2572,49 @@ nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) ...@@ -2513,6 +2572,49 @@ nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
return status; 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 * uint32_t *
nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
{ {
...@@ -2571,6 +2673,8 @@ struct rpc_procinfo nfs4_procedures[] = { ...@@ -2571,6 +2673,8 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(SETATTR, enc_setattr, dec_setattr), PROC(SETATTR, enc_setattr, dec_setattr),
PROC(FSINFO, enc_fsinfo, dec_fsinfo), PROC(FSINFO, enc_fsinfo, dec_fsinfo),
PROC(RENEW, enc_renew, dec_renew), 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 = { struct rpc_version nfs_version4 = {
......
...@@ -223,6 +223,8 @@ enum { ...@@ -223,6 +223,8 @@ enum {
NFSPROC4_CLNT_SETATTR, NFSPROC4_CLNT_SETATTR,
NFSPROC4_CLNT_FSINFO, NFSPROC4_CLNT_FSINFO,
NFSPROC4_CLNT_RENEW, NFSPROC4_CLNT_RENEW,
NFSPROC4_CLNT_SETCLIENTID,
NFSPROC4_CLNT_SETCLIENTID_CONFIRM,
}; };
#endif #endif
......
...@@ -552,6 +552,8 @@ struct nfs4_state { ...@@ -552,6 +552,8 @@ struct nfs4_state {
/* nfs4proc.c */ /* 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_proc_async_renew(struct nfs4_client *);
extern int nfs4_do_close(struct inode *, struct nfs4_state *); extern int nfs4_do_close(struct inode *, struct nfs4_state *);
......
...@@ -555,8 +555,6 @@ struct nfs4_op { ...@@ -555,8 +555,6 @@ struct nfs4_op {
struct nfs4_rename rename; struct nfs4_rename rename;
struct nfs4_client * renew; struct nfs4_client * renew;
struct nfs4_setattr setattr; struct nfs4_setattr setattr;
struct nfs4_setclientid setclientid;
struct nfs4_client * setclientid_confirm;
} u; } u;
}; };
......
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