xref: /openbmc/linux/fs/afs/fsclient.c (revision 1da177e4)
11da177e4SLinus Torvalds /* fsclient.c: AFS File Server client stubs
21da177e4SLinus Torvalds  *
31da177e4SLinus Torvalds  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
41da177e4SLinus Torvalds  * Written by David Howells (dhowells@redhat.com)
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or
71da177e4SLinus Torvalds  * modify it under the terms of the GNU General Public License
81da177e4SLinus Torvalds  * as published by the Free Software Foundation; either version
91da177e4SLinus Torvalds  * 2 of the License, or (at your option) any later version.
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <linux/init.h>
131da177e4SLinus Torvalds #include <linux/sched.h>
141da177e4SLinus Torvalds #include <rxrpc/rxrpc.h>
151da177e4SLinus Torvalds #include <rxrpc/transport.h>
161da177e4SLinus Torvalds #include <rxrpc/connection.h>
171da177e4SLinus Torvalds #include <rxrpc/call.h>
181da177e4SLinus Torvalds #include "fsclient.h"
191da177e4SLinus Torvalds #include "cmservice.h"
201da177e4SLinus Torvalds #include "vnode.h"
211da177e4SLinus Torvalds #include "server.h"
221da177e4SLinus Torvalds #include "errors.h"
231da177e4SLinus Torvalds #include "internal.h"
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #define FSFETCHSTATUS		132	/* AFS Fetch file status */
261da177e4SLinus Torvalds #define FSFETCHDATA		130	/* AFS Fetch file data */
271da177e4SLinus Torvalds #define FSGIVEUPCALLBACKS	147	/* AFS Discard callback promises */
281da177e4SLinus Torvalds #define FSGETVOLUMEINFO		148	/* AFS Get root volume information */
291da177e4SLinus Torvalds #define FSGETROOTVOLUME		151	/* AFS Get root volume name */
301da177e4SLinus Torvalds #define FSLOOKUP		161	/* AFS lookup file in directory */
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds /*****************************************************************************/
331da177e4SLinus Torvalds /*
341da177e4SLinus Torvalds  * map afs abort codes to/from Linux error codes
351da177e4SLinus Torvalds  * - called with call->lock held
361da177e4SLinus Torvalds  */
371da177e4SLinus Torvalds static void afs_rxfs_aemap(struct rxrpc_call *call)
381da177e4SLinus Torvalds {
391da177e4SLinus Torvalds 	switch (call->app_err_state) {
401da177e4SLinus Torvalds 	case RXRPC_ESTATE_LOCAL_ABORT:
411da177e4SLinus Torvalds 		call->app_abort_code = -call->app_errno;
421da177e4SLinus Torvalds 		break;
431da177e4SLinus Torvalds 	case RXRPC_ESTATE_PEER_ABORT:
441da177e4SLinus Torvalds 		call->app_errno = afs_abort_to_error(call->app_abort_code);
451da177e4SLinus Torvalds 		break;
461da177e4SLinus Torvalds 	default:
471da177e4SLinus Torvalds 		break;
481da177e4SLinus Torvalds 	}
491da177e4SLinus Torvalds } /* end afs_rxfs_aemap() */
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds /*****************************************************************************/
521da177e4SLinus Torvalds /*
531da177e4SLinus Torvalds  * get the root volume name from a fileserver
541da177e4SLinus Torvalds  * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
551da177e4SLinus Torvalds  */
561da177e4SLinus Torvalds #if 0
571da177e4SLinus Torvalds int afs_rxfs_get_root_volume(struct afs_server *server,
581da177e4SLinus Torvalds 			     char *buf, size_t *buflen)
591da177e4SLinus Torvalds {
601da177e4SLinus Torvalds 	struct rxrpc_connection *conn;
611da177e4SLinus Torvalds 	struct rxrpc_call *call;
621da177e4SLinus Torvalds 	struct kvec piov[2];
631da177e4SLinus Torvalds 	size_t sent;
641da177e4SLinus Torvalds 	int ret;
651da177e4SLinus Torvalds 	u32 param[1];
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(myself, current);
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds 	kenter("%p,%p,%u",server, buf, *buflen);
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds 	/* get hold of the fileserver connection */
721da177e4SLinus Torvalds 	ret = afs_server_get_fsconn(server, &conn);
731da177e4SLinus Torvalds 	if (ret < 0)
741da177e4SLinus Torvalds 		goto out;
751da177e4SLinus Torvalds 
761da177e4SLinus Torvalds 	/* create a call through that connection */
771da177e4SLinus Torvalds 	ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
781da177e4SLinus Torvalds 	if (ret < 0) {
791da177e4SLinus Torvalds 		printk("kAFS: Unable to create call: %d\n", ret);
801da177e4SLinus Torvalds 		goto out_put_conn;
811da177e4SLinus Torvalds 	}
821da177e4SLinus Torvalds 	call->app_opcode = FSGETROOTVOLUME;
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds 	/* we want to get event notifications from the call */
851da177e4SLinus Torvalds 	add_wait_queue(&call->waitq, &myself);
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds 	/* marshall the parameters */
881da177e4SLinus Torvalds 	param[0] = htonl(FSGETROOTVOLUME);
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds 	piov[0].iov_len = sizeof(param);
911da177e4SLinus Torvalds 	piov[0].iov_base = param;
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds 	/* send the parameters to the server */
941da177e4SLinus Torvalds 	ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
951da177e4SLinus Torvalds 				    0, &sent);
961da177e4SLinus Torvalds 	if (ret < 0)
971da177e4SLinus Torvalds 		goto abort;
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	/* wait for the reply to completely arrive */
1001da177e4SLinus Torvalds 	for (;;) {
1011da177e4SLinus Torvalds 		set_current_state(TASK_INTERRUPTIBLE);
1021da177e4SLinus Torvalds 		if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
1031da177e4SLinus Torvalds 		    signal_pending(current))
1041da177e4SLinus Torvalds 			break;
1051da177e4SLinus Torvalds 		schedule();
1061da177e4SLinus Torvalds 	}
1071da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	ret = -EINTR;
1101da177e4SLinus Torvalds 	if (signal_pending(current))
1111da177e4SLinus Torvalds 		goto abort;
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	switch (call->app_call_state) {
1141da177e4SLinus Torvalds 	case RXRPC_CSTATE_ERROR:
1151da177e4SLinus Torvalds 		ret = call->app_errno;
1161da177e4SLinus Torvalds 		kdebug("Got Error: %d", ret);
1171da177e4SLinus Torvalds 		goto out_unwait;
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds 	case RXRPC_CSTATE_CLNT_GOT_REPLY:
1201da177e4SLinus Torvalds 		/* read the reply */
1211da177e4SLinus Torvalds 		kdebug("Got Reply: qty=%d", call->app_ready_qty);
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds 		ret = -EBADMSG;
1241da177e4SLinus Torvalds 		if (call->app_ready_qty <= 4)
1251da177e4SLinus Torvalds 			goto abort;
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 		ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0);
1281da177e4SLinus Torvalds 		if (ret < 0)
1291da177e4SLinus Torvalds 			goto abort;
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds #if 0
1321da177e4SLinus Torvalds 		/* unmarshall the reply */
1331da177e4SLinus Torvalds 		bp = buffer;
1341da177e4SLinus Torvalds 		for (loop = 0; loop < 65; loop++)
1351da177e4SLinus Torvalds 			entry->name[loop] = ntohl(*bp++);
1361da177e4SLinus Torvalds 		entry->name[64] = 0;
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds 		entry->type = ntohl(*bp++);
1391da177e4SLinus Torvalds 		entry->num_servers = ntohl(*bp++);
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds 		for (loop = 0; loop < 8; loop++)
1421da177e4SLinus Torvalds 			entry->servers[loop].addr.s_addr = *bp++;
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds 		for (loop = 0; loop < 8; loop++)
1451da177e4SLinus Torvalds 			entry->servers[loop].partition = ntohl(*bp++);
1461da177e4SLinus Torvalds 
1471da177e4SLinus Torvalds 		for (loop = 0; loop < 8; loop++)
1481da177e4SLinus Torvalds 			entry->servers[loop].flags = ntohl(*bp++);
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds 		for (loop = 0; loop < 3; loop++)
1511da177e4SLinus Torvalds 			entry->volume_ids[loop] = ntohl(*bp++);
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds 		entry->clone_id = ntohl(*bp++);
1541da177e4SLinus Torvalds 		entry->flags = ntohl(*bp);
1551da177e4SLinus Torvalds #endif
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds 		/* success */
1581da177e4SLinus Torvalds 		ret = 0;
1591da177e4SLinus Torvalds 		goto out_unwait;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds 	default:
1621da177e4SLinus Torvalds 		BUG();
1631da177e4SLinus Torvalds 	}
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds  abort:
1661da177e4SLinus Torvalds 	set_current_state(TASK_UNINTERRUPTIBLE);
1671da177e4SLinus Torvalds 	rxrpc_call_abort(call, ret);
1681da177e4SLinus Torvalds 	schedule();
1691da177e4SLinus Torvalds  out_unwait:
1701da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
1711da177e4SLinus Torvalds 	remove_wait_queue(&call->waitq, &myself);
1721da177e4SLinus Torvalds 	rxrpc_put_call(call);
1731da177e4SLinus Torvalds  out_put_conn:
1741da177e4SLinus Torvalds 	afs_server_release_fsconn(server, conn);
1751da177e4SLinus Torvalds  out:
1761da177e4SLinus Torvalds 	kleave("");
1771da177e4SLinus Torvalds 	return ret;
1781da177e4SLinus Torvalds } /* end afs_rxfs_get_root_volume() */
1791da177e4SLinus Torvalds #endif
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds /*****************************************************************************/
1821da177e4SLinus Torvalds /*
1831da177e4SLinus Torvalds  * get information about a volume
1841da177e4SLinus Torvalds  */
1851da177e4SLinus Torvalds #if 0
1861da177e4SLinus Torvalds int afs_rxfs_get_volume_info(struct afs_server *server,
1871da177e4SLinus Torvalds 			     const char *name,
1881da177e4SLinus Torvalds 			     struct afs_volume_info *vinfo)
1891da177e4SLinus Torvalds {
1901da177e4SLinus Torvalds 	struct rxrpc_connection *conn;
1911da177e4SLinus Torvalds 	struct rxrpc_call *call;
1921da177e4SLinus Torvalds 	struct kvec piov[3];
1931da177e4SLinus Torvalds 	size_t sent;
1941da177e4SLinus Torvalds 	int ret;
1951da177e4SLinus Torvalds 	u32 param[2], *bp, zero;
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(myself, current);
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds 	_enter("%p,%s,%p", server, name, vinfo);
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	/* get hold of the fileserver connection */
2021da177e4SLinus Torvalds 	ret = afs_server_get_fsconn(server, &conn);
2031da177e4SLinus Torvalds 	if (ret < 0)
2041da177e4SLinus Torvalds 		goto out;
2051da177e4SLinus Torvalds 
2061da177e4SLinus Torvalds 	/* create a call through that connection */
2071da177e4SLinus Torvalds 	ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
2081da177e4SLinus Torvalds 	if (ret < 0) {
2091da177e4SLinus Torvalds 		printk("kAFS: Unable to create call: %d\n", ret);
2101da177e4SLinus Torvalds 		goto out_put_conn;
2111da177e4SLinus Torvalds 	}
2121da177e4SLinus Torvalds 	call->app_opcode = FSGETVOLUMEINFO;
2131da177e4SLinus Torvalds 
2141da177e4SLinus Torvalds 	/* we want to get event notifications from the call */
2151da177e4SLinus Torvalds 	add_wait_queue(&call->waitq, &myself);
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds 	/* marshall the parameters */
2181da177e4SLinus Torvalds 	piov[1].iov_len = strlen(name);
2191da177e4SLinus Torvalds 	piov[1].iov_base = (char *) name;
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds 	zero = 0;
2221da177e4SLinus Torvalds 	piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
2231da177e4SLinus Torvalds 	piov[2].iov_base = &zero;
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds 	param[0] = htonl(FSGETVOLUMEINFO);
2261da177e4SLinus Torvalds 	param[1] = htonl(piov[1].iov_len);
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds 	piov[0].iov_len = sizeof(param);
2291da177e4SLinus Torvalds 	piov[0].iov_base = param;
2301da177e4SLinus Torvalds 
2311da177e4SLinus Torvalds 	/* send the parameters to the server */
2321da177e4SLinus Torvalds 	ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
2331da177e4SLinus Torvalds 				    0, &sent);
2341da177e4SLinus Torvalds 	if (ret < 0)
2351da177e4SLinus Torvalds 		goto abort;
2361da177e4SLinus Torvalds 
2371da177e4SLinus Torvalds 	/* wait for the reply to completely arrive */
2381da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, 64);
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds 	ret = rxrpc_call_read_data(call, bp, 64,
2411da177e4SLinus Torvalds 				   RXRPC_CALL_READ_BLOCK |
2421da177e4SLinus Torvalds 				   RXRPC_CALL_READ_ALL);
2431da177e4SLinus Torvalds 	if (ret < 0) {
2441da177e4SLinus Torvalds 		if (ret == -ECONNABORTED) {
2451da177e4SLinus Torvalds 			ret = call->app_errno;
2461da177e4SLinus Torvalds 			goto out_unwait;
2471da177e4SLinus Torvalds 		}
2481da177e4SLinus Torvalds 		goto abort;
2491da177e4SLinus Torvalds 	}
2501da177e4SLinus Torvalds 
2511da177e4SLinus Torvalds 	/* unmarshall the reply */
2521da177e4SLinus Torvalds 	vinfo->vid = ntohl(*bp++);
2531da177e4SLinus Torvalds 	vinfo->type = ntohl(*bp++);
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds 	vinfo->type_vids[0] = ntohl(*bp++);
2561da177e4SLinus Torvalds 	vinfo->type_vids[1] = ntohl(*bp++);
2571da177e4SLinus Torvalds 	vinfo->type_vids[2] = ntohl(*bp++);
2581da177e4SLinus Torvalds 	vinfo->type_vids[3] = ntohl(*bp++);
2591da177e4SLinus Torvalds 	vinfo->type_vids[4] = ntohl(*bp++);
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 	vinfo->nservers = ntohl(*bp++);
2621da177e4SLinus Torvalds 	vinfo->servers[0].addr.s_addr = *bp++;
2631da177e4SLinus Torvalds 	vinfo->servers[1].addr.s_addr = *bp++;
2641da177e4SLinus Torvalds 	vinfo->servers[2].addr.s_addr = *bp++;
2651da177e4SLinus Torvalds 	vinfo->servers[3].addr.s_addr = *bp++;
2661da177e4SLinus Torvalds 	vinfo->servers[4].addr.s_addr = *bp++;
2671da177e4SLinus Torvalds 	vinfo->servers[5].addr.s_addr = *bp++;
2681da177e4SLinus Torvalds 	vinfo->servers[6].addr.s_addr = *bp++;
2691da177e4SLinus Torvalds 	vinfo->servers[7].addr.s_addr = *bp++;
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	ret = -EBADMSG;
2721da177e4SLinus Torvalds 	if (vinfo->nservers > 8)
2731da177e4SLinus Torvalds 		goto abort;
2741da177e4SLinus Torvalds 
2751da177e4SLinus Torvalds 	/* success */
2761da177e4SLinus Torvalds 	ret = 0;
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds  out_unwait:
2791da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
2801da177e4SLinus Torvalds 	remove_wait_queue(&call->waitq, &myself);
2811da177e4SLinus Torvalds 	rxrpc_put_call(call);
2821da177e4SLinus Torvalds  out_put_conn:
2831da177e4SLinus Torvalds 	afs_server_release_fsconn(server, conn);
2841da177e4SLinus Torvalds  out:
2851da177e4SLinus Torvalds 	_leave("");
2861da177e4SLinus Torvalds 	return ret;
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds  abort:
2891da177e4SLinus Torvalds 	set_current_state(TASK_UNINTERRUPTIBLE);
2901da177e4SLinus Torvalds 	rxrpc_call_abort(call, ret);
2911da177e4SLinus Torvalds 	schedule();
2921da177e4SLinus Torvalds 	goto out_unwait;
2931da177e4SLinus Torvalds 
2941da177e4SLinus Torvalds } /* end afs_rxfs_get_volume_info() */
2951da177e4SLinus Torvalds #endif
2961da177e4SLinus Torvalds 
2971da177e4SLinus Torvalds /*****************************************************************************/
2981da177e4SLinus Torvalds /*
2991da177e4SLinus Torvalds  * fetch the status information for a file
3001da177e4SLinus Torvalds  */
3011da177e4SLinus Torvalds int afs_rxfs_fetch_file_status(struct afs_server *server,
3021da177e4SLinus Torvalds 			       struct afs_vnode *vnode,
3031da177e4SLinus Torvalds 			       struct afs_volsync *volsync)
3041da177e4SLinus Torvalds {
3051da177e4SLinus Torvalds 	struct afs_server_callslot callslot;
3061da177e4SLinus Torvalds 	struct rxrpc_call *call;
3071da177e4SLinus Torvalds 	struct kvec piov[1];
3081da177e4SLinus Torvalds 	size_t sent;
3091da177e4SLinus Torvalds 	int ret;
3101da177e4SLinus Torvalds 	__be32 *bp;
3111da177e4SLinus Torvalds 
3121da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(myself, current);
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 	_enter("%p,{%u,%u,%u}",
3151da177e4SLinus Torvalds 	       server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds 	/* get hold of the fileserver connection */
3181da177e4SLinus Torvalds 	ret = afs_server_request_callslot(server, &callslot);
3191da177e4SLinus Torvalds 	if (ret < 0)
3201da177e4SLinus Torvalds 		goto out;
3211da177e4SLinus Torvalds 
3221da177e4SLinus Torvalds 	/* create a call through that connection */
3231da177e4SLinus Torvalds 	ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap,
3241da177e4SLinus Torvalds 				&call);
3251da177e4SLinus Torvalds 	if (ret < 0) {
3261da177e4SLinus Torvalds 		printk("kAFS: Unable to create call: %d\n", ret);
3271da177e4SLinus Torvalds 		goto out_put_conn;
3281da177e4SLinus Torvalds 	}
3291da177e4SLinus Torvalds 	call->app_opcode = FSFETCHSTATUS;
3301da177e4SLinus Torvalds 
3311da177e4SLinus Torvalds 	/* we want to get event notifications from the call */
3321da177e4SLinus Torvalds 	add_wait_queue(&call->waitq, &myself);
3331da177e4SLinus Torvalds 
3341da177e4SLinus Torvalds 	/* marshall the parameters */
3351da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, 16);
3361da177e4SLinus Torvalds 	bp[0] = htonl(FSFETCHSTATUS);
3371da177e4SLinus Torvalds 	bp[1] = htonl(vnode->fid.vid);
3381da177e4SLinus Torvalds 	bp[2] = htonl(vnode->fid.vnode);
3391da177e4SLinus Torvalds 	bp[3] = htonl(vnode->fid.unique);
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds 	piov[0].iov_len = 16;
3421da177e4SLinus Torvalds 	piov[0].iov_base = bp;
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds 	/* send the parameters to the server */
3451da177e4SLinus Torvalds 	ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
3461da177e4SLinus Torvalds 				    0, &sent);
3471da177e4SLinus Torvalds 	if (ret < 0)
3481da177e4SLinus Torvalds 		goto abort;
3491da177e4SLinus Torvalds 
3501da177e4SLinus Torvalds 	/* wait for the reply to completely arrive */
3511da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, 120);
3521da177e4SLinus Torvalds 
3531da177e4SLinus Torvalds 	ret = rxrpc_call_read_data(call, bp, 120,
3541da177e4SLinus Torvalds 				   RXRPC_CALL_READ_BLOCK |
3551da177e4SLinus Torvalds 				   RXRPC_CALL_READ_ALL);
3561da177e4SLinus Torvalds 	if (ret < 0) {
3571da177e4SLinus Torvalds 		if (ret == -ECONNABORTED) {
3581da177e4SLinus Torvalds 			ret = call->app_errno;
3591da177e4SLinus Torvalds 			goto out_unwait;
3601da177e4SLinus Torvalds 		}
3611da177e4SLinus Torvalds 		goto abort;
3621da177e4SLinus Torvalds 	}
3631da177e4SLinus Torvalds 
3641da177e4SLinus Torvalds 	/* unmarshall the reply */
3651da177e4SLinus Torvalds 	vnode->status.if_version	= ntohl(*bp++);
3661da177e4SLinus Torvalds 	vnode->status.type		= ntohl(*bp++);
3671da177e4SLinus Torvalds 	vnode->status.nlink		= ntohl(*bp++);
3681da177e4SLinus Torvalds 	vnode->status.size		= ntohl(*bp++);
3691da177e4SLinus Torvalds 	vnode->status.version		= ntohl(*bp++);
3701da177e4SLinus Torvalds 	vnode->status.author		= ntohl(*bp++);
3711da177e4SLinus Torvalds 	vnode->status.owner		= ntohl(*bp++);
3721da177e4SLinus Torvalds 	vnode->status.caller_access	= ntohl(*bp++);
3731da177e4SLinus Torvalds 	vnode->status.anon_access	= ntohl(*bp++);
3741da177e4SLinus Torvalds 	vnode->status.mode		= ntohl(*bp++);
3751da177e4SLinus Torvalds 	vnode->status.parent.vid	= vnode->fid.vid;
3761da177e4SLinus Torvalds 	vnode->status.parent.vnode	= ntohl(*bp++);
3771da177e4SLinus Torvalds 	vnode->status.parent.unique	= ntohl(*bp++);
3781da177e4SLinus Torvalds 	bp++; /* seg size */
3791da177e4SLinus Torvalds 	vnode->status.mtime_client	= ntohl(*bp++);
3801da177e4SLinus Torvalds 	vnode->status.mtime_server	= ntohl(*bp++);
3811da177e4SLinus Torvalds 	bp++; /* group */
3821da177e4SLinus Torvalds 	bp++; /* sync counter */
3831da177e4SLinus Torvalds 	vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
3841da177e4SLinus Torvalds 	bp++; /* spare2 */
3851da177e4SLinus Torvalds 	bp++; /* spare3 */
3861da177e4SLinus Torvalds 	bp++; /* spare4 */
3871da177e4SLinus Torvalds 
3881da177e4SLinus Torvalds 	vnode->cb_version		= ntohl(*bp++);
3891da177e4SLinus Torvalds 	vnode->cb_expiry		= ntohl(*bp++);
3901da177e4SLinus Torvalds 	vnode->cb_type			= ntohl(*bp++);
3911da177e4SLinus Torvalds 
3921da177e4SLinus Torvalds 	if (volsync) {
3931da177e4SLinus Torvalds 		volsync->creation	= ntohl(*bp++);
3941da177e4SLinus Torvalds 		bp++; /* spare2 */
3951da177e4SLinus Torvalds 		bp++; /* spare3 */
3961da177e4SLinus Torvalds 		bp++; /* spare4 */
3971da177e4SLinus Torvalds 		bp++; /* spare5 */
3981da177e4SLinus Torvalds 		bp++; /* spare6 */
3991da177e4SLinus Torvalds 	}
4001da177e4SLinus Torvalds 
4011da177e4SLinus Torvalds 	/* success */
4021da177e4SLinus Torvalds 	ret = 0;
4031da177e4SLinus Torvalds 
4041da177e4SLinus Torvalds  out_unwait:
4051da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
4061da177e4SLinus Torvalds 	remove_wait_queue(&call->waitq, &myself);
4071da177e4SLinus Torvalds 	rxrpc_put_call(call);
4081da177e4SLinus Torvalds  out_put_conn:
4091da177e4SLinus Torvalds 	afs_server_release_callslot(server, &callslot);
4101da177e4SLinus Torvalds  out:
4111da177e4SLinus Torvalds 	_leave("");
4121da177e4SLinus Torvalds 	return ret;
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds  abort:
4151da177e4SLinus Torvalds 	set_current_state(TASK_UNINTERRUPTIBLE);
4161da177e4SLinus Torvalds 	rxrpc_call_abort(call, ret);
4171da177e4SLinus Torvalds 	schedule();
4181da177e4SLinus Torvalds 	goto out_unwait;
4191da177e4SLinus Torvalds } /* end afs_rxfs_fetch_file_status() */
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds /*****************************************************************************/
4221da177e4SLinus Torvalds /*
4231da177e4SLinus Torvalds  * fetch the contents of a file or directory
4241da177e4SLinus Torvalds  */
4251da177e4SLinus Torvalds int afs_rxfs_fetch_file_data(struct afs_server *server,
4261da177e4SLinus Torvalds 			     struct afs_vnode *vnode,
4271da177e4SLinus Torvalds 			     struct afs_rxfs_fetch_descriptor *desc,
4281da177e4SLinus Torvalds 			     struct afs_volsync *volsync)
4291da177e4SLinus Torvalds {
4301da177e4SLinus Torvalds 	struct afs_server_callslot callslot;
4311da177e4SLinus Torvalds 	struct rxrpc_call *call;
4321da177e4SLinus Torvalds 	struct kvec piov[1];
4331da177e4SLinus Torvalds 	size_t sent;
4341da177e4SLinus Torvalds 	int ret;
4351da177e4SLinus Torvalds 	__be32 *bp;
4361da177e4SLinus Torvalds 
4371da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(myself, current);
4381da177e4SLinus Torvalds 
4391da177e4SLinus Torvalds 	_enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}",
4401da177e4SLinus Torvalds 	       server,
4411da177e4SLinus Torvalds 	       desc->fid.vid,
4421da177e4SLinus Torvalds 	       desc->fid.vnode,
4431da177e4SLinus Torvalds 	       desc->fid.unique,
4441da177e4SLinus Torvalds 	       desc->size,
4451da177e4SLinus Torvalds 	       desc->offset);
4461da177e4SLinus Torvalds 
4471da177e4SLinus Torvalds 	/* get hold of the fileserver connection */
4481da177e4SLinus Torvalds 	ret = afs_server_request_callslot(server, &callslot);
4491da177e4SLinus Torvalds 	if (ret < 0)
4501da177e4SLinus Torvalds 		goto out;
4511da177e4SLinus Torvalds 
4521da177e4SLinus Torvalds 	/* create a call through that connection */
4531da177e4SLinus Torvalds 	ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
4541da177e4SLinus Torvalds 	if (ret < 0) {
4551da177e4SLinus Torvalds 		printk("kAFS: Unable to create call: %d\n", ret);
4561da177e4SLinus Torvalds 		goto out_put_conn;
4571da177e4SLinus Torvalds 	}
4581da177e4SLinus Torvalds 	call->app_opcode = FSFETCHDATA;
4591da177e4SLinus Torvalds 
4601da177e4SLinus Torvalds 	/* we want to get event notifications from the call */
4611da177e4SLinus Torvalds 	add_wait_queue(&call->waitq, &myself);
4621da177e4SLinus Torvalds 
4631da177e4SLinus Torvalds 	/* marshall the parameters */
4641da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, 24);
4651da177e4SLinus Torvalds 	bp[0] = htonl(FSFETCHDATA);
4661da177e4SLinus Torvalds 	bp[1] = htonl(desc->fid.vid);
4671da177e4SLinus Torvalds 	bp[2] = htonl(desc->fid.vnode);
4681da177e4SLinus Torvalds 	bp[3] = htonl(desc->fid.unique);
4691da177e4SLinus Torvalds 	bp[4] = htonl(desc->offset);
4701da177e4SLinus Torvalds 	bp[5] = htonl(desc->size);
4711da177e4SLinus Torvalds 
4721da177e4SLinus Torvalds 	piov[0].iov_len = 24;
4731da177e4SLinus Torvalds 	piov[0].iov_base = bp;
4741da177e4SLinus Torvalds 
4751da177e4SLinus Torvalds 	/* send the parameters to the server */
4761da177e4SLinus Torvalds 	ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
4771da177e4SLinus Torvalds 				    0, &sent);
4781da177e4SLinus Torvalds 	if (ret < 0)
4791da177e4SLinus Torvalds 		goto abort;
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds 	/* wait for the data count to arrive */
4821da177e4SLinus Torvalds 	ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK);
4831da177e4SLinus Torvalds 	if (ret < 0)
4841da177e4SLinus Torvalds 		goto read_failed;
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds 	desc->actual = ntohl(bp[0]);
4871da177e4SLinus Torvalds 	if (desc->actual != desc->size) {
4881da177e4SLinus Torvalds 		ret = -EBADMSG;
4891da177e4SLinus Torvalds 		goto abort;
4901da177e4SLinus Torvalds 	}
4911da177e4SLinus Torvalds 
4921da177e4SLinus Torvalds 	/* call the app to read the actual data */
4931da177e4SLinus Torvalds 	rxrpc_call_reset_scratch(call);
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds 	ret = rxrpc_call_read_data(call, desc->buffer, desc->actual,
4961da177e4SLinus Torvalds 				   RXRPC_CALL_READ_BLOCK);
4971da177e4SLinus Torvalds 	if (ret < 0)
4981da177e4SLinus Torvalds 		goto read_failed;
4991da177e4SLinus Torvalds 
5001da177e4SLinus Torvalds 	/* wait for the rest of the reply to completely arrive */
5011da177e4SLinus Torvalds 	rxrpc_call_reset_scratch(call);
5021da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, 120);
5031da177e4SLinus Torvalds 
5041da177e4SLinus Torvalds 	ret = rxrpc_call_read_data(call, bp, 120,
5051da177e4SLinus Torvalds 				   RXRPC_CALL_READ_BLOCK |
5061da177e4SLinus Torvalds 				   RXRPC_CALL_READ_ALL);
5071da177e4SLinus Torvalds 	if (ret < 0)
5081da177e4SLinus Torvalds 		goto read_failed;
5091da177e4SLinus Torvalds 
5101da177e4SLinus Torvalds 	/* unmarshall the reply */
5111da177e4SLinus Torvalds 	vnode->status.if_version	= ntohl(*bp++);
5121da177e4SLinus Torvalds 	vnode->status.type		= ntohl(*bp++);
5131da177e4SLinus Torvalds 	vnode->status.nlink		= ntohl(*bp++);
5141da177e4SLinus Torvalds 	vnode->status.size		= ntohl(*bp++);
5151da177e4SLinus Torvalds 	vnode->status.version		= ntohl(*bp++);
5161da177e4SLinus Torvalds 	vnode->status.author		= ntohl(*bp++);
5171da177e4SLinus Torvalds 	vnode->status.owner		= ntohl(*bp++);
5181da177e4SLinus Torvalds 	vnode->status.caller_access	= ntohl(*bp++);
5191da177e4SLinus Torvalds 	vnode->status.anon_access	= ntohl(*bp++);
5201da177e4SLinus Torvalds 	vnode->status.mode		= ntohl(*bp++);
5211da177e4SLinus Torvalds 	vnode->status.parent.vid	= desc->fid.vid;
5221da177e4SLinus Torvalds 	vnode->status.parent.vnode	= ntohl(*bp++);
5231da177e4SLinus Torvalds 	vnode->status.parent.unique	= ntohl(*bp++);
5241da177e4SLinus Torvalds 	bp++; /* seg size */
5251da177e4SLinus Torvalds 	vnode->status.mtime_client	= ntohl(*bp++);
5261da177e4SLinus Torvalds 	vnode->status.mtime_server	= ntohl(*bp++);
5271da177e4SLinus Torvalds 	bp++; /* group */
5281da177e4SLinus Torvalds 	bp++; /* sync counter */
5291da177e4SLinus Torvalds 	vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
5301da177e4SLinus Torvalds 	bp++; /* spare2 */
5311da177e4SLinus Torvalds 	bp++; /* spare3 */
5321da177e4SLinus Torvalds 	bp++; /* spare4 */
5331da177e4SLinus Torvalds 
5341da177e4SLinus Torvalds 	vnode->cb_version		= ntohl(*bp++);
5351da177e4SLinus Torvalds 	vnode->cb_expiry		= ntohl(*bp++);
5361da177e4SLinus Torvalds 	vnode->cb_type			= ntohl(*bp++);
5371da177e4SLinus Torvalds 
5381da177e4SLinus Torvalds 	if (volsync) {
5391da177e4SLinus Torvalds 		volsync->creation	= ntohl(*bp++);
5401da177e4SLinus Torvalds 		bp++; /* spare2 */
5411da177e4SLinus Torvalds 		bp++; /* spare3 */
5421da177e4SLinus Torvalds 		bp++; /* spare4 */
5431da177e4SLinus Torvalds 		bp++; /* spare5 */
5441da177e4SLinus Torvalds 		bp++; /* spare6 */
5451da177e4SLinus Torvalds 	}
5461da177e4SLinus Torvalds 
5471da177e4SLinus Torvalds 	/* success */
5481da177e4SLinus Torvalds 	ret = 0;
5491da177e4SLinus Torvalds 
5501da177e4SLinus Torvalds  out_unwait:
5511da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
5521da177e4SLinus Torvalds 	remove_wait_queue(&call->waitq,&myself);
5531da177e4SLinus Torvalds 	rxrpc_put_call(call);
5541da177e4SLinus Torvalds  out_put_conn:
5551da177e4SLinus Torvalds 	afs_server_release_callslot(server, &callslot);
5561da177e4SLinus Torvalds  out:
5571da177e4SLinus Torvalds 	_leave(" = %d", ret);
5581da177e4SLinus Torvalds 	return ret;
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds  read_failed:
5611da177e4SLinus Torvalds 	if (ret == -ECONNABORTED) {
5621da177e4SLinus Torvalds 		ret = call->app_errno;
5631da177e4SLinus Torvalds 		goto out_unwait;
5641da177e4SLinus Torvalds 	}
5651da177e4SLinus Torvalds 
5661da177e4SLinus Torvalds  abort:
5671da177e4SLinus Torvalds 	set_current_state(TASK_UNINTERRUPTIBLE);
5681da177e4SLinus Torvalds 	rxrpc_call_abort(call, ret);
5691da177e4SLinus Torvalds 	schedule();
5701da177e4SLinus Torvalds 	goto out_unwait;
5711da177e4SLinus Torvalds 
5721da177e4SLinus Torvalds } /* end afs_rxfs_fetch_file_data() */
5731da177e4SLinus Torvalds 
5741da177e4SLinus Torvalds /*****************************************************************************/
5751da177e4SLinus Torvalds /*
5761da177e4SLinus Torvalds  * ask the AFS fileserver to discard a callback request on a file
5771da177e4SLinus Torvalds  */
5781da177e4SLinus Torvalds int afs_rxfs_give_up_callback(struct afs_server *server,
5791da177e4SLinus Torvalds 			      struct afs_vnode *vnode)
5801da177e4SLinus Torvalds {
5811da177e4SLinus Torvalds 	struct afs_server_callslot callslot;
5821da177e4SLinus Torvalds 	struct rxrpc_call *call;
5831da177e4SLinus Torvalds 	struct kvec piov[1];
5841da177e4SLinus Torvalds 	size_t sent;
5851da177e4SLinus Torvalds 	int ret;
5861da177e4SLinus Torvalds 	__be32 *bp;
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(myself, current);
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds 	_enter("%p,{%u,%u,%u}",
5911da177e4SLinus Torvalds 	       server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
5921da177e4SLinus Torvalds 
5931da177e4SLinus Torvalds 	/* get hold of the fileserver connection */
5941da177e4SLinus Torvalds 	ret = afs_server_request_callslot(server, &callslot);
5951da177e4SLinus Torvalds 	if (ret < 0)
5961da177e4SLinus Torvalds 		goto out;
5971da177e4SLinus Torvalds 
5981da177e4SLinus Torvalds 	/* create a call through that connection */
5991da177e4SLinus Torvalds 	ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
6001da177e4SLinus Torvalds 	if (ret < 0) {
6011da177e4SLinus Torvalds 		printk("kAFS: Unable to create call: %d\n", ret);
6021da177e4SLinus Torvalds 		goto out_put_conn;
6031da177e4SLinus Torvalds 	}
6041da177e4SLinus Torvalds 	call->app_opcode = FSGIVEUPCALLBACKS;
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds 	/* we want to get event notifications from the call */
6071da177e4SLinus Torvalds 	add_wait_queue(&call->waitq, &myself);
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 	/* marshall the parameters */
6101da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4);
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 	piov[0].iov_len = (1 + 4 + 4) * 4;
6131da177e4SLinus Torvalds 	piov[0].iov_base = bp;
6141da177e4SLinus Torvalds 
6151da177e4SLinus Torvalds 	*bp++ = htonl(FSGIVEUPCALLBACKS);
6161da177e4SLinus Torvalds 	*bp++ = htonl(1);
6171da177e4SLinus Torvalds 	*bp++ = htonl(vnode->fid.vid);
6181da177e4SLinus Torvalds 	*bp++ = htonl(vnode->fid.vnode);
6191da177e4SLinus Torvalds 	*bp++ = htonl(vnode->fid.unique);
6201da177e4SLinus Torvalds 	*bp++ = htonl(1);
6211da177e4SLinus Torvalds 	*bp++ = htonl(vnode->cb_version);
6221da177e4SLinus Torvalds 	*bp++ = htonl(vnode->cb_expiry);
6231da177e4SLinus Torvalds 	*bp++ = htonl(vnode->cb_type);
6241da177e4SLinus Torvalds 
6251da177e4SLinus Torvalds 	/* send the parameters to the server */
6261da177e4SLinus Torvalds 	ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
6271da177e4SLinus Torvalds 				    0, &sent);
6281da177e4SLinus Torvalds 	if (ret < 0)
6291da177e4SLinus Torvalds 		goto abort;
6301da177e4SLinus Torvalds 
6311da177e4SLinus Torvalds 	/* wait for the reply to completely arrive */
6321da177e4SLinus Torvalds 	for (;;) {
6331da177e4SLinus Torvalds 		set_current_state(TASK_INTERRUPTIBLE);
6341da177e4SLinus Torvalds 		if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
6351da177e4SLinus Torvalds 		    signal_pending(current))
6361da177e4SLinus Torvalds 			break;
6371da177e4SLinus Torvalds 		schedule();
6381da177e4SLinus Torvalds 	}
6391da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 	ret = -EINTR;
6421da177e4SLinus Torvalds 	if (signal_pending(current))
6431da177e4SLinus Torvalds 		goto abort;
6441da177e4SLinus Torvalds 
6451da177e4SLinus Torvalds 	switch (call->app_call_state) {
6461da177e4SLinus Torvalds 	case RXRPC_CSTATE_ERROR:
6471da177e4SLinus Torvalds 		ret = call->app_errno;
6481da177e4SLinus Torvalds 		goto out_unwait;
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds 	case RXRPC_CSTATE_CLNT_GOT_REPLY:
6511da177e4SLinus Torvalds 		ret = 0;
6521da177e4SLinus Torvalds 		goto out_unwait;
6531da177e4SLinus Torvalds 
6541da177e4SLinus Torvalds 	default:
6551da177e4SLinus Torvalds 		BUG();
6561da177e4SLinus Torvalds 	}
6571da177e4SLinus Torvalds 
6581da177e4SLinus Torvalds  out_unwait:
6591da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
6601da177e4SLinus Torvalds 	remove_wait_queue(&call->waitq, &myself);
6611da177e4SLinus Torvalds 	rxrpc_put_call(call);
6621da177e4SLinus Torvalds  out_put_conn:
6631da177e4SLinus Torvalds 	afs_server_release_callslot(server, &callslot);
6641da177e4SLinus Torvalds  out:
6651da177e4SLinus Torvalds 	_leave("");
6661da177e4SLinus Torvalds 	return ret;
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds  abort:
6691da177e4SLinus Torvalds 	set_current_state(TASK_UNINTERRUPTIBLE);
6701da177e4SLinus Torvalds 	rxrpc_call_abort(call, ret);
6711da177e4SLinus Torvalds 	schedule();
6721da177e4SLinus Torvalds 	goto out_unwait;
6731da177e4SLinus Torvalds } /* end afs_rxfs_give_up_callback() */
6741da177e4SLinus Torvalds 
6751da177e4SLinus Torvalds /*****************************************************************************/
6761da177e4SLinus Torvalds /*
6771da177e4SLinus Torvalds  * look a filename up in a directory
6781da177e4SLinus Torvalds  * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
6791da177e4SLinus Torvalds  */
6801da177e4SLinus Torvalds #if 0
6811da177e4SLinus Torvalds int afs_rxfs_lookup(struct afs_server *server,
6821da177e4SLinus Torvalds 		    struct afs_vnode *dir,
6831da177e4SLinus Torvalds 		    const char *filename,
6841da177e4SLinus Torvalds 		    struct afs_vnode *vnode,
6851da177e4SLinus Torvalds 		    struct afs_volsync *volsync)
6861da177e4SLinus Torvalds {
6871da177e4SLinus Torvalds 	struct rxrpc_connection *conn;
6881da177e4SLinus Torvalds 	struct rxrpc_call *call;
6891da177e4SLinus Torvalds 	struct kvec piov[3];
6901da177e4SLinus Torvalds 	size_t sent;
6911da177e4SLinus Torvalds 	int ret;
6921da177e4SLinus Torvalds 	u32 *bp, zero;
6931da177e4SLinus Torvalds 
6941da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(myself, current);
6951da177e4SLinus Torvalds 
6961da177e4SLinus Torvalds 	kenter("%p,{%u,%u,%u},%s",
6971da177e4SLinus Torvalds 	       server, fid->vid, fid->vnode, fid->unique, filename);
6981da177e4SLinus Torvalds 
6991da177e4SLinus Torvalds 	/* get hold of the fileserver connection */
7001da177e4SLinus Torvalds 	ret = afs_server_get_fsconn(server, &conn);
7011da177e4SLinus Torvalds 	if (ret < 0)
7021da177e4SLinus Torvalds 		goto out;
7031da177e4SLinus Torvalds 
7041da177e4SLinus Torvalds 	/* create a call through that connection */
7051da177e4SLinus Torvalds 	ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
7061da177e4SLinus Torvalds 	if (ret < 0) {
7071da177e4SLinus Torvalds 		printk("kAFS: Unable to create call: %d\n", ret);
7081da177e4SLinus Torvalds 		goto out_put_conn;
7091da177e4SLinus Torvalds 	}
7101da177e4SLinus Torvalds 	call->app_opcode = FSLOOKUP;
7111da177e4SLinus Torvalds 
7121da177e4SLinus Torvalds 	/* we want to get event notifications from the call */
7131da177e4SLinus Torvalds 	add_wait_queue(&call->waitq,&myself);
7141da177e4SLinus Torvalds 
7151da177e4SLinus Torvalds 	/* marshall the parameters */
7161da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, 20);
7171da177e4SLinus Torvalds 
7181da177e4SLinus Torvalds 	zero = 0;
7191da177e4SLinus Torvalds 
7201da177e4SLinus Torvalds 	piov[0].iov_len = 20;
7211da177e4SLinus Torvalds 	piov[0].iov_base = bp;
7221da177e4SLinus Torvalds 	piov[1].iov_len = strlen(filename);
7231da177e4SLinus Torvalds 	piov[1].iov_base = (char *) filename;
7241da177e4SLinus Torvalds 	piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
7251da177e4SLinus Torvalds 	piov[2].iov_base = &zero;
7261da177e4SLinus Torvalds 
7271da177e4SLinus Torvalds 	*bp++ = htonl(FSLOOKUP);
7281da177e4SLinus Torvalds 	*bp++ = htonl(dirfid->vid);
7291da177e4SLinus Torvalds 	*bp++ = htonl(dirfid->vnode);
7301da177e4SLinus Torvalds 	*bp++ = htonl(dirfid->unique);
7311da177e4SLinus Torvalds 	*bp++ = htonl(piov[1].iov_len);
7321da177e4SLinus Torvalds 
7331da177e4SLinus Torvalds 	/* send the parameters to the server */
7341da177e4SLinus Torvalds 	ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
7351da177e4SLinus Torvalds 				    0, &sent);
7361da177e4SLinus Torvalds 	if (ret < 0)
7371da177e4SLinus Torvalds 		goto abort;
7381da177e4SLinus Torvalds 
7391da177e4SLinus Torvalds 	/* wait for the reply to completely arrive */
7401da177e4SLinus Torvalds 	bp = rxrpc_call_alloc_scratch(call, 220);
7411da177e4SLinus Torvalds 
7421da177e4SLinus Torvalds 	ret = rxrpc_call_read_data(call, bp, 220,
7431da177e4SLinus Torvalds 				   RXRPC_CALL_READ_BLOCK |
7441da177e4SLinus Torvalds 				   RXRPC_CALL_READ_ALL);
7451da177e4SLinus Torvalds 	if (ret < 0) {
7461da177e4SLinus Torvalds 		if (ret == -ECONNABORTED) {
7471da177e4SLinus Torvalds 			ret = call->app_errno;
7481da177e4SLinus Torvalds 			goto out_unwait;
7491da177e4SLinus Torvalds 		}
7501da177e4SLinus Torvalds 		goto abort;
7511da177e4SLinus Torvalds 	}
7521da177e4SLinus Torvalds 
7531da177e4SLinus Torvalds 	/* unmarshall the reply */
7541da177e4SLinus Torvalds 	fid->vid		= ntohl(*bp++);
7551da177e4SLinus Torvalds 	fid->vnode		= ntohl(*bp++);
7561da177e4SLinus Torvalds 	fid->unique		= ntohl(*bp++);
7571da177e4SLinus Torvalds 
7581da177e4SLinus Torvalds 	vnode->status.if_version	= ntohl(*bp++);
7591da177e4SLinus Torvalds 	vnode->status.type		= ntohl(*bp++);
7601da177e4SLinus Torvalds 	vnode->status.nlink		= ntohl(*bp++);
7611da177e4SLinus Torvalds 	vnode->status.size		= ntohl(*bp++);
7621da177e4SLinus Torvalds 	vnode->status.version		= ntohl(*bp++);
7631da177e4SLinus Torvalds 	vnode->status.author		= ntohl(*bp++);
7641da177e4SLinus Torvalds 	vnode->status.owner		= ntohl(*bp++);
7651da177e4SLinus Torvalds 	vnode->status.caller_access	= ntohl(*bp++);
7661da177e4SLinus Torvalds 	vnode->status.anon_access	= ntohl(*bp++);
7671da177e4SLinus Torvalds 	vnode->status.mode		= ntohl(*bp++);
7681da177e4SLinus Torvalds 	vnode->status.parent.vid	= dirfid->vid;
7691da177e4SLinus Torvalds 	vnode->status.parent.vnode	= ntohl(*bp++);
7701da177e4SLinus Torvalds 	vnode->status.parent.unique	= ntohl(*bp++);
7711da177e4SLinus Torvalds 	bp++; /* seg size */
7721da177e4SLinus Torvalds 	vnode->status.mtime_client	= ntohl(*bp++);
7731da177e4SLinus Torvalds 	vnode->status.mtime_server	= ntohl(*bp++);
7741da177e4SLinus Torvalds 	bp++; /* group */
7751da177e4SLinus Torvalds 	bp++; /* sync counter */
7761da177e4SLinus Torvalds 	vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
7771da177e4SLinus Torvalds 	bp++; /* spare2 */
7781da177e4SLinus Torvalds 	bp++; /* spare3 */
7791da177e4SLinus Torvalds 	bp++; /* spare4 */
7801da177e4SLinus Torvalds 
7811da177e4SLinus Torvalds 	dir->status.if_version		= ntohl(*bp++);
7821da177e4SLinus Torvalds 	dir->status.type		= ntohl(*bp++);
7831da177e4SLinus Torvalds 	dir->status.nlink		= ntohl(*bp++);
7841da177e4SLinus Torvalds 	dir->status.size		= ntohl(*bp++);
7851da177e4SLinus Torvalds 	dir->status.version		= ntohl(*bp++);
7861da177e4SLinus Torvalds 	dir->status.author		= ntohl(*bp++);
7871da177e4SLinus Torvalds 	dir->status.owner		= ntohl(*bp++);
7881da177e4SLinus Torvalds 	dir->status.caller_access	= ntohl(*bp++);
7891da177e4SLinus Torvalds 	dir->status.anon_access		= ntohl(*bp++);
7901da177e4SLinus Torvalds 	dir->status.mode		= ntohl(*bp++);
7911da177e4SLinus Torvalds 	dir->status.parent.vid		= dirfid->vid;
7921da177e4SLinus Torvalds 	dir->status.parent.vnode	= ntohl(*bp++);
7931da177e4SLinus Torvalds 	dir->status.parent.unique	= ntohl(*bp++);
7941da177e4SLinus Torvalds 	bp++; /* seg size */
7951da177e4SLinus Torvalds 	dir->status.mtime_client	= ntohl(*bp++);
7961da177e4SLinus Torvalds 	dir->status.mtime_server	= ntohl(*bp++);
7971da177e4SLinus Torvalds 	bp++; /* group */
7981da177e4SLinus Torvalds 	bp++; /* sync counter */
7991da177e4SLinus Torvalds 	dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
8001da177e4SLinus Torvalds 	bp++; /* spare2 */
8011da177e4SLinus Torvalds 	bp++; /* spare3 */
8021da177e4SLinus Torvalds 	bp++; /* spare4 */
8031da177e4SLinus Torvalds 
8041da177e4SLinus Torvalds 	callback->fid		= *fid;
8051da177e4SLinus Torvalds 	callback->version	= ntohl(*bp++);
8061da177e4SLinus Torvalds 	callback->expiry	= ntohl(*bp++);
8071da177e4SLinus Torvalds 	callback->type		= ntohl(*bp++);
8081da177e4SLinus Torvalds 
8091da177e4SLinus Torvalds 	if (volsync) {
8101da177e4SLinus Torvalds 		volsync->creation	= ntohl(*bp++);
8111da177e4SLinus Torvalds 		bp++; /* spare2 */
8121da177e4SLinus Torvalds 		bp++; /* spare3 */
8131da177e4SLinus Torvalds 		bp++; /* spare4 */
8141da177e4SLinus Torvalds 		bp++; /* spare5 */
8151da177e4SLinus Torvalds 		bp++; /* spare6 */
8161da177e4SLinus Torvalds 	}
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds 	/* success */
8191da177e4SLinus Torvalds 	ret = 0;
8201da177e4SLinus Torvalds 
8211da177e4SLinus Torvalds  out_unwait:
8221da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
8231da177e4SLinus Torvalds 	remove_wait_queue(&call->waitq, &myself);
8241da177e4SLinus Torvalds 	rxrpc_put_call(call);
8251da177e4SLinus Torvalds  out_put_conn:
8261da177e4SLinus Torvalds 	afs_server_release_fsconn(server, conn);
8271da177e4SLinus Torvalds  out:
8281da177e4SLinus Torvalds 	kleave("");
8291da177e4SLinus Torvalds 	return ret;
8301da177e4SLinus Torvalds 
8311da177e4SLinus Torvalds  abort:
8321da177e4SLinus Torvalds 	set_current_state(TASK_UNINTERRUPTIBLE);
8331da177e4SLinus Torvalds 	rxrpc_call_abort(call, ret);
8341da177e4SLinus Torvalds 	schedule();
8351da177e4SLinus Torvalds 	goto out_unwait;
8361da177e4SLinus Torvalds } /* end afs_rxfs_lookup() */
8371da177e4SLinus Torvalds #endif
838