fsclient.c 47.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* AFS File Server client stubs
L
Linus Torvalds 已提交
3
 *
4
 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
L
Linus Torvalds 已提交
5 6 7 8
 * Written by David Howells (dhowells@redhat.com)
 */

#include <linux/init.h>
9
#include <linux/slab.h>
L
Linus Torvalds 已提交
10
#include <linux/sched.h>
11
#include <linux/circ_buf.h>
J
Jeff Layton 已提交
12
#include <linux/iversion.h>
L
Linus Torvalds 已提交
13
#include "internal.h"
14
#include "afs_fs.h"
D
David Howells 已提交
15
#include "xdr_fs.h"
16

17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * decode an AFSFid block
 */
static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
{
	const __be32 *bp = *_bp;

	fid->vid		= ntohl(*bp++);
	fid->vnode		= ntohl(*bp++);
	fid->unique		= ntohl(*bp++);
	*_bp = bp;
}

D
David Howells 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
/*
 * Dump a bad file status record.
 */
static void xdr_dump_bad(const __be32 *bp)
{
	__be32 x[4];
	int i;

	pr_notice("AFS XDR: Bad status record\n");
	for (i = 0; i < 5 * 4 * 4; i += 16) {
		memcpy(x, bp, 16);
		bp += 4;
		pr_notice("%03x: %08x %08x %08x %08x\n",
			  i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
	}

	memcpy(x, bp, 4);
	pr_notice("0x50: %08x\n", ntohl(x[0]));
}

D
David Howells 已提交
50 51 52
/*
 * decode an AFSFetchStatus block
 */
53 54 55
static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
				      struct afs_call *call,
				      struct afs_status_cb *scb)
D
David Howells 已提交
56 57
{
	const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
58
	struct afs_file_status *status = &scb->status;
59
	bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
60
	u64 data_version, size;
D
David Howells 已提交
61
	u32 type, abort_code;
62

63 64
	abort_code = ntohl(xdr->abort_code);

D
David Howells 已提交
65
	if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
66 67 68 69 70 71 72 73
		if (xdr->if_version == htonl(0) &&
		    abort_code != 0 &&
		    inline_error) {
			/* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
			 * whereby it doesn't set the interface version in the error
			 * case.
			 */
			status->abort_code = abort_code;
74
			scb->have_error = true;
75
			goto advance;
76 77
		}

D
David Howells 已提交
78 79 80
		pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
		goto bad;
	}
81

82 83
	if (abort_code != 0 && inline_error) {
		status->abort_code = abort_code;
84
		scb->have_error = true;
85
		goto advance;
86 87
	}

D
David Howells 已提交
88 89
	type = ntohl(xdr->type);
	switch (type) {
D
David Howells 已提交
90 91 92
	case AFS_FTYPE_FILE:
	case AFS_FTYPE_DIR:
	case AFS_FTYPE_SYMLINK:
D
David Howells 已提交
93
		status->type = type;
D
David Howells 已提交
94 95
		break;
	default:
D
David Howells 已提交
96
		goto bad;
D
David Howells 已提交
97 98
	}

99 100 101 102 103 104 105 106
	status->nlink		= ntohl(xdr->nlink);
	status->author		= ntohl(xdr->author);
	status->owner		= ntohl(xdr->owner);
	status->caller_access	= ntohl(xdr->caller_access); /* Ticket dependent */
	status->anon_access	= ntohl(xdr->anon_access);
	status->mode		= ntohl(xdr->mode) & S_IALLUGO;
	status->group		= ntohl(xdr->group);
	status->lock_count	= ntohl(xdr->lock_count);
D
David Howells 已提交
107

108 109 110 111
	status->mtime_client.tv_sec = ntohl(xdr->mtime_client);
	status->mtime_client.tv_nsec = 0;
	status->mtime_server.tv_sec = ntohl(xdr->mtime_server);
	status->mtime_server.tv_nsec = 0;
D
David Howells 已提交
112 113 114

	size  = (u64)ntohl(xdr->size_lo);
	size |= (u64)ntohl(xdr->size_hi) << 32;
115
	status->size = size;
D
David Howells 已提交
116 117 118

	data_version  = (u64)ntohl(xdr->data_version_lo);
	data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
119
	status->data_version = data_version;
120
	scb->have_status = true;
121
advance:
D
David Howells 已提交
122
	*_bp = (const void *)*_bp + sizeof(*xdr);
123
	return;
D
David Howells 已提交
124 125 126

bad:
	xdr_dump_bad(*_bp);
127
	afs_protocol_error(call, afs_eproto_bad_status);
128
	goto advance;
129 130
}

131 132 133 134 135
static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
{
	return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry;
}

136 137 138
static void xdr_decode_AFSCallBack(const __be32 **_bp,
				   struct afs_call *call,
				   struct afs_status_cb *scb)
139
{
140
	struct afs_callback *cb = &scb->callback;
141 142
	const __be32 *bp = *_bp;

143
	bp++; /* version */
144
	cb->expires_at	= xdr_decode_expiry(call, ntohl(*bp++));
145
	bp++; /* type */
146
	scb->have_cb	= true;
147 148 149
	*_bp = bp;
}

L
Linus Torvalds 已提交
150
/*
151
 * decode an AFSVolSync block
L
Linus Torvalds 已提交
152
 */
153 154
static void xdr_decode_AFSVolSync(const __be32 **_bp,
				  struct afs_volsync *volsync)
L
Linus Torvalds 已提交
155
{
156
	const __be32 *bp = *_bp;
157
	u32 creation;
L
Linus Torvalds 已提交
158

159
	creation = ntohl(*bp++);
160 161 162 163 164 165
	bp++; /* spare2 */
	bp++; /* spare3 */
	bp++; /* spare4 */
	bp++; /* spare5 */
	bp++; /* spare6 */
	*_bp = bp;
166 167 168

	if (volsync)
		volsync->creation = creation;
169
}
L
Linus Torvalds 已提交
170

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
/*
 * encode the requested attributes into an AFSStoreStatus block
 */
static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
{
	__be32 *bp = *_bp;
	u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;

	mask = 0;
	if (attr->ia_valid & ATTR_MTIME) {
		mask |= AFS_SET_MTIME;
		mtime = attr->ia_mtime.tv_sec;
	}

	if (attr->ia_valid & ATTR_UID) {
		mask |= AFS_SET_OWNER;
187
		owner = from_kuid(&init_user_ns, attr->ia_uid);
188 189 190 191
	}

	if (attr->ia_valid & ATTR_GID) {
		mask |= AFS_SET_GROUP;
192
		group = from_kgid(&init_user_ns, attr->ia_gid);
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
	}

	if (attr->ia_valid & ATTR_MODE) {
		mask |= AFS_SET_MODE;
		mode = attr->ia_mode & S_IALLUGO;
	}

	*bp++ = htonl(mask);
	*bp++ = htonl(mtime);
	*bp++ = htonl(owner);
	*bp++ = htonl(group);
	*bp++ = htonl(mode);
	*bp++ = 0;		/* segment size */
	*_bp = bp;
}

D
David Howells 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
/*
 * decode an AFSFetchVolumeStatus block
 */
static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
					    struct afs_volume_status *vs)
{
	const __be32 *bp = *_bp;

	vs->vid			= ntohl(*bp++);
	vs->parent_id		= ntohl(*bp++);
	vs->online		= ntohl(*bp++);
	vs->in_service		= ntohl(*bp++);
	vs->blessed		= ntohl(*bp++);
	vs->needs_salvage	= ntohl(*bp++);
	vs->type		= ntohl(*bp++);
	vs->min_quota		= ntohl(*bp++);
	vs->max_quota		= ntohl(*bp++);
	vs->blocks_in_use	= ntohl(*bp++);
	vs->part_blocks_avail	= ntohl(*bp++);
	vs->part_max_blocks	= ntohl(*bp++);
229 230
	vs->vol_copy_date	= 0;
	vs->vol_backup_date	= 0;
D
David Howells 已提交
231 232 233
	*_bp = bp;
}

234 235 236
/*
 * deliver reply data to an FS.FetchStatus
 */
237
static int afs_deliver_fs_fetch_status(struct afs_call *call)
238
{
239 240
	struct afs_operation *op = call->op;
	struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
241
	const __be32 *bp;
242
	int ret;
L
Linus Torvalds 已提交
243

244
	ret = afs_transfer_reply(call);
245 246
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
247

248 249
	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
250 251 252
	xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
	xdr_decode_AFSCallBack(&bp, call, &vp->scb);
	xdr_decode_AFSVolSync(&bp, &op->volsync);
L
Linus Torvalds 已提交
253

254 255
	_leave(" = 0 [done]");
	return 0;
D
David Howells 已提交
256
}
257 258 259 260

/*
 * FS.FetchStatus operation type
 */
261 262
static const struct afs_call_type afs_RXFSFetchStatus = {
	.name		= "FS.FetchStatus",
263
	.op		= afs_FS_FetchStatus,
264
	.deliver	= afs_deliver_fs_fetch_status,
265 266
	.destructor	= afs_flat_call_destructor,
};
L
Linus Torvalds 已提交
267 268 269 270

/*
 * fetch the status information for a file
 */
271
void afs_fs_fetch_status(struct afs_operation *op)
L
Linus Torvalds 已提交
272
{
273
	struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
274
	struct afs_call *call;
L
Linus Torvalds 已提交
275 276
	__be32 *bp;

277
	_enter(",%x,{%llx:%llu},,",
278
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
L
Linus Torvalds 已提交
279

280
	call = afs_alloc_flat_call(op->net, &afs_RXFSFetchStatus,
281
				   16, (21 + 3 + 6) * 4);
282 283
	if (!call)
		return afs_op_nomem(op);
L
Linus Torvalds 已提交
284 285

	/* marshall the parameters */
286
	bp = call->request;
L
Linus Torvalds 已提交
287
	bp[0] = htonl(FSFETCHSTATUS);
288 289 290
	bp[1] = htonl(vp->fid.vid);
	bp[2] = htonl(vp->fid.vnode);
	bp[3] = htonl(vp->fid.unique);
L
Linus Torvalds 已提交
291

292 293
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
294
}
L
Linus Torvalds 已提交
295 296

/*
297
 * deliver reply data to an FS.FetchData
L
Linus Torvalds 已提交
298
 */
299
static int afs_deliver_fs_fetch_data(struct afs_call *call)
L
Linus Torvalds 已提交
300
{
301 302 303
	struct afs_operation *op = call->op;
	struct afs_vnode_param *vp = &op->file[0];
	struct afs_read *req = op->fetch.req;
304
	const __be32 *bp;
L
Linus Torvalds 已提交
305 306
	int ret;

307 308 309
	_enter("{%u,%zu,%zu/%llu}",
	       call->unmarshall, call->iov_len, iov_iter_count(call->iter),
	       req->actual_len);
310 311 312

	switch (call->unmarshall) {
	case 0:
313
		req->actual_len = 0;
314
		call->unmarshall++;
315 316 317 318 319
		if (call->operation_ID == FSFETCHDATA64) {
			afs_extract_to_tmp64(call);
		} else {
			call->tmp_u = htonl(0);
			afs_extract_to_tmp(call);
D
David Howells 已提交
320
		}
321
		fallthrough;
322

323 324 325 326
		/* Extract the returned data length into
		 * ->actual_len.  This may indicate more or less data than was
		 * requested will be returned.
		 */
327
	case 1:
328
		_debug("extract data length");
329
		ret = afs_extract_data(call, true);
330 331
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
332

333
		req->actual_len = be64_to_cpu(call->tmp64);
334
		_debug("DATA length: %llu", req->actual_len);
335 336

		if (req->actual_len == 0)
337
			goto no_more_data;
338

339 340
		call->iter = req->iter;
		call->iov_len = min(req->actual_len, req->len);
341
		call->unmarshall++;
342
		fallthrough;
343

344
		/* extract the returned data */
345 346
	case 2:
		_debug("extract data %zu/%llu",
347
		       iov_iter_count(call->iter), req->actual_len);
348

349
		ret = afs_extract_data(call, true);
350 351
		if (ret < 0)
			return ret;
352

353
		call->iter = &call->def_iter;
354 355
		if (req->actual_len <= req->len)
			goto no_more_data;
356 357

		/* Discard any excess data the server gave us */
358
		afs_extract_discard(call, req->actual_len - req->len);
359
		call->unmarshall = 3;
360
		fallthrough;
361

362 363
	case 3:
		_debug("extract discard %zu/%llu",
364
		       iov_iter_count(call->iter), req->actual_len - req->len);
365 366

		ret = afs_extract_data(call, true);
367 368
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
369

370
	no_more_data:
371 372
		call->unmarshall = 4;
		afs_extract_to_buf(call, (21 + 3 + 6) * 4);
373
		fallthrough;
L
Linus Torvalds 已提交
374

375
		/* extract the metadata */
376 377
	case 4:
		ret = afs_extract_data(call, false);
378 379
		if (ret < 0)
			return ret;
380 381

		bp = call->buffer;
382 383 384
		xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
		xdr_decode_AFSCallBack(&bp, call, &vp->scb);
		xdr_decode_AFSVolSync(&bp, &op->volsync);
385

386 387
		req->data_version = vp->scb.status.data_version;
		req->file_size = vp->scb.status.size;
388

389
		call->unmarshall++;
L
Linus Torvalds 已提交
390

391
	case 5:
392
		break;
L
Linus Torvalds 已提交
393 394
	}

395 396
	if (req->done)
		req->done(req);
397

398 399
	_leave(" = 0 [done]");
	return 0;
D
David Howells 已提交
400
}
L
Linus Torvalds 已提交
401 402

/*
403
 * FS.FetchData operation type
L
Linus Torvalds 已提交
404
 */
405
static const struct afs_call_type afs_RXFSFetchData = {
D
David Howells 已提交
406
	.name		= "FS.FetchData",
407
	.op		= afs_FS_FetchData,
408
	.deliver	= afs_deliver_fs_fetch_data,
409
	.destructor	= afs_flat_call_destructor,
410 411
};

D
David Howells 已提交
412 413
static const struct afs_call_type afs_RXFSFetchData64 = {
	.name		= "FS.FetchData64",
414
	.op		= afs_FS_FetchData64,
D
David Howells 已提交
415
	.deliver	= afs_deliver_fs_fetch_data,
416
	.destructor	= afs_flat_call_destructor,
D
David Howells 已提交
417 418 419 420 421
};

/*
 * fetch data from a very large file
 */
422
static void afs_fs_fetch_data64(struct afs_operation *op)
D
David Howells 已提交
423
{
424 425
	struct afs_vnode_param *vp = &op->file[0];
	struct afs_read *req = op->fetch.req;
D
David Howells 已提交
426 427 428 429 430
	struct afs_call *call;
	__be32 *bp;

	_enter("");

431
	call = afs_alloc_flat_call(op->net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
D
David Howells 已提交
432
	if (!call)
433
		return afs_op_nomem(op);
D
David Howells 已提交
434 435 436 437

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSFETCHDATA64);
438 439 440
	bp[1] = htonl(vp->fid.vid);
	bp[2] = htonl(vp->fid.vnode);
	bp[3] = htonl(vp->fid.unique);
441 442
	bp[4] = htonl(upper_32_bits(req->pos));
	bp[5] = htonl(lower_32_bits(req->pos));
D
David Howells 已提交
443
	bp[6] = 0;
444
	bp[7] = htonl(lower_32_bits(req->len));
D
David Howells 已提交
445

446 447
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
448 449
}

450 451 452
/*
 * fetch data from a file
 */
453
void afs_fs_fetch_data(struct afs_operation *op)
L
Linus Torvalds 已提交
454
{
455
	struct afs_vnode_param *vp = &op->file[0];
456
	struct afs_call *call;
457
	struct afs_read *req = op->fetch.req;
L
Linus Torvalds 已提交
458 459
	__be32 *bp;

460 461 462
	if (upper_32_bits(req->pos) ||
	    upper_32_bits(req->len) ||
	    upper_32_bits(req->pos + req->len))
463
		return afs_fs_fetch_data64(op);
D
David Howells 已提交
464

465
	_enter("");
L
Linus Torvalds 已提交
466

467
	call = afs_alloc_flat_call(op->net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
468
	if (!call)
469
		return afs_op_nomem(op);
L
Linus Torvalds 已提交
470

471 472
	req->call_debug_id = call->debug_id;

L
Linus Torvalds 已提交
473
	/* marshall the parameters */
474 475
	bp = call->request;
	bp[0] = htonl(FSFETCHDATA);
476 477 478
	bp[1] = htonl(vp->fid.vid);
	bp[2] = htonl(vp->fid.vnode);
	bp[3] = htonl(vp->fid.unique);
479 480
	bp[4] = htonl(lower_32_bits(req->pos));
	bp[5] = htonl(lower_32_bits(req->len));
L
Linus Torvalds 已提交
481

482 483
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
484
}
485 486 487 488

/*
 * deliver reply data to an FS.CreateFile or an FS.MakeDir
 */
489
static int afs_deliver_fs_create_vnode(struct afs_call *call)
490
{
491 492 493
	struct afs_operation *op = call->op;
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_vnode_param *vp = &op->file[1];
494
	const __be32 *bp;
495
	int ret;
496

497
	ret = afs_transfer_reply(call);
498 499
	if (ret < 0)
		return ret;
500 501 502

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
503 504 505 506 507
	xdr_decode_AFSFid(&bp, &op->file[1].fid);
	xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
	xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
	xdr_decode_AFSCallBack(&bp, call, &vp->scb);
	xdr_decode_AFSVolSync(&bp, &op->volsync);
508 509 510 511 512 513 514 515

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.CreateFile and FS.MakeDir operation type
 */
516 517 518 519 520 521 522
static const struct afs_call_type afs_RXFSCreateFile = {
	.name		= "FS.CreateFile",
	.op		= afs_FS_CreateFile,
	.deliver	= afs_deliver_fs_create_vnode,
	.destructor	= afs_flat_call_destructor,
};

523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
/*
 * Create a file.
 */
void afs_fs_create_file(struct afs_operation *op)
{
	const struct qstr *name = &op->dentry->d_name;
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_call *call;
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	_enter("");

	namesz = name->len;
	padsz = (4 - (namesz & 3)) & 3;
	reqsz = (5 * 4) + namesz + padsz + (6 * 4);

	call = afs_alloc_flat_call(op->net, &afs_RXFSCreateFile,
				   reqsz, (3 + 21 + 21 + 3 + 6) * 4);
	if (!call)
		return afs_op_nomem(op);

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSCREATEFILE);
	*bp++ = htonl(dvp->fid.vid);
	*bp++ = htonl(dvp->fid.vnode);
	*bp++ = htonl(dvp->fid.unique);
	*bp++ = htonl(namesz);
	memcpy(bp, name->name, namesz);
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}
	*bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
	*bp++ = htonl(op->mtime.tv_sec); /* mtime */
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = htonl(op->create.mode & S_IALLUGO); /* unix mode */
	*bp++ = 0; /* segment size */

	trace_afs_make_fs_call1(call, &dvp->fid, name);
	afs_make_op_call(op, call, GFP_NOFS);
}

569 570 571
static const struct afs_call_type afs_RXFSMakeDir = {
	.name		= "FS.MakeDir",
	.op		= afs_FS_MakeDir,
572 573 574 575 576
	.deliver	= afs_deliver_fs_create_vnode,
	.destructor	= afs_flat_call_destructor,
};

/*
577
 * Create a new directory
578
 */
579
void afs_fs_make_dir(struct afs_operation *op)
580
{
581 582
	const struct qstr *name = &op->dentry->d_name;
	struct afs_vnode_param *dvp = &op->file[0];
583 584 585 586 587 588
	struct afs_call *call;
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	_enter("");

589
	namesz = name->len;
590 591 592
	padsz = (4 - (namesz & 3)) & 3;
	reqsz = (5 * 4) + namesz + padsz + (6 * 4);

593 594
	call = afs_alloc_flat_call(op->net, &afs_RXFSMakeDir,
				   reqsz, (3 + 21 + 21 + 3 + 6) * 4);
595
	if (!call)
596
		return afs_op_nomem(op);
597 598 599

	/* marshall the parameters */
	bp = call->request;
600 601 602 603
	*bp++ = htonl(FSMAKEDIR);
	*bp++ = htonl(dvp->fid.vid);
	*bp++ = htonl(dvp->fid.vnode);
	*bp++ = htonl(dvp->fid.unique);
604
	*bp++ = htonl(namesz);
605
	memcpy(bp, name->name, namesz);
606 607 608 609 610
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}
611
	*bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
612
	*bp++ = htonl(op->mtime.tv_sec); /* mtime */
613 614
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
615
	*bp++ = htonl(op->create.mode & S_IALLUGO); /* unix mode */
616 617
	*bp++ = 0; /* segment size */

618 619
	trace_afs_make_fs_call1(call, &dvp->fid, name);
	afs_make_op_call(op, call, GFP_NOFS);
620 621 622
}

/*
623
 * Deliver reply data to any operation that returns status and volume sync.
624
 */
625
static int afs_deliver_fs_file_status_and_vol(struct afs_call *call)
626
{
627 628
	struct afs_operation *op = call->op;
	struct afs_vnode_param *vp = &op->file[0];
629
	const __be32 *bp;
630
	int ret;
631

632
	ret = afs_transfer_reply(call);
633 634
	if (ret < 0)
		return ret;
635 636 637

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
638 639
	xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
	xdr_decode_AFSVolSync(&bp, &op->volsync);
640 641 642 643 644 645

	_leave(" = 0 [done]");
	return 0;
}

/*
646
 * FS.RemoveFile operation type
647
 */
648 649 650
static const struct afs_call_type afs_RXFSRemoveFile = {
	.name		= "FS.RemoveFile",
	.op		= afs_FS_RemoveFile,
651
	.deliver	= afs_deliver_fs_file_status_and_vol,
652 653 654
	.destructor	= afs_flat_call_destructor,
};

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
/*
 * Remove a file.
 */
void afs_fs_remove_file(struct afs_operation *op)
{
	const struct qstr *name = &op->dentry->d_name;
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_call *call;
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	_enter("");

	namesz = name->len;
	padsz = (4 - (namesz & 3)) & 3;
	reqsz = (5 * 4) + namesz + padsz;

	call = afs_alloc_flat_call(op->net, &afs_RXFSRemoveFile,
				   reqsz, (21 + 6) * 4);
	if (!call)
		return afs_op_nomem(op);

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSREMOVEFILE);
	*bp++ = htonl(dvp->fid.vid);
	*bp++ = htonl(dvp->fid.vnode);
	*bp++ = htonl(dvp->fid.unique);
	*bp++ = htonl(namesz);
	memcpy(bp, name->name, namesz);
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}

	trace_afs_make_fs_call1(call, &dvp->fid, name);
	afs_make_op_call(op, call, GFP_NOFS);
}

695 696 697
static const struct afs_call_type afs_RXFSRemoveDir = {
	.name		= "FS.RemoveDir",
	.op		= afs_FS_RemoveDir,
698
	.deliver	= afs_deliver_fs_file_status_and_vol,
699 700 701 702
	.destructor	= afs_flat_call_destructor,
};

/*
703
 * Remove a directory.
704
 */
705
void afs_fs_remove_dir(struct afs_operation *op)
706
{
707 708
	const struct qstr *name = &op->dentry->d_name;
	struct afs_vnode_param *dvp = &op->file[0];
709 710 711 712 713 714
	struct afs_call *call;
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	_enter("");

715
	namesz = name->len;
716 717 718
	padsz = (4 - (namesz & 3)) & 3;
	reqsz = (5 * 4) + namesz + padsz;

719 720
	call = afs_alloc_flat_call(op->net, &afs_RXFSRemoveDir,
				   reqsz, (21 + 6) * 4);
721
	if (!call)
722
		return afs_op_nomem(op);
723 724 725

	/* marshall the parameters */
	bp = call->request;
726 727 728 729
	*bp++ = htonl(FSREMOVEDIR);
	*bp++ = htonl(dvp->fid.vid);
	*bp++ = htonl(dvp->fid.vnode);
	*bp++ = htonl(dvp->fid.unique);
730
	*bp++ = htonl(namesz);
731
	memcpy(bp, name->name, namesz);
732 733 734 735 736 737
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}

738 739
	trace_afs_make_fs_call1(call, &dvp->fid, name);
	afs_make_op_call(op, call, GFP_NOFS);
740 741 742 743 744
}

/*
 * deliver reply data to an FS.Link
 */
745
static int afs_deliver_fs_link(struct afs_call *call)
746
{
747 748 749
	struct afs_operation *op = call->op;
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_vnode_param *vp = &op->file[1];
750
	const __be32 *bp;
751
	int ret;
752

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

755
	ret = afs_transfer_reply(call);
756 757
	if (ret < 0)
		return ret;
758 759 760

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
761 762 763
	xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
	xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
	xdr_decode_AFSVolSync(&bp, &op->volsync);
764 765 766 767 768 769 770 771 772 773

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.Link operation type
 */
static const struct afs_call_type afs_RXFSLink = {
	.name		= "FS.Link",
774
	.op		= afs_FS_Link,
775 776 777 778 779 780 781
	.deliver	= afs_deliver_fs_link,
	.destructor	= afs_flat_call_destructor,
};

/*
 * make a hard link
 */
782
void afs_fs_link(struct afs_operation *op)
783
{
784 785 786
	const struct qstr *name = &op->dentry->d_name;
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_vnode_param *vp = &op->file[1];
787 788 789 790 791 792
	struct afs_call *call;
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	_enter("");

793
	namesz = name->len;
794 795 796
	padsz = (4 - (namesz & 3)) & 3;
	reqsz = (5 * 4) + namesz + padsz + (3 * 4);

797
	call = afs_alloc_flat_call(op->net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
798
	if (!call)
799
		return afs_op_nomem(op);
800 801 802 803

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSLINK);
804 805 806
	*bp++ = htonl(dvp->fid.vid);
	*bp++ = htonl(dvp->fid.vnode);
	*bp++ = htonl(dvp->fid.unique);
807
	*bp++ = htonl(namesz);
808
	memcpy(bp, name->name, namesz);
809 810 811 812 813
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}
814 815 816 817 818 819
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);

	trace_afs_make_fs_call1(call, &vp->fid, name);
	afs_make_op_call(op, call, GFP_NOFS);
820 821 822 823 824
}

/*
 * deliver reply data to an FS.Symlink
 */
825
static int afs_deliver_fs_symlink(struct afs_call *call)
826
{
827 828 829
	struct afs_operation *op = call->op;
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_vnode_param *vp = &op->file[1];
830
	const __be32 *bp;
831
	int ret;
832

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

835
	ret = afs_transfer_reply(call);
836 837
	if (ret < 0)
		return ret;
838 839 840

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
841 842 843 844
	xdr_decode_AFSFid(&bp, &vp->fid);
	xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
	xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
	xdr_decode_AFSVolSync(&bp, &op->volsync);
845 846 847 848 849 850 851 852 853 854

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.Symlink operation type
 */
static const struct afs_call_type afs_RXFSSymlink = {
	.name		= "FS.Symlink",
855
	.op		= afs_FS_Symlink,
856 857 858 859 860 861 862
	.deliver	= afs_deliver_fs_symlink,
	.destructor	= afs_flat_call_destructor,
};

/*
 * create a symbolic link
 */
863
void afs_fs_symlink(struct afs_operation *op)
864
{
865 866
	const struct qstr *name = &op->dentry->d_name;
	struct afs_vnode_param *dvp = &op->file[0];
867 868 869 870 871 872
	struct afs_call *call;
	size_t namesz, reqsz, padsz, c_namesz, c_padsz;
	__be32 *bp;

	_enter("");

873
	namesz = name->len;
874 875
	padsz = (4 - (namesz & 3)) & 3;

876
	c_namesz = strlen(op->create.symlink);
877 878 879 880
	c_padsz = (4 - (c_namesz & 3)) & 3;

	reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);

881
	call = afs_alloc_flat_call(op->net, &afs_RXFSSymlink, reqsz,
882 883
				   (3 + 21 + 21 + 6) * 4);
	if (!call)
884
		return afs_op_nomem(op);
885 886 887 888

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSYMLINK);
889 890 891
	*bp++ = htonl(dvp->fid.vid);
	*bp++ = htonl(dvp->fid.vnode);
	*bp++ = htonl(dvp->fid.unique);
892
	*bp++ = htonl(namesz);
893
	memcpy(bp, name->name, namesz);
894 895 896 897 898 899
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}
	*bp++ = htonl(c_namesz);
900
	memcpy(bp, op->create.symlink, c_namesz);
901 902 903 904 905
	bp = (void *) bp + c_namesz;
	if (c_padsz > 0) {
		memset(bp, 0, c_padsz);
		bp = (void *) bp + c_padsz;
	}
906
	*bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
907
	*bp++ = htonl(op->mtime.tv_sec); /* mtime */
908 909 910 911 912
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = htonl(S_IRWXUGO); /* unix mode */
	*bp++ = 0; /* segment size */

913 914
	trace_afs_make_fs_call1(call, &dvp->fid, name);
	afs_make_op_call(op, call, GFP_NOFS);
915 916 917 918 919
}

/*
 * deliver reply data to an FS.Rename
 */
920
static int afs_deliver_fs_rename(struct afs_call *call)
921
{
922 923 924
	struct afs_operation *op = call->op;
	struct afs_vnode_param *orig_dvp = &op->file[0];
	struct afs_vnode_param *new_dvp = &op->file[1];
925
	const __be32 *bp;
926
	int ret;
927

928
	ret = afs_transfer_reply(call);
929 930
	if (ret < 0)
		return ret;
931

932
	bp = call->buffer;
933 934 935
	/* If the two dirs are the same, we have two copies of the same status
	 * report, so we just decode it twice.
	 */
936 937 938
	xdr_decode_AFSFetchStatus(&bp, call, &orig_dvp->scb);
	xdr_decode_AFSFetchStatus(&bp, call, &new_dvp->scb);
	xdr_decode_AFSVolSync(&bp, &op->volsync);
939 940 941 942 943 944 945 946 947 948

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.Rename operation type
 */
static const struct afs_call_type afs_RXFSRename = {
	.name		= "FS.Rename",
949
	.op		= afs_FS_Rename,
950 951 952 953 954
	.deliver	= afs_deliver_fs_rename,
	.destructor	= afs_flat_call_destructor,
};

/*
955
 * Rename/move a file or directory.
956
 */
957
void afs_fs_rename(struct afs_operation *op)
958
{
959 960 961 962
	struct afs_vnode_param *orig_dvp = &op->file[0];
	struct afs_vnode_param *new_dvp = &op->file[1];
	const struct qstr *orig_name = &op->dentry->d_name;
	const struct qstr *new_name = &op->dentry_2->d_name;
963 964 965 966 967 968
	struct afs_call *call;
	size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
	__be32 *bp;

	_enter("");

969
	o_namesz = orig_name->len;
970 971
	o_padsz = (4 - (o_namesz & 3)) & 3;

972
	n_namesz = new_name->len;
973 974 975 976 977 978 979
	n_padsz = (4 - (n_namesz & 3)) & 3;

	reqsz = (4 * 4) +
		4 + o_namesz + o_padsz +
		(3 * 4) +
		4 + n_namesz + n_padsz;

980
	call = afs_alloc_flat_call(op->net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
981
	if (!call)
982
		return afs_op_nomem(op);
983 984 985 986

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSRENAME);
987 988 989
	*bp++ = htonl(orig_dvp->fid.vid);
	*bp++ = htonl(orig_dvp->fid.vnode);
	*bp++ = htonl(orig_dvp->fid.unique);
990
	*bp++ = htonl(o_namesz);
991
	memcpy(bp, orig_name->name, o_namesz);
992 993 994 995 996 997
	bp = (void *) bp + o_namesz;
	if (o_padsz > 0) {
		memset(bp, 0, o_padsz);
		bp = (void *) bp + o_padsz;
	}

998 999 1000
	*bp++ = htonl(new_dvp->fid.vid);
	*bp++ = htonl(new_dvp->fid.vnode);
	*bp++ = htonl(new_dvp->fid.unique);
1001
	*bp++ = htonl(n_namesz);
1002
	memcpy(bp, new_name->name, n_namesz);
1003 1004 1005 1006 1007 1008
	bp = (void *) bp + n_namesz;
	if (n_padsz > 0) {
		memset(bp, 0, n_padsz);
		bp = (void *) bp + n_padsz;
	}

1009 1010
	trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name);
	afs_make_op_call(op, call, GFP_NOFS);
1011
}
1012 1013

/*
1014
 * Deliver reply data to FS.StoreData or FS.StoreStatus
1015
 */
1016
static int afs_deliver_fs_store_data(struct afs_call *call)
1017
{
1018 1019
	struct afs_operation *op = call->op;
	struct afs_vnode_param *vp = &op->file[0];
1020
	const __be32 *bp;
1021
	int ret;
1022

1023
	_enter("");
1024

1025
	ret = afs_transfer_reply(call);
1026 1027
	if (ret < 0)
		return ret;
1028 1029 1030

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
1031 1032
	xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
	xdr_decode_AFSVolSync(&bp, &op->volsync);
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.StoreData operation type
 */
static const struct afs_call_type afs_RXFSStoreData = {
	.name		= "FS.StoreData",
1043
	.op		= afs_FS_StoreData,
1044 1045 1046 1047
	.deliver	= afs_deliver_fs_store_data,
	.destructor	= afs_flat_call_destructor,
};

D
David Howells 已提交
1048 1049
static const struct afs_call_type afs_RXFSStoreData64 = {
	.name		= "FS.StoreData64",
1050
	.op		= afs_FS_StoreData64,
D
David Howells 已提交
1051 1052 1053 1054 1055 1056 1057
	.deliver	= afs_deliver_fs_store_data,
	.destructor	= afs_flat_call_destructor,
};

/*
 * store a set of pages to a very large file
 */
1058 1059
static void afs_fs_store_data64(struct afs_operation *op,
				loff_t pos, loff_t size, loff_t i_size)
D
David Howells 已提交
1060
{
1061
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
1062 1063 1064
	struct afs_call *call;
	__be32 *bp;

1065
	_enter(",%x,{%llx:%llu},,",
1066
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
D
David Howells 已提交
1067

1068
	call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData64,
D
David Howells 已提交
1069 1070 1071
				   (4 + 6 + 3 * 2) * 4,
				   (21 + 6) * 4);
	if (!call)
1072
		return afs_op_nomem(op);
D
David Howells 已提交
1073 1074 1075 1076 1077 1078

	call->send_pages = true;

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSTOREDATA64);
1079 1080 1081
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);
D
David Howells 已提交
1082

1083
	*bp++ = htonl(AFS_SET_MTIME); /* mask */
1084
	*bp++ = htonl(op->mtime.tv_sec); /* mtime */
D
David Howells 已提交
1085 1086 1087 1088 1089
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = 0; /* unix mode */
	*bp++ = 0; /* segment size */

1090 1091 1092 1093 1094 1095 1096 1097 1098
	*bp++ = htonl(upper_32_bits(pos));
	*bp++ = htonl(lower_32_bits(pos));
	*bp++ = htonl(upper_32_bits(size));
	*bp++ = htonl(lower_32_bits(size));
	*bp++ = htonl(upper_32_bits(i_size));
	*bp++ = htonl(lower_32_bits(i_size));

	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
1099 1100
}

1101 1102 1103
/*
 * store a set of pages
 */
1104
void afs_fs_store_data(struct afs_operation *op)
1105
{
1106
	struct afs_vnode_param *vp = &op->file[0];
1107 1108 1109 1110
	struct afs_call *call;
	loff_t size, pos, i_size;
	__be32 *bp;

1111
	_enter(",%x,{%llx:%llu},,",
1112
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
1113

1114 1115 1116 1117 1118
	size = (loff_t)op->store.last_to - (loff_t)op->store.first_offset;
	if (op->store.first != op->store.last)
		size += (loff_t)(op->store.last - op->store.first) << PAGE_SHIFT;
	pos = (loff_t)op->store.first << PAGE_SHIFT;
	pos += op->store.first_offset;
1119

1120
	i_size = i_size_read(&vp->vnode->vfs_inode);
1121 1122 1123 1124 1125 1126 1127
	if (pos + size > i_size)
		i_size = size + pos;

	_debug("size %llx, at %llx, i_size %llx",
	       (unsigned long long) size, (unsigned long long) pos,
	       (unsigned long long) i_size);

1128 1129 1130
	if (upper_32_bits(pos) || upper_32_bits(i_size) || upper_32_bits(size) ||
	    upper_32_bits(pos + size))
		return afs_fs_store_data64(op, pos, size, i_size);
1131

1132
	call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData,
1133 1134 1135
				   (4 + 6 + 3) * 4,
				   (21 + 6) * 4);
	if (!call)
1136
		return afs_op_nomem(op);
1137 1138 1139 1140 1141 1142

	call->send_pages = true;

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSTOREDATA);
1143 1144 1145
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);
1146

1147
	*bp++ = htonl(AFS_SET_MTIME); /* mask */
1148
	*bp++ = htonl(op->mtime.tv_sec); /* mtime */
1149 1150 1151 1152 1153
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = 0; /* unix mode */
	*bp++ = 0; /* segment size */

1154 1155 1156
	*bp++ = htonl(lower_32_bits(pos));
	*bp++ = htonl(lower_32_bits(size));
	*bp++ = htonl(lower_32_bits(i_size));
1157

1158 1159
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
1160 1161 1162 1163 1164 1165 1166
}

/*
 * FS.StoreStatus operation type
 */
static const struct afs_call_type afs_RXFSStoreStatus = {
	.name		= "FS.StoreStatus",
1167
	.op		= afs_FS_StoreStatus,
1168
	.deliver	= afs_deliver_fs_store_data,
1169 1170 1171 1172 1173
	.destructor	= afs_flat_call_destructor,
};

static const struct afs_call_type afs_RXFSStoreData_as_Status = {
	.name		= "FS.StoreData",
1174
	.op		= afs_FS_StoreData,
1175
	.deliver	= afs_deliver_fs_store_data,
1176 1177 1178
	.destructor	= afs_flat_call_destructor,
};

D
David Howells 已提交
1179 1180
static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
	.name		= "FS.StoreData64",
1181
	.op		= afs_FS_StoreData64,
1182
	.deliver	= afs_deliver_fs_store_data,
D
David Howells 已提交
1183 1184 1185 1186 1187 1188 1189
	.destructor	= afs_flat_call_destructor,
};

/*
 * set the attributes on a very large file, using FS.StoreData rather than
 * FS.StoreStatus so as to alter the file size also
 */
1190
static void afs_fs_setattr_size64(struct afs_operation *op)
D
David Howells 已提交
1191
{
1192
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
1193
	struct afs_call *call;
1194
	struct iattr *attr = op->setattr.attr;
D
David Howells 已提交
1195 1196
	__be32 *bp;

1197
	_enter(",%x,{%llx:%llu},,",
1198
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
D
David Howells 已提交
1199 1200 1201

	ASSERT(attr->ia_valid & ATTR_SIZE);

1202
	call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData64_as_Status,
D
David Howells 已提交
1203 1204 1205
				   (4 + 6 + 3 * 2) * 4,
				   (21 + 6) * 4);
	if (!call)
1206
		return afs_op_nomem(op);
D
David Howells 已提交
1207 1208 1209 1210

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSTOREDATA64);
1211 1212 1213
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);
D
David Howells 已提交
1214 1215 1216

	xdr_encode_AFS_StoreStatus(&bp, attr);

1217 1218 1219
	*bp++ = htonl(upper_32_bits(attr->ia_size));	/* position of start of write */
	*bp++ = htonl(lower_32_bits(attr->ia_size));
	*bp++ = 0;					/* size of write */
D
David Howells 已提交
1220
	*bp++ = 0;
1221 1222 1223 1224 1225
	*bp++ = htonl(upper_32_bits(attr->ia_size));	/* new file length */
	*bp++ = htonl(lower_32_bits(attr->ia_size));

	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
1226 1227
}

1228 1229 1230 1231
/*
 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
 * so as to alter the file size also
 */
1232
static void afs_fs_setattr_size(struct afs_operation *op)
1233
{
1234
	struct afs_vnode_param *vp = &op->file[0];
1235
	struct afs_call *call;
1236
	struct iattr *attr = op->setattr.attr;
1237 1238
	__be32 *bp;

1239
	_enter(",%x,{%llx:%llu},,",
1240
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
1241 1242

	ASSERT(attr->ia_valid & ATTR_SIZE);
1243 1244
	if (upper_32_bits(attr->ia_size))
		return afs_fs_setattr_size64(op);
1245

1246
	call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData_as_Status,
1247 1248 1249
				   (4 + 6 + 3) * 4,
				   (21 + 6) * 4);
	if (!call)
1250
		return afs_op_nomem(op);
1251 1252 1253 1254

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSTOREDATA);
1255 1256 1257
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);
1258 1259 1260

	xdr_encode_AFS_StoreStatus(&bp, attr);

1261
	*bp++ = htonl(attr->ia_size);		/* position of start of write */
1262 1263 1264
	*bp++ = 0;				/* size of write */
	*bp++ = htonl(attr->ia_size);		/* new file length */

1265 1266
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
1267 1268 1269 1270 1271 1272
}

/*
 * set the attributes on a file, using FS.StoreData if there's a change in file
 * size, and FS.StoreStatus otherwise
 */
1273
void afs_fs_setattr(struct afs_operation *op)
1274
{
1275
	struct afs_vnode_param *vp = &op->file[0];
1276
	struct afs_call *call;
1277
	struct iattr *attr = op->setattr.attr;
1278 1279 1280
	__be32 *bp;

	if (attr->ia_valid & ATTR_SIZE)
1281
		return afs_fs_setattr_size(op);
1282

1283
	_enter(",%x,{%llx:%llu},,",
1284
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
1285

1286
	call = afs_alloc_flat_call(op->net, &afs_RXFSStoreStatus,
1287 1288 1289
				   (4 + 6) * 4,
				   (21 + 6) * 4);
	if (!call)
1290
		return afs_op_nomem(op);
1291 1292 1293 1294

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSTORESTATUS);
1295 1296 1297
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);
1298

1299
	xdr_encode_AFS_StoreStatus(&bp, op->setattr.attr);
1300

1301 1302
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
1303
}
D
David Howells 已提交
1304 1305 1306 1307

/*
 * deliver reply data to an FS.GetVolumeStatus
 */
1308
static int afs_deliver_fs_get_volume_status(struct afs_call *call)
D
David Howells 已提交
1309
{
1310
	struct afs_operation *op = call->op;
D
David Howells 已提交
1311 1312
	const __be32 *bp;
	char *p;
1313
	u32 size;
D
David Howells 已提交
1314 1315
	int ret;

1316
	_enter("{%u}", call->unmarshall);
D
David Howells 已提交
1317 1318 1319 1320

	switch (call->unmarshall) {
	case 0:
		call->unmarshall++;
1321
		afs_extract_to_buf(call, 12 * 4);
1322
		fallthrough;
D
David Howells 已提交
1323

1324
		/* extract the returned status record */
D
David Howells 已提交
1325 1326
	case 1:
		_debug("extract status");
1327
		ret = afs_extract_data(call, true);
1328 1329
		if (ret < 0)
			return ret;
D
David Howells 已提交
1330 1331

		bp = call->buffer;
1332
		xdr_decode_AFSFetchVolumeStatus(&bp, &op->volstatus.vs);
D
David Howells 已提交
1333
		call->unmarshall++;
1334
		afs_extract_to_tmp(call);
1335
		fallthrough;
D
David Howells 已提交
1336

1337
		/* extract the volume name length */
D
David Howells 已提交
1338
	case 2:
1339
		ret = afs_extract_data(call, true);
1340 1341
		if (ret < 0)
			return ret;
D
David Howells 已提交
1342 1343 1344 1345

		call->count = ntohl(call->tmp);
		_debug("volname length: %u", call->count);
		if (call->count >= AFSNAMEMAX)
1346
			return afs_protocol_error(call, afs_eproto_volname_len);
1347
		size = (call->count + 3) & ~3; /* It's padded */
1348
		afs_extract_to_buf(call, size);
D
David Howells 已提交
1349
		call->unmarshall++;
1350
		fallthrough;
D
David Howells 已提交
1351

1352
		/* extract the volume name */
D
David Howells 已提交
1353 1354
	case 3:
		_debug("extract volname");
1355 1356 1357
		ret = afs_extract_data(call, true);
		if (ret < 0)
			return ret;
D
David Howells 已提交
1358

1359
		p = call->buffer;
D
David Howells 已提交
1360 1361
		p[call->count] = 0;
		_debug("volname '%s'", p);
1362
		afs_extract_to_tmp(call);
D
David Howells 已提交
1363
		call->unmarshall++;
1364
		fallthrough;
D
David Howells 已提交
1365

1366
		/* extract the offline message length */
1367 1368
	case 4:
		ret = afs_extract_data(call, true);
1369 1370
		if (ret < 0)
			return ret;
D
David Howells 已提交
1371 1372 1373 1374

		call->count = ntohl(call->tmp);
		_debug("offline msg length: %u", call->count);
		if (call->count >= AFSNAMEMAX)
1375
			return afs_protocol_error(call, afs_eproto_offline_msg_len);
1376
		size = (call->count + 3) & ~3; /* It's padded */
1377
		afs_extract_to_buf(call, size);
D
David Howells 已提交
1378
		call->unmarshall++;
1379
		fallthrough;
D
David Howells 已提交
1380

1381
		/* extract the offline message */
1382
	case 5:
D
David Howells 已提交
1383
		_debug("extract offline");
1384 1385 1386
		ret = afs_extract_data(call, true);
		if (ret < 0)
			return ret;
D
David Howells 已提交
1387

1388
		p = call->buffer;
D
David Howells 已提交
1389 1390 1391
		p[call->count] = 0;
		_debug("offline '%s'", p);

1392
		afs_extract_to_tmp(call);
D
David Howells 已提交
1393
		call->unmarshall++;
1394
		fallthrough;
D
David Howells 已提交
1395

1396
		/* extract the message of the day length */
1397 1398
	case 6:
		ret = afs_extract_data(call, true);
1399 1400
		if (ret < 0)
			return ret;
D
David Howells 已提交
1401 1402 1403 1404

		call->count = ntohl(call->tmp);
		_debug("motd length: %u", call->count);
		if (call->count >= AFSNAMEMAX)
1405
			return afs_protocol_error(call, afs_eproto_motd_len);
1406
		size = (call->count + 3) & ~3; /* It's padded */
1407
		afs_extract_to_buf(call, size);
D
David Howells 已提交
1408
		call->unmarshall++;
1409
		fallthrough;
D
David Howells 已提交
1410

1411
		/* extract the message of the day */
1412
	case 7:
D
David Howells 已提交
1413
		_debug("extract motd");
1414 1415 1416
		ret = afs_extract_data(call, false);
		if (ret < 0)
			return ret;
D
David Howells 已提交
1417

1418
		p = call->buffer;
D
David Howells 已提交
1419 1420 1421 1422 1423
		p[call->count] = 0;
		_debug("motd '%s'", p);

		call->unmarshall++;

1424
	case 8:
D
David Howells 已提交
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
		break;
	}

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.GetVolumeStatus operation type
 */
static const struct afs_call_type afs_RXFSGetVolumeStatus = {
	.name		= "FS.GetVolumeStatus",
1437
	.op		= afs_FS_GetVolumeStatus,
D
David Howells 已提交
1438
	.deliver	= afs_deliver_fs_get_volume_status,
1439
	.destructor	= afs_flat_call_destructor,
D
David Howells 已提交
1440 1441 1442 1443 1444
};

/*
 * fetch the status of a volume
 */
1445
void afs_fs_get_volume_status(struct afs_operation *op)
D
David Howells 已提交
1446
{
1447
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
1448 1449 1450 1451 1452
	struct afs_call *call;
	__be32 *bp;

	_enter("");

1453
	call = afs_alloc_flat_call(op->net, &afs_RXFSGetVolumeStatus, 2 * 4,
1454 1455
				   max(12 * 4, AFSOPAQUEMAX + 1));
	if (!call)
1456
		return afs_op_nomem(op);
D
David Howells 已提交
1457 1458 1459 1460

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSGETVOLUMESTATUS);
1461
	bp[1] = htonl(vp->fid.vid);
D
David Howells 已提交
1462

1463 1464
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
1465
}
D
David Howells 已提交
1466 1467 1468 1469

/*
 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
 */
1470
static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
D
David Howells 已提交
1471
{
1472
	struct afs_operation *op = call->op;
D
David Howells 已提交
1473
	const __be32 *bp;
1474
	int ret;
D
David Howells 已提交
1475

1476
	_enter("{%u}", call->unmarshall);
D
David Howells 已提交
1477

1478
	ret = afs_transfer_reply(call);
1479 1480
	if (ret < 0)
		return ret;
D
David Howells 已提交
1481 1482 1483

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
1484
	xdr_decode_AFSVolSync(&bp, &op->volsync);
D
David Howells 已提交
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.SetLock operation type
 */
static const struct afs_call_type afs_RXFSSetLock = {
	.name		= "FS.SetLock",
1495
	.op		= afs_FS_SetLock,
D
David Howells 已提交
1496
	.deliver	= afs_deliver_fs_xxxx_lock,
1497
	.done		= afs_lock_op_done,
D
David Howells 已提交
1498 1499 1500 1501 1502 1503 1504 1505
	.destructor	= afs_flat_call_destructor,
};

/*
 * FS.ExtendLock operation type
 */
static const struct afs_call_type afs_RXFSExtendLock = {
	.name		= "FS.ExtendLock",
1506
	.op		= afs_FS_ExtendLock,
D
David Howells 已提交
1507
	.deliver	= afs_deliver_fs_xxxx_lock,
1508
	.done		= afs_lock_op_done,
D
David Howells 已提交
1509 1510 1511 1512 1513 1514 1515 1516
	.destructor	= afs_flat_call_destructor,
};

/*
 * FS.ReleaseLock operation type
 */
static const struct afs_call_type afs_RXFSReleaseLock = {
	.name		= "FS.ReleaseLock",
1517
	.op		= afs_FS_ReleaseLock,
D
David Howells 已提交
1518 1519 1520 1521 1522
	.deliver	= afs_deliver_fs_xxxx_lock,
	.destructor	= afs_flat_call_destructor,
};

/*
1523
 * Set a lock on a file
D
David Howells 已提交
1524
 */
1525
void afs_fs_set_lock(struct afs_operation *op)
D
David Howells 已提交
1526
{
1527
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
1528 1529 1530 1531 1532
	struct afs_call *call;
	__be32 *bp;

	_enter("");

1533
	call = afs_alloc_flat_call(op->net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
D
David Howells 已提交
1534
	if (!call)
1535
		return afs_op_nomem(op);
D
David Howells 已提交
1536 1537 1538 1539

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSETLOCK);
1540 1541 1542 1543 1544 1545 1546
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);
	*bp++ = htonl(op->lock.type);

	trace_afs_make_fs_calli(call, &vp->fid, op->lock.type);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
1547 1548 1549 1550 1551
}

/*
 * extend a lock on a file
 */
1552
void afs_fs_extend_lock(struct afs_operation *op)
D
David Howells 已提交
1553
{
1554
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
1555 1556 1557 1558 1559
	struct afs_call *call;
	__be32 *bp;

	_enter("");

1560
	call = afs_alloc_flat_call(op->net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
D
David Howells 已提交
1561
	if (!call)
1562
		return afs_op_nomem(op);
D
David Howells 已提交
1563 1564 1565 1566

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSEXTENDLOCK);
1567 1568 1569 1570 1571 1572
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);

	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
D
David Howells 已提交
1573 1574 1575 1576 1577
}

/*
 * release a lock on a file
 */
1578
void afs_fs_release_lock(struct afs_operation *op)
D
David Howells 已提交
1579
{
1580
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
1581 1582 1583 1584 1585
	struct afs_call *call;
	__be32 *bp;

	_enter("");

1586
	call = afs_alloc_flat_call(op->net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
D
David Howells 已提交
1587
	if (!call)
1588
		return afs_op_nomem(op);
D
David Howells 已提交
1589 1590 1591 1592

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSRELEASELOCK);
1593 1594 1595 1596 1597 1598
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);

	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
}

/*
 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
 */
static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
{
	return afs_transfer_reply(call);
}

/*
 * FS.GiveUpAllCallBacks operation type
 */
static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
	.name		= "FS.GiveUpAllCallBacks",
1614
	.op		= afs_FS_GiveUpAllCallBacks,
1615 1616 1617 1618 1619 1620 1621
	.deliver	= afs_deliver_fs_give_up_all_callbacks,
	.destructor	= afs_flat_call_destructor,
};

/*
 * Flush all the callbacks we have on a server.
 */
1622 1623
int afs_fs_give_up_all_callbacks(struct afs_net *net,
				 struct afs_server *server,
D
David Howells 已提交
1624
				 struct afs_addr_cursor *ac,
1625
				 struct key *key)
1626 1627 1628 1629 1630 1631
{
	struct afs_call *call;
	__be32 *bp;

	_enter("");

1632
	call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
1633 1634 1635 1636 1637 1638 1639 1640 1641
	if (!call)
		return -ENOMEM;

	call->key = key;

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSGIVEUPALLCALLBACKS);

1642
	call->server = afs_use_server(server, afs_server_trace_give_up_cb);
1643 1644
	afs_make_call(ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, ac);
1645 1646 1647 1648 1649 1650 1651 1652 1653 1654
}

/*
 * Deliver reply data to an FS.GetCapabilities operation.
 */
static int afs_deliver_fs_get_capabilities(struct afs_call *call)
{
	u32 count;
	int ret;

1655
	_enter("{%u,%zu}", call->unmarshall, iov_iter_count(call->iter));
1656 1657 1658

	switch (call->unmarshall) {
	case 0:
1659
		afs_extract_to_tmp(call);
1660
		call->unmarshall++;
1661
		fallthrough;
1662

1663
		/* Extract the capabilities word count */
1664
	case 1:
1665
		ret = afs_extract_data(call, true);
1666 1667 1668 1669 1670 1671 1672
		if (ret < 0)
			return ret;

		count = ntohl(call->tmp);

		call->count = count;
		call->count2 = count;
1673
		afs_extract_discard(call, count * sizeof(__be32));
1674
		call->unmarshall++;
1675
		fallthrough;
1676

1677
		/* Extract capabilities words */
1678
	case 2:
1679
		ret = afs_extract_data(call, false);
1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
		if (ret < 0)
			return ret;

		/* TODO: Examine capabilities */

		call->unmarshall++;
		break;
	}

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.GetCapabilities operation type
 */
static const struct afs_call_type afs_RXFSGetCapabilities = {
	.name		= "FS.GetCapabilities",
1698
	.op		= afs_FS_GetCapabilities,
1699
	.deliver	= afs_deliver_fs_get_capabilities,
1700
	.done		= afs_fileserver_probe_result,
1701
	.destructor	= afs_flat_call_destructor,
1702 1703 1704
};

/*
1705 1706 1707 1708
 * Probe a fileserver for the capabilities that it supports.  This RPC can
 * reply with up to 196 words.  The operation is asynchronous and if we managed
 * to allocate a call, true is returned the result is delivered through the
 * ->done() - otherwise we return false to indicate we didn't even try.
1709
 */
1710 1711
bool afs_fs_get_capabilities(struct afs_net *net, struct afs_server *server,
			     struct afs_addr_cursor *ac, struct key *key)
1712 1713 1714 1715 1716 1717 1718 1719
{
	struct afs_call *call;
	__be32 *bp;

	_enter("");

	call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
	if (!call)
1720
		return false;
1721 1722

	call->key = key;
1723
	call->server = afs_use_server(server, afs_server_trace_get_caps);
1724
	call->upgrade = true;
1725
	call->async = true;
1726
	call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
1727 1728 1729 1730 1731

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSGETCAPABILITIES);

1732
	trace_afs_make_fs_call(call, NULL);
1733
	afs_make_call(ac, call, GFP_NOFS);
1734 1735
	afs_put_call(call);
	return true;
D
David Howells 已提交
1736
}
1737 1738 1739 1740 1741 1742

/*
 * Deliver reply data to an FS.InlineBulkStatus call
 */
static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
{
1743
	struct afs_operation *op = call->op;
1744
	struct afs_status_cb *scb;
1745 1746 1747 1748 1749 1750 1751 1752
	const __be32 *bp;
	u32 tmp;
	int ret;

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

	switch (call->unmarshall) {
	case 0:
1753
		afs_extract_to_tmp(call);
1754
		call->unmarshall++;
1755
		fallthrough;
1756 1757 1758 1759

		/* Extract the file status count and array in two steps */
	case 1:
		_debug("extract status count");
1760
		ret = afs_extract_data(call, true);
1761 1762 1763 1764
		if (ret < 0)
			return ret;

		tmp = ntohl(call->tmp);
1765 1766
		_debug("status count: %u/%u", tmp, op->nr_files);
		if (tmp != op->nr_files)
1767
			return afs_protocol_error(call, afs_eproto_ibulkst_count);
1768 1769 1770 1771

		call->count = 0;
		call->unmarshall++;
	more_counts:
1772
		afs_extract_to_buf(call, 21 * sizeof(__be32));
1773
		fallthrough;
1774

1775 1776
	case 2:
		_debug("extract status array %u", call->count);
1777
		ret = afs_extract_data(call, true);
1778 1779 1780
		if (ret < 0)
			return ret;

1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792
		switch (call->count) {
		case 0:
			scb = &op->file[0].scb;
			break;
		case 1:
			scb = &op->file[1].scb;
			break;
		default:
			scb = &op->more_files[call->count - 2].scb;
			break;
		}

1793
		bp = call->buffer;
1794
		xdr_decode_AFSFetchStatus(&bp, call, scb);
1795

1796
		call->count++;
1797
		if (call->count < op->nr_files)
1798 1799 1800 1801
			goto more_counts;

		call->count = 0;
		call->unmarshall++;
1802
		afs_extract_to_tmp(call);
1803
		fallthrough;
1804 1805 1806 1807

		/* Extract the callback count and array in two steps */
	case 3:
		_debug("extract CB count");
1808
		ret = afs_extract_data(call, true);
1809 1810 1811 1812 1813
		if (ret < 0)
			return ret;

		tmp = ntohl(call->tmp);
		_debug("CB count: %u", tmp);
1814
		if (tmp != op->nr_files)
1815
			return afs_protocol_error(call, afs_eproto_ibulkst_cb_count);
1816 1817 1818
		call->count = 0;
		call->unmarshall++;
	more_cbs:
1819
		afs_extract_to_buf(call, 3 * sizeof(__be32));
1820
		fallthrough;
1821

1822 1823
	case 4:
		_debug("extract CB array");
1824
		ret = afs_extract_data(call, true);
1825 1826 1827 1828
		if (ret < 0)
			return ret;

		_debug("unmarshall CB array");
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840
		switch (call->count) {
		case 0:
			scb = &op->file[0].scb;
			break;
		case 1:
			scb = &op->file[1].scb;
			break;
		default:
			scb = &op->more_files[call->count - 2].scb;
			break;
		}

1841
		bp = call->buffer;
1842
		xdr_decode_AFSCallBack(&bp, call, scb);
1843
		call->count++;
1844
		if (call->count < op->nr_files)
1845 1846
			goto more_cbs;

1847
		afs_extract_to_buf(call, 6 * sizeof(__be32));
1848
		call->unmarshall++;
1849
		fallthrough;
1850

1851
	case 5:
1852
		ret = afs_extract_data(call, false);
1853 1854 1855 1856
		if (ret < 0)
			return ret;

		bp = call->buffer;
1857
		xdr_decode_AFSVolSync(&bp, &op->volsync);
1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868

		call->unmarshall++;

	case 6:
		break;
	}

	_leave(" = 0 [done]");
	return 0;
}

1869 1870 1871
static void afs_done_fs_inline_bulk_status(struct afs_call *call)
{
	if (call->error == -ECONNABORTED &&
1872
	    call->abort_code == RX_INVALID_OPERATION) {
1873
		set_bit(AFS_SERVER_FL_NO_IBULK, &call->server->flags);
1874 1875 1876
		if (call->op)
			set_bit(AFS_VOLUME_MAYBE_NO_IBULK, &call->op->volume->flags);
	}
1877 1878
}

1879 1880 1881 1882 1883 1884 1885
/*
 * FS.InlineBulkStatus operation type
 */
static const struct afs_call_type afs_RXFSInlineBulkStatus = {
	.name		= "FS.InlineBulkStatus",
	.op		= afs_FS_InlineBulkStatus,
	.deliver	= afs_deliver_fs_inline_bulk_status,
1886
	.done		= afs_done_fs_inline_bulk_status,
1887 1888 1889 1890 1891 1892
	.destructor	= afs_flat_call_destructor,
};

/*
 * Fetch the status information for up to 50 files
 */
1893
void afs_fs_inline_bulk_status(struct afs_operation *op)
1894
{
1895 1896
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_vnode_param *vp = &op->file[1];
1897 1898 1899 1900
	struct afs_call *call;
	__be32 *bp;
	int i;

1901
	if (test_bit(AFS_SERVER_FL_NO_IBULK, &op->server->flags)) {
1902 1903 1904
		op->error = -ENOTSUPP;
		return;
	}
1905

1906
	_enter(",%x,{%llx:%llu},%u",
1907
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode, op->nr_files);
1908

1909 1910
	call = afs_alloc_flat_call(op->net, &afs_RXFSInlineBulkStatus,
				   (2 + op->nr_files * 3) * 4,
1911
				   21 * 4);
1912 1913
	if (!call)
		return afs_op_nomem(op);
1914 1915 1916 1917

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSINLINEBULKSTATUS);
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928
	*bp++ = htonl(op->nr_files);
	*bp++ = htonl(dvp->fid.vid);
	*bp++ = htonl(dvp->fid.vnode);
	*bp++ = htonl(dvp->fid.unique);
	*bp++ = htonl(vp->fid.vid);
	*bp++ = htonl(vp->fid.vnode);
	*bp++ = htonl(vp->fid.unique);
	for (i = 0; i < op->nr_files - 2; i++) {
		*bp++ = htonl(op->more_files[i].fid.vid);
		*bp++ = htonl(op->more_files[i].fid.vnode);
		*bp++ = htonl(op->more_files[i].fid.unique);
1929 1930
	}

1931 1932
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_NOFS);
1933
}
D
David Howells 已提交
1934 1935 1936 1937 1938 1939

/*
 * deliver reply data to an FS.FetchACL
 */
static int afs_deliver_fs_fetch_acl(struct afs_call *call)
{
1940 1941
	struct afs_operation *op = call->op;
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952
	struct afs_acl *acl;
	const __be32 *bp;
	unsigned int size;
	int ret;

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

	switch (call->unmarshall) {
	case 0:
		afs_extract_to_tmp(call);
		call->unmarshall++;
1953
		fallthrough;
D
David Howells 已提交
1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966

		/* extract the returned data length */
	case 1:
		ret = afs_extract_data(call, true);
		if (ret < 0)
			return ret;

		size = call->count2 = ntohl(call->tmp);
		size = round_up(size, 4);

		acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
		if (!acl)
			return -ENOMEM;
1967
		op->acl = acl;
D
David Howells 已提交
1968 1969 1970
		acl->size = call->count2;
		afs_extract_begin(call, acl->data, size);
		call->unmarshall++;
1971
		fallthrough;
D
David Howells 已提交
1972 1973 1974 1975 1976 1977 1978 1979 1980

		/* extract the returned data */
	case 2:
		ret = afs_extract_data(call, true);
		if (ret < 0)
			return ret;

		afs_extract_to_buf(call, (21 + 6) * 4);
		call->unmarshall++;
1981
		fallthrough;
D
David Howells 已提交
1982 1983 1984 1985 1986 1987 1988 1989

		/* extract the metadata */
	case 3:
		ret = afs_extract_data(call, false);
		if (ret < 0)
			return ret;

		bp = call->buffer;
1990 1991
		xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
		xdr_decode_AFSVolSync(&bp, &op->volsync);
D
David Howells 已提交
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014

		call->unmarshall++;

	case 4:
		break;
	}

	_leave(" = 0 [done]");
	return 0;
}

/*
 * FS.FetchACL operation type
 */
static const struct afs_call_type afs_RXFSFetchACL = {
	.name		= "FS.FetchACL",
	.op		= afs_FS_FetchACL,
	.deliver	= afs_deliver_fs_fetch_acl,
};

/*
 * Fetch the ACL for a file.
 */
2015
void afs_fs_fetch_acl(struct afs_operation *op)
D
David Howells 已提交
2016
{
2017
	struct afs_vnode_param *vp = &op->file[0];
D
David Howells 已提交
2018 2019 2020 2021
	struct afs_call *call;
	__be32 *bp;

	_enter(",%x,{%llx:%llu},,",
2022
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
D
David Howells 已提交
2023

2024 2025 2026
	call = afs_alloc_flat_call(op->net, &afs_RXFSFetchACL, 16, (21 + 6) * 4);
	if (!call)
		return afs_op_nomem(op);
D
David Howells 已提交
2027 2028 2029 2030

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSFETCHACL);
2031 2032 2033
	bp[1] = htonl(vp->fid.vid);
	bp[2] = htonl(vp->fid.vnode);
	bp[3] = htonl(vp->fid.unique);
J
Joe Gorse 已提交
2034

2035 2036
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_KERNEL);
2037 2038
}

J
Joe Gorse 已提交
2039 2040 2041 2042 2043 2044
/*
 * FS.StoreACL operation type
 */
static const struct afs_call_type afs_RXFSStoreACL = {
	.name		= "FS.StoreACL",
	.op		= afs_FS_StoreACL,
2045
	.deliver	= afs_deliver_fs_file_status_and_vol,
J
Joe Gorse 已提交
2046 2047 2048 2049 2050 2051
	.destructor	= afs_flat_call_destructor,
};

/*
 * Fetch the ACL for a file.
 */
2052
void afs_fs_store_acl(struct afs_operation *op)
J
Joe Gorse 已提交
2053
{
2054
	struct afs_vnode_param *vp = &op->file[0];
J
Joe Gorse 已提交
2055
	struct afs_call *call;
2056
	const struct afs_acl *acl = op->acl;
J
Joe Gorse 已提交
2057 2058 2059 2060
	size_t size;
	__be32 *bp;

	_enter(",%x,{%llx:%llu},,",
2061
	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);
J
Joe Gorse 已提交
2062 2063

	size = round_up(acl->size, 4);
2064
	call = afs_alloc_flat_call(op->net, &afs_RXFSStoreACL,
J
Joe Gorse 已提交
2065
				   5 * 4 + size, (21 + 6) * 4);
2066 2067
	if (!call)
		return afs_op_nomem(op);
J
Joe Gorse 已提交
2068 2069 2070 2071

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSSTOREACL);
2072 2073 2074
	bp[1] = htonl(vp->fid.vid);
	bp[2] = htonl(vp->fid.vnode);
	bp[3] = htonl(vp->fid.unique);
J
Joe Gorse 已提交
2075 2076 2077 2078 2079
	bp[4] = htonl(acl->size);
	memcpy(&bp[5], acl->data, acl->size);
	if (acl->size != size)
		memset((void *)&bp[5] + acl->size, 0, size - acl->size);

2080 2081
	trace_afs_make_fs_call(call, &vp->fid);
	afs_make_op_call(op, call, GFP_KERNEL);
2082
}