nfs41: cb_sequence xdr implementation
[nfs41: get rid of READMEM and COPYMEM for callback_xdr.c] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: get rid of READ64 in callback_xdr.c] See http://linux-nfs.org/pipermail/pnfs/2009-June/007846.html Signed-off-by: Benny Halevy <bhalevy@panasas.com>
This commit is contained in:
parent
d49433e1e3
commit
4aece6a19c
|
@ -20,6 +20,11 @@
|
||||||
2 + 2 + 3 + 3)
|
2 + 2 + 3 + 3)
|
||||||
#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
|
#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
|
||||||
|
|
||||||
|
#if defined(CONFIG_NFS_V4_1)
|
||||||
|
#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
|
||||||
|
4 + 1 + 3)
|
||||||
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
#define NFSDBG_FACILITY NFSDBG_CALLBACK
|
#define NFSDBG_FACILITY NFSDBG_CALLBACK
|
||||||
|
|
||||||
typedef __be32 (*callback_process_op_t)(void *, void *);
|
typedef __be32 (*callback_process_op_t)(void *, void *);
|
||||||
|
@ -207,6 +212,122 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NFS_V4_1)
|
||||||
|
|
||||||
|
static unsigned decode_sessionid(struct xdr_stream *xdr,
|
||||||
|
struct nfs4_sessionid *sid)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
int len = NFS4_MAX_SESSIONID_LEN;
|
||||||
|
|
||||||
|
p = read_buf(xdr, len);
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
return htonl(NFS4ERR_RESOURCE);;
|
||||||
|
|
||||||
|
memcpy(sid->data, p, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned decode_rc_list(struct xdr_stream *xdr,
|
||||||
|
struct referring_call_list *rc_list)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
int i;
|
||||||
|
unsigned status;
|
||||||
|
|
||||||
|
status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
status = htonl(NFS4ERR_RESOURCE);
|
||||||
|
p = read_buf(xdr, sizeof(uint32_t));
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rc_list->rcl_nrefcalls = ntohl(*p++);
|
||||||
|
if (rc_list->rcl_nrefcalls) {
|
||||||
|
p = read_buf(xdr,
|
||||||
|
rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
goto out;
|
||||||
|
rc_list->rcl_refcalls = kmalloc(rc_list->rcl_nrefcalls *
|
||||||
|
sizeof(*rc_list->rcl_refcalls),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (unlikely(rc_list->rcl_refcalls == NULL))
|
||||||
|
goto out;
|
||||||
|
for (i = 0; i < rc_list->rcl_nrefcalls; i++) {
|
||||||
|
rc_list->rcl_refcalls[i].rc_sequenceid = ntohl(*p++);
|
||||||
|
rc_list->rcl_refcalls[i].rc_slotid = ntohl(*p++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp,
|
||||||
|
struct xdr_stream *xdr,
|
||||||
|
struct cb_sequenceargs *args)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
int i;
|
||||||
|
unsigned status;
|
||||||
|
|
||||||
|
status = decode_sessionid(xdr, &args->csa_sessionid);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
status = htonl(NFS4ERR_RESOURCE);
|
||||||
|
p = read_buf(xdr, 5 * sizeof(uint32_t));
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
args->csa_addr = svc_addr_in(rqstp);
|
||||||
|
args->csa_sequenceid = ntohl(*p++);
|
||||||
|
args->csa_slotid = ntohl(*p++);
|
||||||
|
args->csa_highestslotid = ntohl(*p++);
|
||||||
|
args->csa_cachethis = ntohl(*p++);
|
||||||
|
args->csa_nrclists = ntohl(*p++);
|
||||||
|
args->csa_rclists = NULL;
|
||||||
|
if (args->csa_nrclists) {
|
||||||
|
args->csa_rclists = kmalloc(args->csa_nrclists *
|
||||||
|
sizeof(*args->csa_rclists),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (unlikely(args->csa_rclists == NULL))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for (i = 0; i < args->csa_nrclists; i++) {
|
||||||
|
status = decode_rc_list(xdr, &args->csa_rclists[i]);
|
||||||
|
if (status)
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = 0;
|
||||||
|
|
||||||
|
dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
|
||||||
|
"highestslotid %u cachethis %d nrclists %u\n",
|
||||||
|
__func__,
|
||||||
|
((u32 *)&args->csa_sessionid)[0],
|
||||||
|
((u32 *)&args->csa_sessionid)[1],
|
||||||
|
((u32 *)&args->csa_sessionid)[2],
|
||||||
|
((u32 *)&args->csa_sessionid)[3],
|
||||||
|
args->csa_sequenceid, args->csa_slotid,
|
||||||
|
args->csa_highestslotid, args->csa_cachethis,
|
||||||
|
args->csa_nrclists);
|
||||||
|
out:
|
||||||
|
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
|
||||||
|
return status;
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
for (i = 0; i < args->csa_nrclists; i++)
|
||||||
|
kfree(args->csa_rclists[i].rcl_refcalls);
|
||||||
|
kfree(args->csa_rclists);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
|
static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
|
||||||
{
|
{
|
||||||
__be32 *p;
|
__be32 *p;
|
||||||
|
@ -358,12 +479,52 @@ out:
|
||||||
|
|
||||||
#if defined(CONFIG_NFS_V4_1)
|
#if defined(CONFIG_NFS_V4_1)
|
||||||
|
|
||||||
|
static unsigned encode_sessionid(struct xdr_stream *xdr,
|
||||||
|
const struct nfs4_sessionid *sid)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
int len = NFS4_MAX_SESSIONID_LEN;
|
||||||
|
|
||||||
|
p = xdr_reserve_space(xdr, len);
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
return htonl(NFS4ERR_RESOURCE);
|
||||||
|
|
||||||
|
memcpy(p, sid, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned encode_cb_sequence_res(struct svc_rqst *rqstp,
|
||||||
|
struct xdr_stream *xdr,
|
||||||
|
const struct cb_sequenceres *res)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
unsigned status = res->csr_status;
|
||||||
|
|
||||||
|
if (unlikely(status != 0))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
encode_sessionid(xdr, &res->csr_sessionid);
|
||||||
|
|
||||||
|
p = xdr_reserve_space(xdr, 4 * sizeof(uint32_t));
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
return htonl(NFS4ERR_RESOURCE);
|
||||||
|
|
||||||
|
*p++ = htonl(res->csr_sequenceid);
|
||||||
|
*p++ = htonl(res->csr_slotid);
|
||||||
|
*p++ = htonl(res->csr_highestslotid);
|
||||||
|
*p++ = htonl(res->csr_target_highestslotid);
|
||||||
|
out:
|
||||||
|
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
|
preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
|
||||||
{
|
{
|
||||||
switch (op_nr) {
|
switch (op_nr) {
|
||||||
case OP_CB_GETATTR:
|
case OP_CB_GETATTR:
|
||||||
case OP_CB_RECALL:
|
case OP_CB_RECALL:
|
||||||
|
case OP_CB_SEQUENCE:
|
||||||
*op = &callback_ops[op_nr];
|
*op = &callback_ops[op_nr];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -374,7 +535,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
|
||||||
case OP_CB_RECALL_ANY:
|
case OP_CB_RECALL_ANY:
|
||||||
case OP_CB_RECALLABLE_OBJ_AVAIL:
|
case OP_CB_RECALLABLE_OBJ_AVAIL:
|
||||||
case OP_CB_RECALL_SLOT:
|
case OP_CB_RECALL_SLOT:
|
||||||
case OP_CB_SEQUENCE:
|
|
||||||
case OP_CB_WANTS_CANCELLED:
|
case OP_CB_WANTS_CANCELLED:
|
||||||
case OP_CB_NOTIFY_LOCK:
|
case OP_CB_NOTIFY_LOCK:
|
||||||
return htonl(NFS4ERR_NOTSUPP);
|
return htonl(NFS4ERR_NOTSUPP);
|
||||||
|
@ -512,7 +672,15 @@ static struct callback_op callback_ops[] = {
|
||||||
.process_op = (callback_process_op_t)nfs4_callback_recall,
|
.process_op = (callback_process_op_t)nfs4_callback_recall,
|
||||||
.decode_args = (callback_decode_arg_t)decode_recall_args,
|
.decode_args = (callback_decode_arg_t)decode_recall_args,
|
||||||
.res_maxsize = CB_OP_RECALL_RES_MAXSZ,
|
.res_maxsize = CB_OP_RECALL_RES_MAXSZ,
|
||||||
}
|
},
|
||||||
|
#if defined(CONFIG_NFS_V4_1)
|
||||||
|
[OP_CB_SEQUENCE] = {
|
||||||
|
.process_op = (callback_process_op_t)nfs4_callback_sequence,
|
||||||
|
.decode_args = (callback_decode_arg_t)decode_cb_sequence_args,
|
||||||
|
.encode_res = (callback_encode_res_t)encode_cb_sequence_res,
|
||||||
|
.res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ,
|
||||||
|
},
|
||||||
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue