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)
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
renew_lease(struct nfs_server *server, unsigned long timestamp)
{
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;
/*
* 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;
* 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++;
return status;
out_unlock:
up_write(&clp->cl_sem);
+out:
return status;
}
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,
#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)
#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? */
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 {
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();
}
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.
* These may look a little ugly since they are imported from a "generic"
}
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;
}
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;
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;
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)
{
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 = {
NFSPROC4_CLNT_SETATTR,
NFSPROC4_CLNT_FSINFO,
NFSPROC4_CLNT_RENEW,
+ NFSPROC4_CLNT_SETCLIENTID,
+ NFSPROC4_CLNT_SETCLIENTID_CONFIRM,
};
#endif
/* 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 *);
struct nfs4_rename rename;
struct nfs4_client * renew;
struct nfs4_setattr setattr;
- struct nfs4_setclientid setclientid;
- struct nfs4_client * setclientid_confirm;
} u;
};