forked from mirrors/linux
		
	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
					
				
					 1 changed files with 170 additions and 2 deletions
				
			
		| 
						 | 
					@ -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 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 | 
				
			||||||
	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 @@ static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#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 a new issue