Example #1
0
/*
 * deliver request data to a CB.InitCallBackState call
 */
static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
{
	struct sockaddr_rxrpc srx;
	struct afs_server *server;
	int ret;

	_enter("");

	rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);

	ret = afs_extract_data(call, NULL, 0, false);
	if (ret < 0)
		return ret;

	/* no unmarshalling required */
	call->state = AFS_CALL_REPLYING;

	/* we'll need the file server record as that tells us which set of
	 * vnodes to operate upon */
	server = afs_find_server(&srx);
	if (!server)
		return -ENOTCONN;
	call->server = server;

	return afs_queue_call_work(call);
}
Example #2
0
File: rxrpc.c Project: krzk/linux
/*
 * Grab the operation ID from an incoming cache manager call.  The socket
 * buffer is discarded on error or if we don't yet have sufficient data.
 */
static int afs_deliver_cm_op_id(struct afs_call *call)
{
	int ret;

	_enter("{%zu}", call->offset);

	ASSERTCMP(call->offset, <, 4);

	/* the operation ID forms the first four bytes of the request data */
	ret = afs_extract_data(call, &call->tmp, 4, true);
	if (ret < 0)
		return ret;

	call->operation_ID = ntohl(call->tmp);
	afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
	call->offset = 0;

	/* ask the cache manager to route the call (it'll change the call type
	 * if successful) */
	if (!afs_cm_incoming_call(call))
		return -ENOTSUPP;

	trace_afs_cb_call(call);

	/* pass responsibility for the remainer of this message off to the
	 * cache manager op */
	return call->type->deliver(call);
}
Example #3
0
/*
 * deliver request data to a CB.ProbeUuid call
 */
static int afs_deliver_cb_probe_uuid(struct afs_call *call)
{
	struct uuid_v1 *r;
	unsigned loop;
	__be32 *b;
	int ret;

	_enter("{%u}", call->unmarshall);

	switch (call->unmarshall) {
	case 0:
		call->offset = 0;
		call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
		if (!call->buffer)
			return -ENOMEM;
		call->unmarshall++;

	case 1:
		_debug("extract UUID");
		ret = afs_extract_data(call, call->buffer,
				       11 * sizeof(__be32), false);
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		_debug("unmarshall UUID");
		call->request = kmalloc(sizeof(struct uuid_v1), GFP_KERNEL);
		if (!call->request)
			return -ENOMEM;

		b = call->buffer;
		r = call->request;
		r->time_low			= b[0];
		r->time_mid			= htons(ntohl(b[1]));
		r->time_hi_and_version		= htons(ntohl(b[2]));
		r->clock_seq_hi_and_reserved 	= ntohl(b[3]);
		r->clock_seq_low		= ntohl(b[4]);

		for (loop = 0; loop < 6; loop++)
			r->node[loop] = ntohl(b[loop + 5]);

		call->offset = 0;
		call->unmarshall++;

	case 2:
		break;
	}

	call->state = AFS_CALL_REPLYING;

	return afs_queue_call_work(call);
}
Example #4
0
/*
 * deliver request data to a CB.TellMeAboutYourself call
 */
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
{
	int ret;

	_enter("");

	ret = afs_extract_data(call, NULL, 0, false);
	if (ret < 0)
		return ret;

	/* no unmarshalling required */
	call->state = AFS_CALL_REPLYING;

	return afs_queue_call_work(call);
}
Example #5
0
/*
 * deliver request data to a CB.CallBack call
 */
static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
				   bool last)
{
	struct afs_callback *cb;
	struct afs_server *server;
	struct in_addr addr;
	__be32 *bp;
	u32 tmp;
	int ret, loop;

	_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);

	switch (call->unmarshall) {
	case 0:
		call->offset = 0;
		call->unmarshall++;

		/* extract the FID array and its count in two steps */
	case 1:
		_debug("extract FID count");
		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		call->count = ntohl(call->tmp);
		_debug("FID count: %u", call->count);
		if (call->count > AFSCBMAX)
			return -EBADMSG;

		call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
		if (!call->buffer)
			return -ENOMEM;
		call->offset = 0;
		call->unmarshall++;

	case 2:
		_debug("extract FID array");
		ret = afs_extract_data(call, skb, last, call->buffer,
				       call->count * 3 * 4);
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		_debug("unmarshall FID array");
		call->request = kcalloc(call->count,
					sizeof(struct afs_callback),
					GFP_KERNEL);
		if (!call->request)
			return -ENOMEM;

		cb = call->request;
		bp = call->buffer;
		for (loop = call->count; loop > 0; loop--, cb++) {
			cb->fid.vid	= ntohl(*bp++);
			cb->fid.vnode	= ntohl(*bp++);
			cb->fid.unique	= ntohl(*bp++);
			cb->type	= AFSCM_CB_UNTYPED;
		}

		call->offset = 0;
		call->unmarshall++;

		/* extract the callback array and its count in two steps */
	case 3:
		_debug("extract CB count");
		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		tmp = ntohl(call->tmp);
		_debug("CB count: %u", tmp);
		if (tmp != call->count && tmp != 0)
			return -EBADMSG;
		call->offset = 0;
		call->unmarshall++;
		if (tmp == 0)
			goto empty_cb_array;

	case 4:
		_debug("extract CB array");
		ret = afs_extract_data(call, skb, last, call->request,
				       call->count * 3 * 4);
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		_debug("unmarshall CB array");
		cb = call->request;
		bp = call->buffer;
		for (loop = call->count; loop > 0; loop--, cb++) {
			cb->version	= ntohl(*bp++);
			cb->expiry	= ntohl(*bp++);
			cb->type	= ntohl(*bp++);
		}

	empty_cb_array:
		call->offset = 0;
		call->unmarshall++;

	case 5:
		_debug("trailer");
		if (skb->len != 0)
			return -EBADMSG;
		break;
	}

	if (!last)
		return 0;

	call->state = AFS_CALL_REPLYING;

	/* we'll need the file server record as that tells us which set of
	 * vnodes to operate upon */
	memcpy(&addr, &ip_hdr(skb)->saddr, 4);
	server = afs_find_server(&addr);
	if (!server)
		return -ENOTCONN;
	call->server = server;

	INIT_WORK(&call->work, SRXAFSCB_CallBack);
	schedule_work(&call->work);
	return 0;
}
Example #6
0
/*
 * deliver request data to a CB.InitCallBackState3 call
 */
static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
{
	struct sockaddr_rxrpc srx;
	struct afs_server *server;
	struct uuid_v1 *r;
	unsigned loop;
	__be32 *b;
	int ret;

	_enter("");

	rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);

	_enter("{%u}", call->unmarshall);

	switch (call->unmarshall) {
	case 0:
		call->offset = 0;
		call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
		if (!call->buffer)
			return -ENOMEM;
		call->unmarshall++;

	case 1:
		_debug("extract UUID");
		ret = afs_extract_data(call, call->buffer,
				       11 * sizeof(__be32), false);
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		_debug("unmarshall UUID");
		call->request = kmalloc(sizeof(struct uuid_v1), GFP_KERNEL);
		if (!call->request)
			return -ENOMEM;

		b = call->buffer;
		r = call->request;
		r->time_low			= b[0];
		r->time_mid			= htons(ntohl(b[1]));
		r->time_hi_and_version		= htons(ntohl(b[2]));
		r->clock_seq_hi_and_reserved 	= ntohl(b[3]);
		r->clock_seq_low		= ntohl(b[4]);

		for (loop = 0; loop < 6; loop++)
			r->node[loop] = ntohl(b[loop + 5]);

		call->offset = 0;
		call->unmarshall++;

	case 2:
		break;
	}

	/* no unmarshalling required */
	call->state = AFS_CALL_REPLYING;

	/* we'll need the file server record as that tells us which set of
	 * vnodes to operate upon */
	server = afs_find_server(&srx);
	if (!server)
		return -ENOTCONN;
	call->server = server;

	return afs_queue_call_work(call);
}
Example #7
0
/*
 * deliver request data to a CB.CallBack call
 */
static int afs_deliver_cb_callback(struct afs_call *call)
{
	struct sockaddr_rxrpc srx;
	struct afs_callback *cb;
	struct afs_server *server;
	__be32 *bp;
	u32 tmp;
	int ret, loop;

	_enter("{%u}", call->unmarshall);

	switch (call->unmarshall) {
	case 0:
		rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
		call->offset = 0;
		call->unmarshall++;

		/* extract the FID array and its count in two steps */
	case 1:
		_debug("extract FID count");
		ret = afs_extract_data(call, &call->tmp, 4, true);
		if (ret < 0)
			return ret;

		call->count = ntohl(call->tmp);
		_debug("FID count: %u", call->count);
		if (call->count > AFSCBMAX)
			return -EBADMSG;

		call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
		if (!call->buffer)
			return -ENOMEM;
		call->offset = 0;
		call->unmarshall++;

	case 2:
		_debug("extract FID array");
		ret = afs_extract_data(call, call->buffer,
				       call->count * 3 * 4, true);
		if (ret < 0)
			return ret;

		_debug("unmarshall FID array");
		call->request = kcalloc(call->count,
					sizeof(struct afs_callback),
					GFP_KERNEL);
		if (!call->request)
			return -ENOMEM;

		cb = call->request;
		bp = call->buffer;
		for (loop = call->count; loop > 0; loop--, cb++) {
			cb->fid.vid	= ntohl(*bp++);
			cb->fid.vnode	= ntohl(*bp++);
			cb->fid.unique	= ntohl(*bp++);
			cb->type	= AFSCM_CB_UNTYPED;
		}

		call->offset = 0;
		call->unmarshall++;

		/* extract the callback array and its count in two steps */
	case 3:
		_debug("extract CB count");
		ret = afs_extract_data(call, &call->tmp, 4, true);
		if (ret < 0)
			return ret;

		tmp = ntohl(call->tmp);
		_debug("CB count: %u", tmp);
		if (tmp != call->count && tmp != 0)
			return -EBADMSG;
		call->offset = 0;
		call->unmarshall++;

	case 4:
		_debug("extract CB array");
		ret = afs_extract_data(call, call->buffer,
				       call->count * 3 * 4, false);
		if (ret < 0)
			return ret;

		_debug("unmarshall CB array");
		cb = call->request;
		bp = call->buffer;
		for (loop = call->count; loop > 0; loop--, cb++) {
			cb->version	= ntohl(*bp++);
			cb->expiry	= ntohl(*bp++);
			cb->type	= ntohl(*bp++);
		}

		call->offset = 0;
		call->unmarshall++;

		/* Record that the message was unmarshalled successfully so
		 * that the call destructor can know do the callback breaking
		 * work, even if the final ACK isn't received.
		 *
		 * If the step number changes, then afs_cm_destructor() must be
		 * updated also.
		 */
		call->unmarshall++;
	case 5:
		break;
	}

	call->state = AFS_CALL_REPLYING;

	/* we'll need the file server record as that tells us which set of
	 * vnodes to operate upon */
	server = afs_find_server(&srx);
	if (!server)
		return -ENOTCONN;
	call->server = server;

	return afs_queue_call_work(call);
}
Example #8
0
/*
 * deliver request data to a CB.ProbeUuid call
 */
static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
				     bool last)
{
	struct afs_uuid *r;
	unsigned loop;
	__be32 *b;
	int ret;

	_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);

	if (skb->len > 0)
		return -EBADMSG;
	if (!last)
		return 0;

	switch (call->unmarshall) {
	case 0:
		call->offset = 0;
		call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
		if (!call->buffer)
			return -ENOMEM;
		call->unmarshall++;

	case 1:
		_debug("extract UUID");
		ret = afs_extract_data(call, skb, last, call->buffer,
				       11 * sizeof(__be32));
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		_debug("unmarshall UUID");
		call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
		if (!call->request)
			return -ENOMEM;

		b = call->buffer;
		r = call->request;
		r->time_low			= ntohl(b[0]);
		r->time_mid			= ntohl(b[1]);
		r->time_hi_and_version		= ntohl(b[2]);
		r->clock_seq_hi_and_reserved 	= ntohl(b[3]);
		r->clock_seq_low		= ntohl(b[4]);

		for (loop = 0; loop < 6; loop++)
			r->node[loop] = ntohl(b[loop + 5]);

		call->offset = 0;
		call->unmarshall++;

	case 2:
		_debug("trailer");
		if (skb->len != 0)
			return -EBADMSG;
		break;
	}

	if (!last)
		return 0;

	call->state = AFS_CALL_REPLYING;

	INIT_WORK(&call->work, SRXAFSCB_ProbeUuid);
	queue_work(afs_wq, &call->work);
	return 0;
}