cmservice.c 16.9 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
D
David Howells 已提交
2
/* AFS Cache Manager Service
L
Linus Torvalds 已提交
3 4 5 6 7 8 9
 *
 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 */

#include <linux/module.h>
#include <linux/init.h>
10
#include <linux/slab.h>
L
Linus Torvalds 已提交
11
#include <linux/sched.h>
12
#include <linux/ip.h>
L
Linus Torvalds 已提交
13
#include "internal.h"
14
#include "afs_cm.h"
15
#include "protocol_yfs.h"
L
Linus Torvalds 已提交
16

17 18 19 20 21 22
static int afs_deliver_cb_init_call_back_state(struct afs_call *);
static int afs_deliver_cb_init_call_back_state3(struct afs_call *);
static int afs_deliver_cb_probe(struct afs_call *);
static int afs_deliver_cb_callback(struct afs_call *);
static int afs_deliver_cb_probe_uuid(struct afs_call *);
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *);
23
static void afs_cm_destructor(struct afs_call *);
24 25 26 27 28
static void SRXAFSCB_CallBack(struct work_struct *);
static void SRXAFSCB_InitCallBackState(struct work_struct *);
static void SRXAFSCB_Probe(struct work_struct *);
static void SRXAFSCB_ProbeUuid(struct work_struct *);
static void SRXAFSCB_TellMeAboutYourself(struct work_struct *);
L
Linus Torvalds 已提交
29

30 31
static int afs_deliver_yfs_cb_callback(struct afs_call *);

D
David Howells 已提交
32
#define CM_NAME(name) \
33
	char afs_SRXCB##name##_name[] __tracepoint_string =	\
D
David Howells 已提交
34 35
		"CB." #name

L
Linus Torvalds 已提交
36
/*
37
 * CB.CallBack operation type
L
Linus Torvalds 已提交
38
 */
D
David Howells 已提交
39
static CM_NAME(CallBack);
40
static const struct afs_call_type afs_SRXCBCallBack = {
D
David Howells 已提交
41
	.name		= afs_SRXCBCallBack_name,
42 43
	.deliver	= afs_deliver_cb_callback,
	.destructor	= afs_cm_destructor,
44
	.work		= SRXAFSCB_CallBack,
45
};
L
Linus Torvalds 已提交
46 47

/*
48
 * CB.InitCallBackState operation type
L
Linus Torvalds 已提交
49
 */
D
David Howells 已提交
50
static CM_NAME(InitCallBackState);
51
static const struct afs_call_type afs_SRXCBInitCallBackState = {
D
David Howells 已提交
52
	.name		= afs_SRXCBInitCallBackState_name,
53 54
	.deliver	= afs_deliver_cb_init_call_back_state,
	.destructor	= afs_cm_destructor,
55
	.work		= SRXAFSCB_InitCallBackState,
56
};
L
Linus Torvalds 已提交
57

58 59 60
/*
 * CB.InitCallBackState3 operation type
 */
D
David Howells 已提交
61
static CM_NAME(InitCallBackState3);
62
static const struct afs_call_type afs_SRXCBInitCallBackState3 = {
D
David Howells 已提交
63
	.name		= afs_SRXCBInitCallBackState3_name,
64 65
	.deliver	= afs_deliver_cb_init_call_back_state3,
	.destructor	= afs_cm_destructor,
66
	.work		= SRXAFSCB_InitCallBackState,
67 68
};

L
Linus Torvalds 已提交
69
/*
70
 * CB.Probe operation type
L
Linus Torvalds 已提交
71
 */
D
David Howells 已提交
72
static CM_NAME(Probe);
73
static const struct afs_call_type afs_SRXCBProbe = {
D
David Howells 已提交
74
	.name		= afs_SRXCBProbe_name,
75 76
	.deliver	= afs_deliver_cb_probe,
	.destructor	= afs_cm_destructor,
77
	.work		= SRXAFSCB_Probe,
78
};
L
Linus Torvalds 已提交
79

80 81 82
/*
 * CB.ProbeUuid operation type
 */
D
David Howells 已提交
83
static CM_NAME(ProbeUuid);
84
static const struct afs_call_type afs_SRXCBProbeUuid = {
D
David Howells 已提交
85
	.name		= afs_SRXCBProbeUuid_name,
86 87
	.deliver	= afs_deliver_cb_probe_uuid,
	.destructor	= afs_cm_destructor,
88
	.work		= SRXAFSCB_ProbeUuid,
89 90
};

91
/*
92
 * CB.TellMeAboutYourself operation type
93
 */
D
David Howells 已提交
94
static CM_NAME(TellMeAboutYourself);
95
static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
D
David Howells 已提交
96
	.name		= afs_SRXCBTellMeAboutYourself_name,
97
	.deliver	= afs_deliver_cb_tell_me_about_yourself,
98
	.destructor	= afs_cm_destructor,
99
	.work		= SRXAFSCB_TellMeAboutYourself,
100 101
};

102 103 104 105 106 107 108 109 110 111 112
/*
 * YFS CB.CallBack operation type
 */
static CM_NAME(YFS_CallBack);
static const struct afs_call_type afs_SRXYFSCB_CallBack = {
	.name		= afs_SRXCBYFS_CallBack_name,
	.deliver	= afs_deliver_yfs_cb_callback,
	.destructor	= afs_cm_destructor,
	.work		= SRXAFSCB_CallBack,
};

L
Linus Torvalds 已提交
113
/*
114 115
 * route an incoming cache manager call
 * - return T if supported, F if not
L
Linus Torvalds 已提交
116
 */
117
bool afs_cm_incoming_call(struct afs_call *call)
L
Linus Torvalds 已提交
118
{
119
	_enter("{%u, CB.OP %u}", call->service_id, call->operation_ID);
120

121 122
	call->epoch = rxrpc_kernel_get_epoch(call->net->socket, call->rxcall);

123
	switch (call->operation_ID) {
124 125 126 127 128 129
	case CBCallBack:
		call->type = &afs_SRXCBCallBack;
		return true;
	case CBInitCallBackState:
		call->type = &afs_SRXCBInitCallBackState;
		return true;
130 131 132
	case CBInitCallBackState3:
		call->type = &afs_SRXCBInitCallBackState3;
		return true;
133 134 135
	case CBProbe:
		call->type = &afs_SRXCBProbe;
		return true;
D
David Howells 已提交
136 137 138
	case CBProbeUuid:
		call->type = &afs_SRXCBProbeUuid;
		return true;
139 140
	case CBTellMeAboutYourself:
		call->type = &afs_SRXCBTellMeAboutYourself;
141
		return true;
142 143 144 145 146
	case YFSCBCallBack:
		if (call->service_id != YFS_CM_SERVICE)
			return false;
		call->type = &afs_SRXYFSCB_CallBack;
		return true;
147 148
	default:
		return false;
L
Linus Torvalds 已提交
149
	}
D
David Howells 已提交
150
}
L
Linus Torvalds 已提交
151

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
/*
 * Record a probe to the cache manager from a server.
 */
static int afs_record_cm_probe(struct afs_call *call, struct afs_server *server)
{
	_enter("");

	if (test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags) &&
	    !test_bit(AFS_SERVER_FL_PROBING, &server->flags)) {
		if (server->cm_epoch == call->epoch)
			return 0;

		if (!server->probe.said_rebooted) {
			pr_notice("kAFS: FS rebooted %pU\n", &server->uuid);
			server->probe.said_rebooted = true;
		}
	}

	spin_lock(&server->probe_lock);

	if (!test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags)) {
		server->cm_epoch = call->epoch;
		server->probe.cm_epoch = call->epoch;
		goto out;
	}

	if (server->probe.cm_probed &&
	    call->epoch != server->probe.cm_epoch &&
	    !server->probe.said_inconsistent) {
		pr_notice("kAFS: FS endpoints inconsistent %pU\n",
			  &server->uuid);
		server->probe.said_inconsistent = true;
	}

	if (!server->probe.cm_probed || call->epoch == server->cm_epoch)
		server->probe.cm_epoch = server->cm_epoch;

out:
	server->probe.cm_probed = true;
	spin_unlock(&server->probe_lock);
	return 0;
}

/*
 * Find the server record by peer address and record a probe to the cache
 * manager from a server.
 */
static int afs_find_cm_server_by_peer(struct afs_call *call)
{
	struct sockaddr_rxrpc srx;
	struct afs_server *server;

	rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);

	server = afs_find_server(call->net, &srx);
	if (!server) {
		trace_afs_cm_no_server(call, &srx);
		return 0;
	}

212
	call->server = server;
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
	return afs_record_cm_probe(call, server);
}

/*
 * Find the server record by server UUID and record a probe to the cache
 * manager from a server.
 */
static int afs_find_cm_server_by_uuid(struct afs_call *call,
				      struct afs_uuid *uuid)
{
	struct afs_server *server;

	rcu_read_lock();
	server = afs_find_server_by_uuid(call->net, call->request);
	rcu_read_unlock();
	if (!server) {
		trace_afs_cm_no_server_u(call, call->request);
		return 0;
	}

233
	call->server = server;
234 235 236
	return afs_record_cm_probe(call, server);
}

L
Linus Torvalds 已提交
237
/*
D
David Howells 已提交
238
 * Clean up a cache manager call.
L
Linus Torvalds 已提交
239
 */
240
static void afs_cm_destructor(struct afs_call *call)
L
Linus Torvalds 已提交
241
{
242 243
	kfree(call->buffer);
	call->buffer = NULL;
D
David Howells 已提交
244
}
L
Linus Torvalds 已提交
245 246

/*
247
 * The server supplied a list of callbacks that it wanted to break.
L
Linus Torvalds 已提交
248
 */
249
static void SRXAFSCB_CallBack(struct work_struct *work)
L
Linus Torvalds 已提交
250
{
251
	struct afs_call *call = container_of(work, struct afs_call, work);
L
Linus Torvalds 已提交
252

253
	_enter("");
L
Linus Torvalds 已提交
254

D
David Howells 已提交
255 256 257 258
	/* We need to break the callbacks before sending the reply as the
	 * server holds up change visibility till it receives our reply so as
	 * to maintain cache coherency.
	 */
D
David Howells 已提交
259 260 261
	if (call->server) {
		trace_afs_server(call->server, atomic_read(&call->server->usage),
				 afs_server_trace_callback);
262
		afs_break_callbacks(call->server, call->count, call->request);
D
David Howells 已提交
263
	}
D
David Howells 已提交
264 265

	afs_send_empty_reply(call);
266
	afs_put_call(call);
267
	_leave("");
D
David Howells 已提交
268
}
L
Linus Torvalds 已提交
269 270

/*
271
 * deliver request data to a CB.CallBack call
L
Linus Torvalds 已提交
272
 */
273
static int afs_deliver_cb_callback(struct afs_call *call)
L
Linus Torvalds 已提交
274
{
275
	struct afs_callback_break *cb;
276 277 278
	__be32 *bp;
	int ret, loop;

279
	_enter("{%u}", call->unmarshall);
280 281 282

	switch (call->unmarshall) {
	case 0:
283
		afs_extract_to_tmp(call);
284 285 286
		call->unmarshall++;

		/* extract the FID array and its count in two steps */
287
		/* fall through */
288 289
	case 1:
		_debug("extract FID count");
290
		ret = afs_extract_data(call, true);
291 292
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
293

294 295 296
		call->count = ntohl(call->tmp);
		_debug("FID count: %u", call->count);
		if (call->count > AFSCBMAX)
297 298
			return afs_protocol_error(call, -EBADMSG,
						  afs_eproto_cb_fid_count);
299

300 301
		call->buffer = kmalloc(array3_size(call->count, 3, 4),
				       GFP_KERNEL);
302 303
		if (!call->buffer)
			return -ENOMEM;
304
		afs_extract_to_buf(call, call->count * 3 * 4);
305 306
		call->unmarshall++;

307
		/* Fall through */
308 309
	case 2:
		_debug("extract FID array");
310
		ret = afs_extract_data(call, true);
311 312
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
313

314 315
		_debug("unmarshall FID array");
		call->request = kcalloc(call->count,
316
					sizeof(struct afs_callback_break),
317 318 319 320 321 322 323 324 325 326
					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++);
L
Linus Torvalds 已提交
327 328
		}

329
		afs_extract_to_tmp(call);
330 331 332
		call->unmarshall++;

		/* extract the callback array and its count in two steps */
333
		/* fall through */
334 335
	case 3:
		_debug("extract CB count");
336
		ret = afs_extract_data(call, true);
337 338
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
339

340 341 342
		call->count2 = ntohl(call->tmp);
		_debug("CB count: %u", call->count2);
		if (call->count2 != call->count && call->count2 != 0)
343 344
			return afs_protocol_error(call, -EBADMSG,
						  afs_eproto_cb_count);
345 346
		call->_iter = &call->iter;
		iov_iter_discard(&call->iter, READ, call->count2 * 3 * 4);
347 348
		call->unmarshall++;

349
		/* Fall through */
350
	case 4:
351 352 353
		_debug("extract discard %zu/%u",
		       iov_iter_count(&call->iter), call->count2 * 3 * 4);

354
		ret = afs_extract_data(call, false);
355 356
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
357

358
		call->unmarshall++;
359
	case 5:
L
Linus Torvalds 已提交
360 361 362
		break;
	}

363
	if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
364
		return afs_io_error(call, afs_io_error_cm_reply);
L
Linus Torvalds 已提交
365

366 367
	/* we'll need the file server record as that tells us which set of
	 * vnodes to operate upon */
368
	return afs_find_cm_server_by_peer(call);
D
David Howells 已提交
369
}
L
Linus Torvalds 已提交
370 371

/*
372
 * allow the fileserver to request callback state (re-)initialisation
L
Linus Torvalds 已提交
373
 */
374
static void SRXAFSCB_InitCallBackState(struct work_struct *work)
L
Linus Torvalds 已提交
375
{
376
	struct afs_call *call = container_of(work, struct afs_call, work);
L
Linus Torvalds 已提交
377

378
	_enter("{%p}", call->server);
L
Linus Torvalds 已提交
379

380 381
	if (call->server)
		afs_init_callback_state(call->server);
382
	afs_send_empty_reply(call);
383
	afs_put_call(call);
384
	_leave("");
D
David Howells 已提交
385
}
L
Linus Torvalds 已提交
386 387

/*
388
 * deliver request data to a CB.InitCallBackState call
L
Linus Torvalds 已提交
389
 */
390
static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
L
Linus Torvalds 已提交
391
{
392
	int ret;
L
Linus Torvalds 已提交
393

394
	_enter("");
L
Linus Torvalds 已提交
395

396 397
	afs_extract_discard(call, 0);
	ret = afs_extract_data(call, false);
398 399
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
400

401 402
	/* we'll need the file server record as that tells us which set of
	 * vnodes to operate upon */
403
	return afs_find_cm_server_by_peer(call);
404
}
L
Linus Torvalds 已提交
405

406 407 408
/*
 * deliver request data to a CB.InitCallBackState3 call
 */
409
static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
410
{
411
	struct afs_uuid *r;
412 413 414
	unsigned loop;
	__be32 *b;
	int ret;
415

416
	_enter("");
417

418 419 420 421
	_enter("{%u}", call->unmarshall);

	switch (call->unmarshall) {
	case 0:
422
		call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
423 424
		if (!call->buffer)
			return -ENOMEM;
425
		afs_extract_to_buf(call, 11 * sizeof(__be32));
426 427
		call->unmarshall++;

428
		/* Fall through */
429 430
	case 1:
		_debug("extract UUID");
431
		ret = afs_extract_data(call, false);
432 433 434 435 436 437 438
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		_debug("unmarshall UUID");
439
		call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
440 441 442 443 444
		if (!call->request)
			return -ENOMEM;

		b = call->buffer;
		r = call->request;
445 446 447
		r->time_low			= b[0];
		r->time_mid			= htons(ntohl(b[1]));
		r->time_hi_and_version		= htons(ntohl(b[2]));
448 449 450 451 452 453 454 455 456 457 458
		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->unmarshall++;

	case 2:
		break;
	}
459

460
	if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
461
		return afs_io_error(call, afs_io_error_cm_reply);
462 463 464

	/* we'll need the file server record as that tells us which set of
	 * vnodes to operate upon */
465
	return afs_find_cm_server_by_uuid(call, call->request);
466 467
}

468 469 470 471 472 473
/*
 * allow the fileserver to see if the cache manager is still alive
 */
static void SRXAFSCB_Probe(struct work_struct *work)
{
	struct afs_call *call = container_of(work, struct afs_call, work);
L
Linus Torvalds 已提交
474

475 476
	_enter("");
	afs_send_empty_reply(call);
477
	afs_put_call(call);
478 479
	_leave("");
}
L
Linus Torvalds 已提交
480

481 482 483
/*
 * deliver request data to a CB.Probe call
 */
484
static int afs_deliver_cb_probe(struct afs_call *call)
485
{
486 487
	int ret;

488
	_enter("");
L
Linus Torvalds 已提交
489

490 491
	afs_extract_discard(call, 0);
	ret = afs_extract_data(call, false);
492 493
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
494

495
	if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
496
		return afs_io_error(call, afs_io_error_cm_reply);
497
	return afs_find_cm_server_by_peer(call);
D
David Howells 已提交
498
}
499

500 501 502 503 504 505
/*
 * allow the fileserver to quickly find out if the fileserver has been rebooted
 */
static void SRXAFSCB_ProbeUuid(struct work_struct *work)
{
	struct afs_call *call = container_of(work, struct afs_call, work);
506
	struct afs_uuid *r = call->request;
507 508 509

	_enter("");

510
	if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
511
		afs_send_empty_reply(call);
512
	else
513 514
		rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
					1, 1, "K-1");
515

516
	afs_put_call(call);
517 518 519 520 521 522
	_leave("");
}

/*
 * deliver request data to a CB.ProbeUuid call
 */
523
static int afs_deliver_cb_probe_uuid(struct afs_call *call)
524
{
525
	struct afs_uuid *r;
526 527 528 529
	unsigned loop;
	__be32 *b;
	int ret;

530
	_enter("{%u}", call->unmarshall);
531 532 533

	switch (call->unmarshall) {
	case 0:
534
		call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
535 536
		if (!call->buffer)
			return -ENOMEM;
537
		afs_extract_to_buf(call, 11 * sizeof(__be32));
538 539
		call->unmarshall++;

540
		/* Fall through */
541 542
	case 1:
		_debug("extract UUID");
543
		ret = afs_extract_data(call, false);
544 545 546 547 548 549 550
		switch (ret) {
		case 0:		break;
		case -EAGAIN:	return 0;
		default:	return ret;
		}

		_debug("unmarshall UUID");
551
		call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
552 553 554 555 556
		if (!call->request)
			return -ENOMEM;

		b = call->buffer;
		r = call->request;
D
David Howells 已提交
557 558 559
		r->time_low			= b[0];
		r->time_mid			= htons(ntohl(b[1]));
		r->time_hi_and_version		= htons(ntohl(b[2]));
560 561 562 563 564 565 566 567 568 569 570 571
		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->unmarshall++;

	case 2:
		break;
	}

572
	if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
573
		return afs_io_error(call, afs_io_error_cm_reply);
574
	return afs_find_cm_server_by_uuid(call, call->request);
575 576
}

577 578 579
/*
 * allow the fileserver to ask about the cache manager's capabilities
 */
580
static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
581 582
{
	struct afs_call *call = container_of(work, struct afs_call, work);
583
	int loop;
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602

	struct {
		struct /* InterfaceAddr */ {
			__be32 nifs;
			__be32 uuid[11];
			__be32 ifaddr[32];
			__be32 netmask[32];
			__be32 mtu[32];
		} ia;
		struct /* Capabilities */ {
			__be32 capcount;
			__be32 caps[1];
		} cap;
	} reply;

	_enter("");

	memset(&reply, 0, sizeof(reply));

603 604 605 606 607
	reply.ia.uuid[0] = call->net->uuid.time_low;
	reply.ia.uuid[1] = htonl(ntohs(call->net->uuid.time_mid));
	reply.ia.uuid[2] = htonl(ntohs(call->net->uuid.time_hi_and_version));
	reply.ia.uuid[3] = htonl((s8) call->net->uuid.clock_seq_hi_and_reserved);
	reply.ia.uuid[4] = htonl((s8) call->net->uuid.clock_seq_low);
608
	for (loop = 0; loop < 6; loop++)
609
		reply.ia.uuid[loop + 5] = htonl((s8) call->net->uuid.node[loop]);
610 611 612 613

	reply.cap.capcount = htonl(1);
	reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION);
	afs_send_simple_reply(call, &reply, sizeof(reply));
614
	afs_put_call(call);
615 616 617 618
	_leave("");
}

/*
619
 * deliver request data to a CB.TellMeAboutYourself call
620
 */
621
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
622
{
623 624
	int ret;

625
	_enter("");
626

627 628
	afs_extract_discard(call, 0);
	ret = afs_extract_data(call, false);
629 630
	if (ret < 0)
		return ret;
631

632
	if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
633
		return afs_io_error(call, afs_io_error_cm_reply);
634
	return afs_find_cm_server_by_peer(call);
635
}
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654

/*
 * deliver request data to a YFS CB.CallBack call
 */
static int afs_deliver_yfs_cb_callback(struct afs_call *call)
{
	struct afs_callback_break *cb;
	struct yfs_xdr_YFSFid *bp;
	size_t size;
	int ret, loop;

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

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

		/* extract the FID array and its count in two steps */
655
		/* Fall through */
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
	case 1:
		_debug("extract FID count");
		ret = afs_extract_data(call, true);
		if (ret < 0)
			return ret;

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

		size = array_size(call->count, sizeof(struct yfs_xdr_YFSFid));
		call->buffer = kmalloc(size, GFP_KERNEL);
		if (!call->buffer)
			return -ENOMEM;
		afs_extract_to_buf(call, size);
		call->unmarshall++;

675
		/* Fall through */
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
	case 2:
		_debug("extract FID array");
		ret = afs_extract_data(call, false);
		if (ret < 0)
			return ret;

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

		cb = call->request;
		bp = call->buffer;
		for (loop = call->count; loop > 0; loop--, cb++) {
			cb->fid.vid	= xdr_to_u64(bp->volume);
			cb->fid.vnode	= xdr_to_u64(bp->vnode.lo);
			cb->fid.vnode_hi = ntohl(bp->vnode.hi);
			cb->fid.unique	= ntohl(bp->vnode.unique);
			bp++;
		}

		afs_extract_to_tmp(call);
		call->unmarshall++;

	case 3:
		break;
	}

	if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
		return afs_io_error(call, afs_io_error_cm_reply);

	/* We'll need the file server record as that tells us which set of
	 * vnodes to operate upon.
	 */
712
	return afs_find_cm_server_by_peer(call);
713
}