fsclient.c 56.0 KB
Newer Older
1
/* AFS File Server client stubs
L
Linus Torvalds 已提交
2
 *
3
 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
L
Linus Torvalds 已提交
4 5 6 7 8 9 10 11 12
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/init.h>
13
#include <linux/slab.h>
L
Linus Torvalds 已提交
14
#include <linux/sched.h>
15
#include <linux/circ_buf.h>
J
Jeff Layton 已提交
16
#include <linux/iversion.h>
L
Linus Torvalds 已提交
17
#include "internal.h"
18
#include "afs_fs.h"
D
David Howells 已提交
19
#include "xdr_fs.h"
20
#include "protocol_yfs.h"
L
Linus Torvalds 已提交
21

22 23
static const struct afs_fid afs_zero_fid;

24
static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
25
{
26
	call->cbi = afs_get_cb_interest(cbi);
27 28
}

29 30 31 32 33 34 35 36 37 38 39 40 41
/*
 * 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 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
/*
 * 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 已提交
62 63 64
/*
 * decode an AFSFetchStatus block
 */
65 66 67
static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
				     struct afs_call *call,
				     struct afs_status_cb *scb)
D
David Howells 已提交
68 69
{
	const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
70
	struct afs_file_status *status = &scb->status;
71
	bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
72
	u64 data_version, size;
D
David Howells 已提交
73
	u32 type, abort_code;
74

75 76
	abort_code = ntohl(xdr->abort_code);

D
David Howells 已提交
77
	if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
78 79 80 81 82 83 84 85
		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;
86
			return 0;
87 88
		}

D
David Howells 已提交
89 90 91
		pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
		goto bad;
	}
92

93 94
	if (abort_code != 0 && inline_error) {
		status->abort_code = abort_code;
95
		return 0;
96 97
	}

D
David Howells 已提交
98 99
	type = ntohl(xdr->type);
	switch (type) {
D
David Howells 已提交
100 101 102
	case AFS_FTYPE_FILE:
	case AFS_FTYPE_DIR:
	case AFS_FTYPE_SYMLINK:
D
David Howells 已提交
103
		status->type = type;
D
David Howells 已提交
104 105
		break;
	default:
D
David Howells 已提交
106
		goto bad;
D
David Howells 已提交
107 108
	}

109 110 111 112 113 114 115 116
	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 已提交
117

118 119 120 121
	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 已提交
122 123 124

	size  = (u64)ntohl(xdr->size_lo);
	size |= (u64)ntohl(xdr->size_hi) << 32;
125
	status->size = size;
D
David Howells 已提交
126 127 128

	data_version  = (u64)ntohl(xdr->data_version_lo);
	data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
129
	status->data_version = data_version;
130

D
David Howells 已提交
131
	*_bp = (const void *)*_bp + sizeof(*xdr);
132
	return 0;
D
David Howells 已提交
133 134 135

bad:
	xdr_dump_bad(*_bp);
136
	return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
137 138
}

139 140 141 142 143
static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
{
	return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry;
}

144 145 146
static void xdr_decode_AFSCallBack(const __be32 **_bp,
				   struct afs_call *call,
				   struct afs_status_cb *scb)
147
{
148
	struct afs_callback *cb = &scb->callback;
149 150
	const __be32 *bp = *_bp;

151
	bp++; /* version */
152
	cb->expires_at	= xdr_decode_expiry(call, ntohl(*bp++));
153
	bp++; /* type */
154
	scb->have_cb	= true;
155 156 157
	*_bp = bp;
}

L
Linus Torvalds 已提交
158
/*
159
 * decode an AFSVolSync block
L
Linus Torvalds 已提交
160
 */
161 162
static void xdr_decode_AFSVolSync(const __be32 **_bp,
				  struct afs_volsync *volsync)
L
Linus Torvalds 已提交
163
{
164
	const __be32 *bp = *_bp;
165
	u32 creation;
L
Linus Torvalds 已提交
166

167
	creation = ntohl(*bp++);
168 169 170 171 172 173
	bp++; /* spare2 */
	bp++; /* spare3 */
	bp++; /* spare4 */
	bp++; /* spare5 */
	bp++; /* spare6 */
	*_bp = bp;
174 175 176

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

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
/*
 * 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;
195
		owner = from_kuid(&init_user_ns, attr->ia_uid);
196 197 198 199
	}

	if (attr->ia_valid & ATTR_GID) {
		mask |= AFS_SET_GROUP;
200
		group = from_kgid(&init_user_ns, attr->ia_gid);
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
	}

	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 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
/*
 * 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++);
237 238
	vs->vol_copy_date	= 0;
	vs->vol_backup_date	= 0;
D
David Howells 已提交
239 240 241
	*_bp = bp;
}

242 243 244
/*
 * deliver reply data to an FS.FetchStatus
 */
245
static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
246 247
{
	const __be32 *bp;
248
	int ret;
L
Linus Torvalds 已提交
249

250
	ret = afs_transfer_reply(call);
251 252
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
253

254 255
	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
256
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
257 258
	if (ret < 0)
		return ret;
259
	xdr_decode_AFSCallBack(&bp, call, call->out_scb);
260
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
L
Linus Torvalds 已提交
261

262 263
	_leave(" = 0 [done]");
	return 0;
D
David Howells 已提交
264
}
265 266 267 268

/*
 * FS.FetchStatus operation type
 */
269 270
static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
	.name		= "FS.FetchStatus(vnode)",
271
	.op		= afs_FS_FetchStatus,
272
	.deliver	= afs_deliver_fs_fetch_status_vnode,
273 274
	.destructor	= afs_flat_call_destructor,
};
L
Linus Torvalds 已提交
275 276 277 278

/*
 * fetch the status information for a file
 */
279 280
int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb,
			     struct afs_volsync *volsync)
L
Linus Torvalds 已提交
281
{
282
	struct afs_vnode *vnode = fc->vnode;
283
	struct afs_call *call;
284
	struct afs_net *net = afs_v2net(vnode);
L
Linus Torvalds 已提交
285 286
	__be32 *bp;

287
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
288
		return yfs_fs_fetch_file_status(fc, scb, volsync);
289

290
	_enter(",%x,{%llx:%llu},,",
291
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
L
Linus Torvalds 已提交
292

293 294
	call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
				   16, (21 + 3 + 6) * 4);
295 296
	if (!call) {
		fc->ac.error = -ENOMEM;
297
		return -ENOMEM;
298
	}
L
Linus Torvalds 已提交
299

300
	call->key = fc->key;
301
	call->out_scb = scb;
302
	call->out_volsync = volsync;
L
Linus Torvalds 已提交
303 304

	/* marshall the parameters */
305
	bp = call->request;
L
Linus Torvalds 已提交
306 307 308 309 310
	bp[0] = htonl(FSFETCHSTATUS);
	bp[1] = htonl(vnode->fid.vid);
	bp[2] = htonl(vnode->fid.vnode);
	bp[3] = htonl(vnode->fid.unique);

311
	afs_use_fs_server(call, fc->cbi);
312
	trace_afs_make_fs_call(call, &vnode->fid);
313

314
	afs_set_fc_call(call, fc);
315 316
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
317
}
L
Linus Torvalds 已提交
318 319

/*
320
 * deliver reply data to an FS.FetchData
L
Linus Torvalds 已提交
321
 */
322
static int afs_deliver_fs_fetch_data(struct afs_call *call)
L
Linus Torvalds 已提交
323
{
324
	struct afs_read *req = call->read_request;
325
	const __be32 *bp;
326
	unsigned int size;
L
Linus Torvalds 已提交
327 328
	int ret;

329 330
	_enter("{%u,%zu/%llu}",
	       call->unmarshall, iov_iter_count(&call->iter), req->actual_len);
331 332 333

	switch (call->unmarshall) {
	case 0:
334
		req->actual_len = 0;
335 336
		req->index = 0;
		req->offset = req->pos & (PAGE_SIZE - 1);
337
		call->unmarshall++;
338 339 340 341 342
		if (call->operation_ID == FSFETCHDATA64) {
			afs_extract_to_tmp64(call);
		} else {
			call->tmp_u = htonl(0);
			afs_extract_to_tmp(call);
D
David Howells 已提交
343
		}
344

345
		/* Fall through - and extract the returned data length */
346
	case 1:
347
		_debug("extract data length");
348
		ret = afs_extract_data(call, true);
349 350
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
351

352
		req->actual_len = be64_to_cpu(call->tmp64);
353
		_debug("DATA length: %llu", req->actual_len);
354 355
		req->remain = min(req->len, req->actual_len);
		if (req->remain == 0)
356
			goto no_more_data;
357

358 359
		call->unmarshall++;

360
	begin_page:
361
		ASSERTCMP(req->index, <, req->nr_pages);
362 363
		if (req->remain > PAGE_SIZE - req->offset)
			size = PAGE_SIZE - req->offset;
364 365
		else
			size = req->remain;
366 367 368 369 370
		call->bvec[0].bv_len = size;
		call->bvec[0].bv_offset = req->offset;
		call->bvec[0].bv_page = req->pages[req->index];
		iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
		ASSERTCMP(size, <=, PAGE_SIZE);
371

372
		/* Fall through - and extract the returned data */
373 374 375
	case 2:
		_debug("extract data %zu/%llu",
		       iov_iter_count(&call->iter), req->remain);
376

377
		ret = afs_extract_data(call, true);
378 379
		if (ret < 0)
			return ret;
380 381 382 383 384
		req->remain -= call->bvec[0].bv_len;
		req->offset += call->bvec[0].bv_len;
		ASSERTCMP(req->offset, <=, PAGE_SIZE);
		if (req->offset == PAGE_SIZE) {
			req->offset = 0;
385
			if (req->page_done)
386
				req->page_done(req);
D
David Howells 已提交
387
			req->index++;
388
			if (req->remain > 0)
389
				goto begin_page;
390
		}
391 392 393 394

		ASSERTCMP(req->remain, ==, 0);
		if (req->actual_len <= req->len)
			goto no_more_data;
395 396

		/* Discard any excess data the server gave us */
397 398
		iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
		call->unmarshall = 3;
399 400

		/* Fall through */
401 402 403 404 405
	case 3:
		_debug("extract discard %zu/%llu",
		       iov_iter_count(&call->iter), req->actual_len - req->len);

		ret = afs_extract_data(call, true);
406 407
		if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
408

409
	no_more_data:
410 411
		call->unmarshall = 4;
		afs_extract_to_buf(call, (21 + 3 + 6) * 4);
L
Linus Torvalds 已提交
412

413
		/* Fall through - and extract the metadata */
414 415
	case 4:
		ret = afs_extract_data(call, false);
416 417
		if (ret < 0)
			return ret;
418 419

		bp = call->buffer;
420
		ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
421 422
		if (ret < 0)
			return ret;
423
		xdr_decode_AFSCallBack(&bp, call, call->out_scb);
424
		xdr_decode_AFSVolSync(&bp, call->out_volsync);
425

426 427 428
		req->data_version = call->out_scb->status.data_version;
		req->file_size = call->out_scb->status.size;

429
		call->unmarshall++;
L
Linus Torvalds 已提交
430

431
	case 5:
432
		break;
L
Linus Torvalds 已提交
433 434
	}

435
	for (; req->index < req->nr_pages; req->index++) {
436
		if (req->offset < PAGE_SIZE)
437
			zero_user_segment(req->pages[req->index],
438
					  req->offset, PAGE_SIZE);
439
		if (req->page_done)
440
			req->page_done(req);
441
		req->offset = 0;
D
David Howells 已提交
442 443
	}

444 445
	_leave(" = 0 [done]");
	return 0;
D
David Howells 已提交
446
}
L
Linus Torvalds 已提交
447

448 449
static void afs_fetch_data_destructor(struct afs_call *call)
{
450
	struct afs_read *req = call->read_request;
451 452 453 454 455

	afs_put_read(req);
	afs_flat_call_destructor(call);
}

L
Linus Torvalds 已提交
456
/*
457
 * FS.FetchData operation type
L
Linus Torvalds 已提交
458
 */
459
static const struct afs_call_type afs_RXFSFetchData = {
D
David Howells 已提交
460
	.name		= "FS.FetchData",
461
	.op		= afs_FS_FetchData,
462
	.deliver	= afs_deliver_fs_fetch_data,
463
	.destructor	= afs_fetch_data_destructor,
464 465
};

D
David Howells 已提交
466 467
static const struct afs_call_type afs_RXFSFetchData64 = {
	.name		= "FS.FetchData64",
468
	.op		= afs_FS_FetchData64,
D
David Howells 已提交
469
	.deliver	= afs_deliver_fs_fetch_data,
470
	.destructor	= afs_fetch_data_destructor,
D
David Howells 已提交
471 472 473 474 475
};

/*
 * fetch data from a very large file
 */
476 477 478
static int afs_fs_fetch_data64(struct afs_fs_cursor *fc,
			       struct afs_status_cb *scb,
			       struct afs_read *req)
D
David Howells 已提交
479
{
480
	struct afs_vnode *vnode = fc->vnode;
D
David Howells 已提交
481
	struct afs_call *call;
482
	struct afs_net *net = afs_v2net(vnode);
D
David Howells 已提交
483 484 485 486
	__be32 *bp;

	_enter("");

487
	call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
D
David Howells 已提交
488 489 490
	if (!call)
		return -ENOMEM;

491
	call->key = fc->key;
492
	call->out_scb = scb;
493 494
	call->out_volsync = NULL;
	call->read_request = req;
D
David Howells 已提交
495 496 497 498 499 500 501

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSFETCHDATA64);
	bp[1] = htonl(vnode->fid.vid);
	bp[2] = htonl(vnode->fid.vnode);
	bp[3] = htonl(vnode->fid.unique);
502 503
	bp[4] = htonl(upper_32_bits(req->pos));
	bp[5] = htonl(lower_32_bits(req->pos));
D
David Howells 已提交
504
	bp[6] = 0;
505
	bp[7] = htonl(lower_32_bits(req->len));
D
David Howells 已提交
506

D
David Howells 已提交
507
	refcount_inc(&req->usage);
508
	afs_use_fs_server(call, fc->cbi);
509
	trace_afs_make_fs_call(call, &vnode->fid);
510
	afs_set_fc_call(call, fc);
511 512
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
513 514
}

515 516 517
/*
 * fetch data from a file
 */
518 519 520
int afs_fs_fetch_data(struct afs_fs_cursor *fc,
		      struct afs_status_cb *scb,
		      struct afs_read *req)
L
Linus Torvalds 已提交
521
{
522
	struct afs_vnode *vnode = fc->vnode;
523
	struct afs_call *call;
524
	struct afs_net *net = afs_v2net(vnode);
L
Linus Torvalds 已提交
525 526
	__be32 *bp;

527
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
528
		return yfs_fs_fetch_data(fc, scb, req);
529

530 531 532
	if (upper_32_bits(req->pos) ||
	    upper_32_bits(req->len) ||
	    upper_32_bits(req->pos + req->len))
533
		return afs_fs_fetch_data64(fc, scb, req);
D
David Howells 已提交
534

535
	_enter("");
L
Linus Torvalds 已提交
536

537
	call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
538 539
	if (!call)
		return -ENOMEM;
L
Linus Torvalds 已提交
540

541
	call->key = fc->key;
542
	call->out_scb = scb;
543 544
	call->out_volsync = NULL;
	call->read_request = req;
L
Linus Torvalds 已提交
545 546

	/* marshall the parameters */
547 548 549 550 551
	bp = call->request;
	bp[0] = htonl(FSFETCHDATA);
	bp[1] = htonl(vnode->fid.vid);
	bp[2] = htonl(vnode->fid.vnode);
	bp[3] = htonl(vnode->fid.unique);
552 553
	bp[4] = htonl(lower_32_bits(req->pos));
	bp[5] = htonl(lower_32_bits(req->len));
L
Linus Torvalds 已提交
554

D
David Howells 已提交
555
	refcount_inc(&req->usage);
556
	afs_use_fs_server(call, fc->cbi);
557
	trace_afs_make_fs_call(call, &vnode->fid);
558
	afs_set_fc_call(call, fc);
559 560
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
561
}
562 563 564 565

/*
 * deliver reply data to an FS.CreateFile or an FS.MakeDir
 */
566
static int afs_deliver_fs_create_vnode(struct afs_call *call)
567 568
{
	const __be32 *bp;
569
	int ret;
570

571
	ret = afs_transfer_reply(call);
572 573
	if (ret < 0)
		return ret;
574 575 576

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
577
	xdr_decode_AFSFid(&bp, call->out_fid);
578
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
579 580
	if (ret < 0)
		return ret;
581
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
582 583
	if (ret < 0)
		return ret;
584
	xdr_decode_AFSCallBack(&bp, call, call->out_scb);
585
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
586 587 588 589 590 591 592 593

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

/*
 * FS.CreateFile and FS.MakeDir operation type
 */
594 595 596 597 598 599 600 601 602 603
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,
};

static const struct afs_call_type afs_RXFSMakeDir = {
	.name		= "FS.MakeDir",
	.op		= afs_FS_MakeDir,
604 605 606 607 608 609 610
	.deliver	= afs_deliver_fs_create_vnode,
	.destructor	= afs_flat_call_destructor,
};

/*
 * create a file or make a directory
 */
D
David Howells 已提交
611
int afs_fs_create(struct afs_fs_cursor *fc,
612 613
		  const char *name,
		  umode_t mode,
614
		  struct afs_status_cb *dvnode_scb,
615
		  struct afs_fid *newfid,
616
		  struct afs_status_cb *new_scb)
617
{
618
	struct afs_vnode *dvnode = fc->vnode;
619
	struct afs_call *call;
620
	struct afs_net *net = afs_v2net(dvnode);
621 622 623
	size_t namesz, reqsz, padsz;
	__be32 *bp;

624 625
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){
		if (S_ISDIR(mode))
626 627
			return yfs_fs_make_dir(fc, name, mode, dvnode_scb,
					       newfid, new_scb);
628
		else
629 630
			return yfs_fs_create_file(fc, name, mode, dvnode_scb,
						  newfid, new_scb);
631 632
	}

633 634 635 636 637 638
	_enter("");

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

639 640 641
	call = afs_alloc_flat_call(
		net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
		reqsz, (3 + 21 + 21 + 3 + 6) * 4);
642 643 644
	if (!call)
		return -ENOMEM;

645
	call->key = fc->key;
646
	call->out_dir_scb = dvnode_scb;
647
	call->out_fid = newfid;
648
	call->out_scb = new_scb;
649 650 651 652

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
653 654 655
	*bp++ = htonl(dvnode->fid.vid);
	*bp++ = htonl(dvnode->fid.vnode);
	*bp++ = htonl(dvnode->fid.unique);
656 657 658 659 660 661 662
	*bp++ = htonl(namesz);
	memcpy(bp, name, namesz);
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}
663
	*bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
664
	*bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */
665 666 667 668 669
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = htonl(mode & S_IALLUGO); /* unix mode */
	*bp++ = 0; /* segment size */

670
	afs_use_fs_server(call, fc->cbi);
671
	trace_afs_make_fs_call1(call, &dvnode->fid, name);
672
	afs_set_fc_call(call, fc);
673 674
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
675 676 677
}

/*
678
 * Deliver reply data to any operation that returns directory status and volume
J
Joe Gorse 已提交
679
 * sync.
680
 */
681
static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call)
682 683
{
	const __be32 *bp;
684
	int ret;
685

686
	ret = afs_transfer_reply(call);
687 688
	if (ret < 0)
		return ret;
689 690 691

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
692
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
693 694
	if (ret < 0)
		return ret;
695
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
696 697 698 699 700 701 702 703

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

/*
 * FS.RemoveDir/FS.RemoveFile operation type
 */
704 705 706
static const struct afs_call_type afs_RXFSRemoveFile = {
	.name		= "FS.RemoveFile",
	.op		= afs_FS_RemoveFile,
707
	.deliver	= afs_deliver_fs_dir_status_and_vol,
708 709 710 711 712 713
	.destructor	= afs_flat_call_destructor,
};

static const struct afs_call_type afs_RXFSRemoveDir = {
	.name		= "FS.RemoveDir",
	.op		= afs_FS_RemoveDir,
714
	.deliver	= afs_deliver_fs_dir_status_and_vol,
715 716 717 718 719 720
	.destructor	= afs_flat_call_destructor,
};

/*
 * remove a file or directory
 */
721
int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
722
		  const char *name, bool isdir, struct afs_status_cb *dvnode_scb)
723
{
724
	struct afs_vnode *dvnode = fc->vnode;
725
	struct afs_call *call;
726
	struct afs_net *net = afs_v2net(dvnode);
727 728 729
	size_t namesz, reqsz, padsz;
	__be32 *bp;

730
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
731
		return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb);
732

733 734 735 736 737 738
	_enter("");

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

739 740 741
	call = afs_alloc_flat_call(
		net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
		reqsz, (21 + 6) * 4);
742 743 744
	if (!call)
		return -ENOMEM;

745
	call->key = fc->key;
746
	call->out_dir_scb = dvnode_scb;
747 748 749 750

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
751 752 753
	*bp++ = htonl(dvnode->fid.vid);
	*bp++ = htonl(dvnode->fid.vnode);
	*bp++ = htonl(dvnode->fid.unique);
754 755 756 757 758 759 760 761
	*bp++ = htonl(namesz);
	memcpy(bp, name, namesz);
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}

762
	afs_use_fs_server(call, fc->cbi);
D
David Howells 已提交
763
	trace_afs_make_fs_call1(call, &dvnode->fid, name);
764
	afs_set_fc_call(call, fc);
765 766
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
767 768 769 770 771
}

/*
 * deliver reply data to an FS.Link
 */
772
static int afs_deliver_fs_link(struct afs_call *call)
773 774
{
	const __be32 *bp;
775
	int ret;
776

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

779
	ret = afs_transfer_reply(call);
780 781
	if (ret < 0)
		return ret;
782 783 784

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
785
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
786 787
	if (ret < 0)
		return ret;
788
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
789 790
	if (ret < 0)
		return ret;
791
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
792 793 794 795 796 797 798 799 800 801

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

/*
 * FS.Link operation type
 */
static const struct afs_call_type afs_RXFSLink = {
	.name		= "FS.Link",
802
	.op		= afs_FS_Link,
803 804 805 806 807 808 809
	.deliver	= afs_deliver_fs_link,
	.destructor	= afs_flat_call_destructor,
};

/*
 * make a hard link
 */
810
int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
811 812 813
		const char *name,
		struct afs_status_cb *dvnode_scb,
		struct afs_status_cb *vnode_scb)
814
{
815
	struct afs_vnode *dvnode = fc->vnode;
816
	struct afs_call *call;
817
	struct afs_net *net = afs_v2net(vnode);
818 819 820
	size_t namesz, reqsz, padsz;
	__be32 *bp;

821
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
822
		return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb);
823

824 825 826 827 828 829
	_enter("");

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

830
	call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
831 832 833
	if (!call)
		return -ENOMEM;

834
	call->key = fc->key;
835 836
	call->out_dir_scb = dvnode_scb;
	call->out_scb = vnode_scb;
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854

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

855
	afs_use_fs_server(call, fc->cbi);
D
David Howells 已提交
856
	trace_afs_make_fs_call1(call, &vnode->fid, name);
857
	afs_set_fc_call(call, fc);
858 859
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
860 861 862 863 864
}

/*
 * deliver reply data to an FS.Symlink
 */
865
static int afs_deliver_fs_symlink(struct afs_call *call)
866 867
{
	const __be32 *bp;
868
	int ret;
869

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

872
	ret = afs_transfer_reply(call);
873 874
	if (ret < 0)
		return ret;
875 876 877

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
878
	xdr_decode_AFSFid(&bp, call->out_fid);
879
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
880 881
	if (ret < 0)
		return ret;
882
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
883 884
	if (ret < 0)
		return ret;
885
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
886 887 888 889 890 891 892 893 894 895

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

/*
 * FS.Symlink operation type
 */
static const struct afs_call_type afs_RXFSSymlink = {
	.name		= "FS.Symlink",
896
	.op		= afs_FS_Symlink,
897 898 899 900 901 902 903
	.deliver	= afs_deliver_fs_symlink,
	.destructor	= afs_flat_call_destructor,
};

/*
 * create a symbolic link
 */
D
David Howells 已提交
904
int afs_fs_symlink(struct afs_fs_cursor *fc,
905 906
		   const char *name,
		   const char *contents,
907
		   struct afs_status_cb *dvnode_scb,
908
		   struct afs_fid *newfid,
909
		   struct afs_status_cb *new_scb)
910
{
911
	struct afs_vnode *dvnode = fc->vnode;
912
	struct afs_call *call;
913
	struct afs_net *net = afs_v2net(dvnode);
914 915 916
	size_t namesz, reqsz, padsz, c_namesz, c_padsz;
	__be32 *bp;

917
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
918 919
		return yfs_fs_symlink(fc, name, contents, dvnode_scb,
				      newfid, new_scb);
920

921 922 923 924 925 926 927 928 929 930
	_enter("");

	namesz = strlen(name);
	padsz = (4 - (namesz & 3)) & 3;

	c_namesz = strlen(contents);
	c_padsz = (4 - (c_namesz & 3)) & 3;

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

931
	call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
932 933 934 935
				   (3 + 21 + 21 + 6) * 4);
	if (!call)
		return -ENOMEM;

936
	call->key = fc->key;
937
	call->out_dir_scb = dvnode_scb;
938
	call->out_fid = newfid;
939
	call->out_scb = new_scb;
940 941 942 943

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSYMLINK);
944 945 946
	*bp++ = htonl(dvnode->fid.vid);
	*bp++ = htonl(dvnode->fid.vnode);
	*bp++ = htonl(dvnode->fid.unique);
947 948 949 950 951 952 953 954 955 956 957 958 959 960
	*bp++ = htonl(namesz);
	memcpy(bp, name, namesz);
	bp = (void *) bp + namesz;
	if (padsz > 0) {
		memset(bp, 0, padsz);
		bp = (void *) bp + padsz;
	}
	*bp++ = htonl(c_namesz);
	memcpy(bp, contents, c_namesz);
	bp = (void *) bp + c_namesz;
	if (c_padsz > 0) {
		memset(bp, 0, c_padsz);
		bp = (void *) bp + c_padsz;
	}
961
	*bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
962
	*bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */
963 964 965 966 967
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = htonl(S_IRWXUGO); /* unix mode */
	*bp++ = 0; /* segment size */

968
	afs_use_fs_server(call, fc->cbi);
969
	trace_afs_make_fs_call1(call, &dvnode->fid, name);
970
	afs_set_fc_call(call, fc);
971 972
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
973 974 975 976 977
}

/*
 * deliver reply data to an FS.Rename
 */
978
static int afs_deliver_fs_rename(struct afs_call *call)
979 980
{
	const __be32 *bp;
981
	int ret;
982

983
	ret = afs_transfer_reply(call);
984 985
	if (ret < 0)
		return ret;
986 987 988

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
989
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
990 991
	if (ret < 0)
		return ret;
992 993
	if (call->out_dir_scb != call->out_scb) {
		ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
994 995 996
		if (ret < 0)
			return ret;
	}
997
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
998 999 1000 1001 1002 1003 1004 1005 1006 1007

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

/*
 * FS.Rename operation type
 */
static const struct afs_call_type afs_RXFSRename = {
	.name		= "FS.Rename",
1008
	.op		= afs_FS_Rename,
1009 1010 1011 1012 1013
	.deliver	= afs_deliver_fs_rename,
	.destructor	= afs_flat_call_destructor,
};

/*
1014
 * Rename/move a file or directory.
1015
 */
D
David Howells 已提交
1016
int afs_fs_rename(struct afs_fs_cursor *fc,
1017 1018
		  const char *orig_name,
		  struct afs_vnode *new_dvnode,
1019
		  const char *new_name,
1020 1021
		  struct afs_status_cb *orig_dvnode_scb,
		  struct afs_status_cb *new_dvnode_scb)
1022
{
1023
	struct afs_vnode *orig_dvnode = fc->vnode;
1024
	struct afs_call *call;
1025
	struct afs_net *net = afs_v2net(orig_dvnode);
1026 1027 1028
	size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
	__be32 *bp;

1029 1030 1031
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_rename(fc, orig_name,
				     new_dvnode, new_name,
1032 1033
				     orig_dvnode_scb,
				     new_dvnode_scb);
1034

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
	_enter("");

	o_namesz = strlen(orig_name);
	o_padsz = (4 - (o_namesz & 3)) & 3;

	n_namesz = strlen(new_name);
	n_padsz = (4 - (n_namesz & 3)) & 3;

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

1048
	call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
1049 1050 1051
	if (!call)
		return -ENOMEM;

1052
	call->key = fc->key;
1053 1054
	call->out_dir_scb = orig_dvnode_scb;
	call->out_scb = new_dvnode_scb;
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSRENAME);
	*bp++ = htonl(orig_dvnode->fid.vid);
	*bp++ = htonl(orig_dvnode->fid.vnode);
	*bp++ = htonl(orig_dvnode->fid.unique);
	*bp++ = htonl(o_namesz);
	memcpy(bp, orig_name, o_namesz);
	bp = (void *) bp + o_namesz;
	if (o_padsz > 0) {
		memset(bp, 0, o_padsz);
		bp = (void *) bp + o_padsz;
	}

	*bp++ = htonl(new_dvnode->fid.vid);
	*bp++ = htonl(new_dvnode->fid.vnode);
	*bp++ = htonl(new_dvnode->fid.unique);
	*bp++ = htonl(n_namesz);
	memcpy(bp, new_name, n_namesz);
	bp = (void *) bp + n_namesz;
	if (n_padsz > 0) {
		memset(bp, 0, n_padsz);
		bp = (void *) bp + n_padsz;
	}

1081
	afs_use_fs_server(call, fc->cbi);
D
David Howells 已提交
1082
	trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name);
1083
	afs_set_fc_call(call, fc);
1084 1085
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
1086
}
1087 1088 1089 1090

/*
 * deliver reply data to an FS.StoreData
 */
1091
static int afs_deliver_fs_store_data(struct afs_call *call)
1092 1093
{
	const __be32 *bp;
1094
	int ret;
1095

1096
	_enter("");
1097

1098
	ret = afs_transfer_reply(call);
1099 1100
	if (ret < 0)
		return ret;
1101 1102 1103

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
1104
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
1105 1106
	if (ret < 0)
		return ret;
1107
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117

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

/*
 * FS.StoreData operation type
 */
static const struct afs_call_type afs_RXFSStoreData = {
	.name		= "FS.StoreData",
1118
	.op		= afs_FS_StoreData,
1119 1120 1121 1122
	.deliver	= afs_deliver_fs_store_data,
	.destructor	= afs_flat_call_destructor,
};

D
David Howells 已提交
1123 1124
static const struct afs_call_type afs_RXFSStoreData64 = {
	.name		= "FS.StoreData64",
1125
	.op		= afs_FS_StoreData64,
D
David Howells 已提交
1126 1127 1128 1129 1130 1131 1132
	.deliver	= afs_deliver_fs_store_data,
	.destructor	= afs_flat_call_destructor,
};

/*
 * store a set of pages to a very large file
 */
D
David Howells 已提交
1133
static int afs_fs_store_data64(struct afs_fs_cursor *fc,
1134
			       struct address_space *mapping,
D
David Howells 已提交
1135 1136
			       pgoff_t first, pgoff_t last,
			       unsigned offset, unsigned to,
1137 1138
			       loff_t size, loff_t pos, loff_t i_size,
			       struct afs_status_cb *scb)
D
David Howells 已提交
1139
{
1140
	struct afs_vnode *vnode = fc->vnode;
D
David Howells 已提交
1141
	struct afs_call *call;
1142
	struct afs_net *net = afs_v2net(vnode);
D
David Howells 已提交
1143 1144
	__be32 *bp;

1145
	_enter(",%x,{%llx:%llu},,",
1146
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
D
David Howells 已提交
1147

1148
	call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
D
David Howells 已提交
1149 1150 1151 1152 1153
				   (4 + 6 + 3 * 2) * 4,
				   (21 + 6) * 4);
	if (!call)
		return -ENOMEM;

1154 1155
	call->key = fc->key;
	call->mapping = mapping;
D
David Howells 已提交
1156 1157 1158 1159 1160
	call->first = first;
	call->last = last;
	call->first_offset = offset;
	call->last_to = to;
	call->send_pages = true;
1161
	call->out_scb = scb;
D
David Howells 已提交
1162 1163 1164 1165 1166 1167 1168 1169

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSTOREDATA64);
	*bp++ = htonl(vnode->fid.vid);
	*bp++ = htonl(vnode->fid.vnode);
	*bp++ = htonl(vnode->fid.unique);

1170 1171
	*bp++ = htonl(AFS_SET_MTIME); /* mask */
	*bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
D
David Howells 已提交
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = 0; /* unix mode */
	*bp++ = 0; /* segment size */

	*bp++ = htonl(pos >> 32);
	*bp++ = htonl((u32) pos);
	*bp++ = htonl(size >> 32);
	*bp++ = htonl((u32) size);
	*bp++ = htonl(i_size >> 32);
	*bp++ = htonl((u32) i_size);

1184
	trace_afs_make_fs_call(call, &vnode->fid);
1185
	afs_set_fc_call(call, fc);
1186 1187
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
1188 1189
}

1190 1191 1192
/*
 * store a set of pages
 */
1193
int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
1194
		      pgoff_t first, pgoff_t last,
1195 1196
		      unsigned offset, unsigned to,
		      struct afs_status_cb *scb)
1197
{
1198
	struct afs_vnode *vnode = fc->vnode;
1199
	struct afs_call *call;
1200
	struct afs_net *net = afs_v2net(vnode);
1201 1202 1203
	loff_t size, pos, i_size;
	__be32 *bp;

1204
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1205
		return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb);
1206

1207
	_enter(",%x,{%llx:%llu},,",
1208
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
1209

1210
	size = (loff_t)to - (loff_t)offset;
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
	if (first != last)
		size += (loff_t)(last - first) << PAGE_SHIFT;
	pos = (loff_t)first << PAGE_SHIFT;
	pos += offset;

	i_size = i_size_read(&vnode->vfs_inode);
	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);

D
David Howells 已提交
1224
	if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
1225
		return afs_fs_store_data64(fc, mapping, first, last, offset, to,
1226
					   size, pos, i_size, scb);
1227

1228
	call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
1229 1230 1231 1232 1233
				   (4 + 6 + 3) * 4,
				   (21 + 6) * 4);
	if (!call)
		return -ENOMEM;

1234 1235
	call->key = fc->key;
	call->mapping = mapping;
1236 1237 1238 1239 1240
	call->first = first;
	call->last = last;
	call->first_offset = offset;
	call->last_to = to;
	call->send_pages = true;
1241
	call->out_scb = scb;
1242 1243 1244 1245 1246 1247 1248 1249

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

1250 1251
	*bp++ = htonl(AFS_SET_MTIME); /* mask */
	*bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
1252 1253 1254 1255 1256 1257 1258 1259 1260
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = 0; /* unix mode */
	*bp++ = 0; /* segment size */

	*bp++ = htonl(pos);
	*bp++ = htonl(size);
	*bp++ = htonl(i_size);

1261
	afs_use_fs_server(call, fc->cbi);
1262
	trace_afs_make_fs_call(call, &vnode->fid);
1263
	afs_set_fc_call(call, fc);
1264 1265
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
1266 1267 1268 1269 1270
}

/*
 * deliver reply data to an FS.StoreStatus
 */
1271
static int afs_deliver_fs_store_status(struct afs_call *call)
1272 1273
{
	const __be32 *bp;
1274
	int ret;
1275

1276
	_enter("");
1277

1278
	ret = afs_transfer_reply(call);
1279 1280
	if (ret < 0)
		return ret;
1281 1282 1283

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
1284
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
1285 1286
	if (ret < 0)
		return ret;
1287
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297

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

/*
 * FS.StoreStatus operation type
 */
static const struct afs_call_type afs_RXFSStoreStatus = {
	.name		= "FS.StoreStatus",
1298
	.op		= afs_FS_StoreStatus,
1299 1300 1301 1302 1303 1304
	.deliver	= afs_deliver_fs_store_status,
	.destructor	= afs_flat_call_destructor,
};

static const struct afs_call_type afs_RXFSStoreData_as_Status = {
	.name		= "FS.StoreData",
1305
	.op		= afs_FS_StoreData,
1306 1307 1308 1309
	.deliver	= afs_deliver_fs_store_status,
	.destructor	= afs_flat_call_destructor,
};

D
David Howells 已提交
1310 1311
static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
	.name		= "FS.StoreData64",
1312
	.op		= afs_FS_StoreData64,
D
David Howells 已提交
1313 1314 1315 1316 1317 1318 1319 1320
	.deliver	= afs_deliver_fs_store_status,
	.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
 */
1321 1322
static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr,
				 struct afs_status_cb *scb)
D
David Howells 已提交
1323
{
1324
	struct afs_vnode *vnode = fc->vnode;
D
David Howells 已提交
1325
	struct afs_call *call;
1326
	struct afs_net *net = afs_v2net(vnode);
D
David Howells 已提交
1327 1328
	__be32 *bp;

1329
	_enter(",%x,{%llx:%llu},,",
1330
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
D
David Howells 已提交
1331 1332 1333

	ASSERT(attr->ia_valid & ATTR_SIZE);

1334
	call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
D
David Howells 已提交
1335 1336 1337 1338 1339
				   (4 + 6 + 3 * 2) * 4,
				   (21 + 6) * 4);
	if (!call)
		return -ENOMEM;

1340
	call->key = fc->key;
1341
	call->out_scb = scb;
D
David Howells 已提交
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSTOREDATA64);
	*bp++ = htonl(vnode->fid.vid);
	*bp++ = htonl(vnode->fid.vnode);
	*bp++ = htonl(vnode->fid.unique);

	xdr_encode_AFS_StoreStatus(&bp, attr);

1352 1353
	*bp++ = htonl(attr->ia_size >> 32);	/* position of start of write */
	*bp++ = htonl((u32) attr->ia_size);
D
David Howells 已提交
1354 1355 1356 1357 1358
	*bp++ = 0;				/* size of write */
	*bp++ = 0;
	*bp++ = htonl(attr->ia_size >> 32);	/* new file length */
	*bp++ = htonl((u32) attr->ia_size);

1359
	afs_use_fs_server(call, fc->cbi);
1360
	trace_afs_make_fs_call(call, &vnode->fid);
1361
	afs_set_fc_call(call, fc);
1362 1363
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
1364 1365
}

1366 1367 1368 1369
/*
 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
 * so as to alter the file size also
 */
1370 1371
static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr,
			       struct afs_status_cb *scb)
1372
{
1373
	struct afs_vnode *vnode = fc->vnode;
1374
	struct afs_call *call;
1375
	struct afs_net *net = afs_v2net(vnode);
1376 1377
	__be32 *bp;

1378
	_enter(",%x,{%llx:%llu},,",
1379
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
1380 1381

	ASSERT(attr->ia_valid & ATTR_SIZE);
D
David Howells 已提交
1382
	if (attr->ia_size >> 32)
1383
		return afs_fs_setattr_size64(fc, attr, scb);
1384

1385
	call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
1386 1387 1388 1389 1390
				   (4 + 6 + 3) * 4,
				   (21 + 6) * 4);
	if (!call)
		return -ENOMEM;

1391
	call->key = fc->key;
1392
	call->out_scb = scb;
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402

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

	xdr_encode_AFS_StoreStatus(&bp, attr);

1403
	*bp++ = htonl(attr->ia_size);		/* position of start of write */
1404 1405 1406
	*bp++ = 0;				/* size of write */
	*bp++ = htonl(attr->ia_size);		/* new file length */

1407
	afs_use_fs_server(call, fc->cbi);
1408
	trace_afs_make_fs_call(call, &vnode->fid);
1409
	afs_set_fc_call(call, fc);
1410 1411
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
1412 1413 1414 1415 1416 1417
}

/*
 * set the attributes on a file, using FS.StoreData if there's a change in file
 * size, and FS.StoreStatus otherwise
 */
1418 1419
int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr,
		   struct afs_status_cb *scb)
1420
{
1421
	struct afs_vnode *vnode = fc->vnode;
1422
	struct afs_call *call;
1423
	struct afs_net *net = afs_v2net(vnode);
1424 1425
	__be32 *bp;

1426
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1427
		return yfs_fs_setattr(fc, attr, scb);
1428

1429
	if (attr->ia_valid & ATTR_SIZE)
1430
		return afs_fs_setattr_size(fc, attr, scb);
1431

1432
	_enter(",%x,{%llx:%llu},,",
1433
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
1434

1435
	call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
1436 1437 1438 1439 1440
				   (4 + 6) * 4,
				   (21 + 6) * 4);
	if (!call)
		return -ENOMEM;

1441
	call->key = fc->key;
1442
	call->out_scb = scb;
1443 1444 1445 1446 1447 1448 1449 1450 1451 1452

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

	xdr_encode_AFS_StoreStatus(&bp, attr);

1453
	afs_use_fs_server(call, fc->cbi);
1454
	trace_afs_make_fs_call(call, &vnode->fid);
1455
	afs_set_fc_call(call, fc);
1456 1457
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
1458
}
D
David Howells 已提交
1459 1460 1461 1462

/*
 * deliver reply data to an FS.GetVolumeStatus
 */
1463
static int afs_deliver_fs_get_volume_status(struct afs_call *call)
D
David Howells 已提交
1464 1465 1466
{
	const __be32 *bp;
	char *p;
1467
	u32 size;
D
David Howells 已提交
1468 1469
	int ret;

1470
	_enter("{%u}", call->unmarshall);
D
David Howells 已提交
1471 1472 1473 1474

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

1477
		/* Fall through - and extract the returned status record */
D
David Howells 已提交
1478 1479
	case 1:
		_debug("extract status");
1480
		ret = afs_extract_data(call, true);
1481 1482
		if (ret < 0)
			return ret;
D
David Howells 已提交
1483 1484

		bp = call->buffer;
1485
		xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus);
D
David Howells 已提交
1486
		call->unmarshall++;
1487
		afs_extract_to_tmp(call);
D
David Howells 已提交
1488

1489
		/* Fall through - and extract the volume name length */
D
David Howells 已提交
1490
	case 2:
1491
		ret = afs_extract_data(call, true);
1492 1493
		if (ret < 0)
			return ret;
D
David Howells 已提交
1494 1495 1496 1497

		call->count = ntohl(call->tmp);
		_debug("volname length: %u", call->count);
		if (call->count >= AFSNAMEMAX)
1498 1499
			return afs_protocol_error(call, -EBADMSG,
						  afs_eproto_volname_len);
1500
		size = (call->count + 3) & ~3; /* It's padded */
1501
		afs_extract_to_buf(call, size);
D
David Howells 已提交
1502 1503
		call->unmarshall++;

1504
		/* Fall through - and extract the volume name */
D
David Howells 已提交
1505 1506
	case 3:
		_debug("extract volname");
1507 1508 1509
		ret = afs_extract_data(call, true);
		if (ret < 0)
			return ret;
D
David Howells 已提交
1510

1511
		p = call->buffer;
D
David Howells 已提交
1512 1513
		p[call->count] = 0;
		_debug("volname '%s'", p);
1514
		afs_extract_to_tmp(call);
D
David Howells 已提交
1515 1516
		call->unmarshall++;

1517
		/* Fall through - and extract the offline message length */
1518 1519
	case 4:
		ret = afs_extract_data(call, true);
1520 1521
		if (ret < 0)
			return ret;
D
David Howells 已提交
1522 1523 1524 1525

		call->count = ntohl(call->tmp);
		_debug("offline msg length: %u", call->count);
		if (call->count >= AFSNAMEMAX)
1526 1527
			return afs_protocol_error(call, -EBADMSG,
						  afs_eproto_offline_msg_len);
1528
		size = (call->count + 3) & ~3; /* It's padded */
1529
		afs_extract_to_buf(call, size);
D
David Howells 已提交
1530 1531
		call->unmarshall++;

1532
		/* Fall through - and extract the offline message */
1533
	case 5:
D
David Howells 已提交
1534
		_debug("extract offline");
1535 1536 1537
		ret = afs_extract_data(call, true);
		if (ret < 0)
			return ret;
D
David Howells 已提交
1538

1539
		p = call->buffer;
D
David Howells 已提交
1540 1541 1542
		p[call->count] = 0;
		_debug("offline '%s'", p);

1543
		afs_extract_to_tmp(call);
D
David Howells 已提交
1544 1545
		call->unmarshall++;

1546
		/* Fall through - and extract the message of the day length */
1547 1548
	case 6:
		ret = afs_extract_data(call, true);
1549 1550
		if (ret < 0)
			return ret;
D
David Howells 已提交
1551 1552 1553 1554

		call->count = ntohl(call->tmp);
		_debug("motd length: %u", call->count);
		if (call->count >= AFSNAMEMAX)
1555 1556
			return afs_protocol_error(call, -EBADMSG,
						  afs_eproto_motd_len);
1557
		size = (call->count + 3) & ~3; /* It's padded */
1558
		afs_extract_to_buf(call, size);
D
David Howells 已提交
1559 1560
		call->unmarshall++;

1561
		/* Fall through - and extract the message of the day */
1562
	case 7:
D
David Howells 已提交
1563
		_debug("extract motd");
1564 1565 1566
		ret = afs_extract_data(call, false);
		if (ret < 0)
			return ret;
D
David Howells 已提交
1567

1568
		p = call->buffer;
D
David Howells 已提交
1569 1570 1571 1572 1573
		p[call->count] = 0;
		_debug("motd '%s'", p);

		call->unmarshall++;

1574
	case 8:
D
David Howells 已提交
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
		break;
	}

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

/*
 * FS.GetVolumeStatus operation type
 */
static const struct afs_call_type afs_RXFSGetVolumeStatus = {
	.name		= "FS.GetVolumeStatus",
1587
	.op		= afs_FS_GetVolumeStatus,
D
David Howells 已提交
1588
	.deliver	= afs_deliver_fs_get_volume_status,
1589
	.destructor	= afs_flat_call_destructor,
D
David Howells 已提交
1590 1591 1592 1593 1594
};

/*
 * fetch the status of a volume
 */
D
David Howells 已提交
1595
int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
1596
			     struct afs_volume_status *vs)
D
David Howells 已提交
1597
{
1598
	struct afs_vnode *vnode = fc->vnode;
D
David Howells 已提交
1599
	struct afs_call *call;
1600
	struct afs_net *net = afs_v2net(vnode);
D
David Howells 已提交
1601 1602
	__be32 *bp;

1603 1604 1605
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_get_volume_status(fc, vs);

D
David Howells 已提交
1606 1607
	_enter("");

1608 1609 1610
	call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4,
				   max(12 * 4, AFSOPAQUEMAX + 1));
	if (!call)
D
David Howells 已提交
1611 1612
		return -ENOMEM;

1613
	call->key = fc->key;
1614
	call->out_volstatus = vs;
D
David Howells 已提交
1615 1616 1617 1618 1619 1620

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSGETVOLUMESTATUS);
	bp[1] = htonl(vnode->fid.vid);

1621
	afs_use_fs_server(call, fc->cbi);
1622
	trace_afs_make_fs_call(call, &vnode->fid);
1623
	afs_set_fc_call(call, fc);
1624 1625
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
1626
}
D
David Howells 已提交
1627 1628 1629 1630

/*
 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
 */
1631
static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
D
David Howells 已提交
1632 1633
{
	const __be32 *bp;
1634
	int ret;
D
David Howells 已提交
1635

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

1638
	ret = afs_transfer_reply(call);
1639 1640
	if (ret < 0)
		return ret;
D
David Howells 已提交
1641 1642 1643

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
1644
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
D
David Howells 已提交
1645 1646 1647 1648 1649 1650 1651 1652 1653 1654

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

/*
 * FS.SetLock operation type
 */
static const struct afs_call_type afs_RXFSSetLock = {
	.name		= "FS.SetLock",
1655
	.op		= afs_FS_SetLock,
D
David Howells 已提交
1656
	.deliver	= afs_deliver_fs_xxxx_lock,
1657
	.done		= afs_lock_op_done,
D
David Howells 已提交
1658 1659 1660 1661 1662 1663 1664 1665
	.destructor	= afs_flat_call_destructor,
};

/*
 * FS.ExtendLock operation type
 */
static const struct afs_call_type afs_RXFSExtendLock = {
	.name		= "FS.ExtendLock",
1666
	.op		= afs_FS_ExtendLock,
D
David Howells 已提交
1667
	.deliver	= afs_deliver_fs_xxxx_lock,
1668
	.done		= afs_lock_op_done,
D
David Howells 已提交
1669 1670 1671 1672 1673 1674 1675 1676
	.destructor	= afs_flat_call_destructor,
};

/*
 * FS.ReleaseLock operation type
 */
static const struct afs_call_type afs_RXFSReleaseLock = {
	.name		= "FS.ReleaseLock",
1677
	.op		= afs_FS_ReleaseLock,
D
David Howells 已提交
1678 1679 1680 1681 1682
	.deliver	= afs_deliver_fs_xxxx_lock,
	.destructor	= afs_flat_call_destructor,
};

/*
1683
 * Set a lock on a file
D
David Howells 已提交
1684
 */
1685 1686
int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type,
		    struct afs_status_cb *scb)
D
David Howells 已提交
1687
{
1688
	struct afs_vnode *vnode = fc->vnode;
D
David Howells 已提交
1689
	struct afs_call *call;
1690
	struct afs_net *net = afs_v2net(vnode);
D
David Howells 已提交
1691 1692
	__be32 *bp;

1693
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1694
		return yfs_fs_set_lock(fc, type, scb);
1695

D
David Howells 已提交
1696 1697
	_enter("");

1698
	call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
D
David Howells 已提交
1699 1700 1701
	if (!call)
		return -ENOMEM;

1702
	call->key = fc->key;
1703 1704
	call->lvnode = vnode;
	call->out_scb = scb;
D
David Howells 已提交
1705 1706 1707 1708 1709 1710 1711 1712 1713

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSETLOCK);
	*bp++ = htonl(vnode->fid.vid);
	*bp++ = htonl(vnode->fid.vnode);
	*bp++ = htonl(vnode->fid.unique);
	*bp++ = htonl(type);

1714
	afs_use_fs_server(call, fc->cbi);
1715
	trace_afs_make_fs_calli(call, &vnode->fid, type);
1716
	afs_set_fc_call(call, fc);
1717 1718
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
1719 1720 1721 1722 1723
}

/*
 * extend a lock on a file
 */
1724
int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
D
David Howells 已提交
1725
{
1726
	struct afs_vnode *vnode = fc->vnode;
D
David Howells 已提交
1727
	struct afs_call *call;
1728
	struct afs_net *net = afs_v2net(vnode);
D
David Howells 已提交
1729 1730
	__be32 *bp;

1731
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1732
		return yfs_fs_extend_lock(fc, scb);
1733

D
David Howells 已提交
1734 1735
	_enter("");

1736
	call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
D
David Howells 已提交
1737 1738 1739
	if (!call)
		return -ENOMEM;

1740
	call->key = fc->key;
1741 1742
	call->lvnode = vnode;
	call->out_scb = scb;
D
David Howells 已提交
1743 1744 1745 1746 1747 1748 1749 1750

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSEXTENDLOCK);
	*bp++ = htonl(vnode->fid.vid);
	*bp++ = htonl(vnode->fid.vnode);
	*bp++ = htonl(vnode->fid.unique);

1751
	afs_use_fs_server(call, fc->cbi);
1752
	trace_afs_make_fs_call(call, &vnode->fid);
1753
	afs_set_fc_call(call, fc);
1754 1755
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
D
David Howells 已提交
1756 1757 1758 1759 1760
}

/*
 * release a lock on a file
 */
1761
int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
D
David Howells 已提交
1762
{
1763
	struct afs_vnode *vnode = fc->vnode;
D
David Howells 已提交
1764
	struct afs_call *call;
1765
	struct afs_net *net = afs_v2net(vnode);
D
David Howells 已提交
1766 1767
	__be32 *bp;

1768
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1769
		return yfs_fs_release_lock(fc, scb);
1770

D
David Howells 已提交
1771 1772
	_enter("");

1773
	call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
D
David Howells 已提交
1774 1775 1776
	if (!call)
		return -ENOMEM;

1777
	call->key = fc->key;
1778 1779
	call->lvnode = vnode;
	call->out_scb = scb;
D
David Howells 已提交
1780 1781 1782 1783 1784 1785 1786 1787

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSRELEASELOCK);
	*bp++ = htonl(vnode->fid.vid);
	*bp++ = htonl(vnode->fid.vnode);
	*bp++ = htonl(vnode->fid.unique);

1788
	afs_use_fs_server(call, fc->cbi);
1789
	trace_afs_make_fs_call(call, &vnode->fid);
1790
	afs_set_fc_call(call, fc);
1791 1792
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807
}

/*
 * 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",
1808
	.op		= afs_FS_GiveUpAllCallBacks,
1809 1810 1811 1812 1813 1814 1815
	.deliver	= afs_deliver_fs_give_up_all_callbacks,
	.destructor	= afs_flat_call_destructor,
};

/*
 * Flush all the callbacks we have on a server.
 */
1816 1817
int afs_fs_give_up_all_callbacks(struct afs_net *net,
				 struct afs_server *server,
D
David Howells 已提交
1818
				 struct afs_addr_cursor *ac,
1819
				 struct key *key)
1820 1821 1822 1823 1824 1825
{
	struct afs_call *call;
	__be32 *bp;

	_enter("");

1826
	call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836
	if (!call)
		return -ENOMEM;

	call->key = key;

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

	/* Can't take a ref on server */
1837 1838
	afs_make_call(ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, ac);
1839 1840 1841 1842 1843 1844 1845 1846 1847 1848
}

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

1849
	_enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter));
1850 1851 1852

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

1856
		/* Fall through - and extract the capabilities word count */
1857
	case 1:
1858
		ret = afs_extract_data(call, true);
1859 1860 1861 1862 1863 1864 1865
		if (ret < 0)
			return ret;

		count = ntohl(call->tmp);

		call->count = count;
		call->count2 = count;
1866
		iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
1867 1868
		call->unmarshall++;

1869
		/* Fall through - and extract capabilities words */
1870
	case 2:
1871
		ret = afs_extract_data(call, false);
1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
		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",
1890
	.op		= afs_FS_GetCapabilities,
1891
	.deliver	= afs_deliver_fs_get_capabilities,
1892
	.done		= afs_fileserver_probe_result,
1893
	.destructor	= afs_flat_call_destructor,
1894 1895 1896 1897 1898 1899
};

/*
 * Probe a fileserver for the capabilities that it supports.  This can
 * return up to 196 words.
 */
1900 1901 1902 1903 1904
struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
					 struct afs_server *server,
					 struct afs_addr_cursor *ac,
					 struct key *key,
					 unsigned int server_index)
1905 1906 1907 1908 1909 1910 1911 1912
{
	struct afs_call *call;
	__be32 *bp;

	_enter("");

	call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
	if (!call)
1913
		return ERR_PTR(-ENOMEM);
1914 1915

	call->key = key;
1916 1917
	call->server = afs_get_server(server);
	call->server_index = server_index;
1918
	call->upgrade = true;
1919
	call->async = true;
1920
	call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
1921 1922 1923 1924 1925 1926

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

	/* Can't take a ref on server */
1927
	trace_afs_make_fs_call(call, NULL);
1928 1929
	afs_make_call(ac, call, GFP_NOFS);
	return call;
D
David Howells 已提交
1930
}
1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945

/*
 * Deliver reply data to an FS.FetchStatus with no vnode.
 */
static int afs_deliver_fs_fetch_status(struct afs_call *call)
{
	const __be32 *bp;
	int ret;

	ret = afs_transfer_reply(call);
	if (ret < 0)
		return ret;

	/* unmarshall the reply once we've received all of it */
	bp = call->buffer;
1946
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
1947 1948
	if (ret < 0)
		return ret;
1949 1950
	xdr_decode_AFSCallBack(&bp, call, call->out_scb);
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971

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

/*
 * FS.FetchStatus operation type
 */
static const struct afs_call_type afs_RXFSFetchStatus = {
	.name		= "FS.FetchStatus",
	.op		= afs_FS_FetchStatus,
	.deliver	= afs_deliver_fs_fetch_status,
	.destructor	= afs_flat_call_destructor,
};

/*
 * Fetch the status information for a fid without needing a vnode handle.
 */
int afs_fs_fetch_status(struct afs_fs_cursor *fc,
			struct afs_net *net,
			struct afs_fid *fid,
1972
			struct afs_status_cb *scb,
1973 1974 1975 1976 1977
			struct afs_volsync *volsync)
{
	struct afs_call *call;
	__be32 *bp;

1978
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1979
		return yfs_fs_fetch_status(fc, net, fid, scb, volsync);
1980

1981
	_enter(",%x,{%llx:%llu},,",
1982 1983 1984 1985 1986 1987 1988 1989 1990
	       key_serial(fc->key), fid->vid, fid->vnode);

	call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
	if (!call) {
		fc->ac.error = -ENOMEM;
		return -ENOMEM;
	}

	call->key = fc->key;
1991
	call->out_fid = fid;
1992
	call->out_scb = scb;
1993
	call->out_volsync = volsync;
1994 1995 1996 1997 1998 1999 2000 2001 2002 2003

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSFETCHSTATUS);
	bp[1] = htonl(fid->vid);
	bp[2] = htonl(fid->vnode);
	bp[3] = htonl(fid->unique);

	afs_use_fs_server(call, fc->cbi);
	trace_afs_make_fs_call(call, fid);
2004
	afs_set_fc_call(call, fc);
2005 2006
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
2007 2008 2009 2010 2011 2012 2013
}

/*
 * Deliver reply data to an FS.InlineBulkStatus call
 */
static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
{
2014
	struct afs_status_cb *scb;
2015 2016 2017 2018 2019 2020 2021 2022
	const __be32 *bp;
	u32 tmp;
	int ret;

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

	switch (call->unmarshall) {
	case 0:
2023
		afs_extract_to_tmp(call);
2024 2025 2026
		call->unmarshall++;

		/* Extract the file status count and array in two steps */
2027
		/* Fall through */
2028 2029
	case 1:
		_debug("extract status count");
2030
		ret = afs_extract_data(call, true);
2031 2032 2033 2034 2035 2036
		if (ret < 0)
			return ret;

		tmp = ntohl(call->tmp);
		_debug("status count: %u/%u", tmp, call->count2);
		if (tmp != call->count2)
2037 2038
			return afs_protocol_error(call, -EBADMSG,
						  afs_eproto_ibulkst_count);
2039 2040 2041 2042

		call->count = 0;
		call->unmarshall++;
	more_counts:
2043
		afs_extract_to_buf(call, 21 * sizeof(__be32));
2044

2045
		/* Fall through */
2046 2047
	case 2:
		_debug("extract status array %u", call->count);
2048
		ret = afs_extract_data(call, true);
2049 2050 2051 2052
		if (ret < 0)
			return ret;

		bp = call->buffer;
2053
		scb = &call->out_scb[call->count];
2054
		ret = xdr_decode_AFSFetchStatus(&bp, call, scb);
2055 2056
		if (ret < 0)
			return ret;
2057 2058 2059 2060 2061 2062 2063

		call->count++;
		if (call->count < call->count2)
			goto more_counts;

		call->count = 0;
		call->unmarshall++;
2064
		afs_extract_to_tmp(call);
2065 2066

		/* Extract the callback count and array in two steps */
2067
		/* Fall through */
2068 2069
	case 3:
		_debug("extract CB count");
2070
		ret = afs_extract_data(call, true);
2071 2072 2073 2074 2075 2076
		if (ret < 0)
			return ret;

		tmp = ntohl(call->tmp);
		_debug("CB count: %u", tmp);
		if (tmp != call->count2)
2077 2078
			return afs_protocol_error(call, -EBADMSG,
						  afs_eproto_ibulkst_cb_count);
2079 2080 2081
		call->count = 0;
		call->unmarshall++;
	more_cbs:
2082
		afs_extract_to_buf(call, 3 * sizeof(__be32));
2083

2084
		/* Fall through */
2085 2086
	case 4:
		_debug("extract CB array");
2087
		ret = afs_extract_data(call, true);
2088 2089 2090 2091 2092
		if (ret < 0)
			return ret;

		_debug("unmarshall CB array");
		bp = call->buffer;
2093
		scb = &call->out_scb[call->count];
2094
		xdr_decode_AFSCallBack(&bp, call, scb);
2095 2096 2097 2098
		call->count++;
		if (call->count < call->count2)
			goto more_cbs;

2099
		afs_extract_to_buf(call, 6 * sizeof(__be32));
2100 2101
		call->unmarshall++;

2102
		/* Fall through */
2103
	case 5:
2104
		ret = afs_extract_data(call, false);
2105 2106 2107 2108
		if (ret < 0)
			return ret;

		bp = call->buffer;
2109
		xdr_decode_AFSVolSync(&bp, call->out_volsync);
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136

		call->unmarshall++;

	case 6:
		break;
	}

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

/*
 * 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,
	.destructor	= afs_flat_call_destructor,
};

/*
 * Fetch the status information for up to 50 files
 */
int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
			      struct afs_net *net,
			      struct afs_fid *fids,
2137
			      struct afs_status_cb *statuses,
2138 2139 2140 2141 2142 2143 2144
			      unsigned int nr_fids,
			      struct afs_volsync *volsync)
{
	struct afs_call *call;
	__be32 *bp;
	int i;

2145
	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
2146
		return yfs_fs_inline_bulk_status(fc, net, fids, statuses,
2147 2148
						 nr_fids, volsync);

2149
	_enter(",%x,{%llx:%llu},%u",
2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160
	       key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);

	call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
				   (2 + nr_fids * 3) * 4,
				   21 * 4);
	if (!call) {
		fc->ac.error = -ENOMEM;
		return -ENOMEM;
	}

	call->key = fc->key;
2161
	call->out_scb = statuses;
2162
	call->out_volsync = volsync;
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176
	call->count2 = nr_fids;

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSINLINEBULKSTATUS);
	*bp++ = htonl(nr_fids);
	for (i = 0; i < nr_fids; i++) {
		*bp++ = htonl(fids[i].vid);
		*bp++ = htonl(fids[i].vnode);
		*bp++ = htonl(fids[i].unique);
	}

	afs_use_fs_server(call, fc->cbi);
	trace_afs_make_fs_call(call, &fids[0]);
2177
	afs_set_fc_call(call, fc);
2178 2179
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
2180
}
D
David Howells 已提交
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210

/*
 * deliver reply data to an FS.FetchACL
 */
static int afs_deliver_fs_fetch_acl(struct afs_call *call)
{
	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++;

		/* 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;
2211
		call->ret_acl = acl;
D
David Howells 已提交
2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231
		acl->size = call->count2;
		afs_extract_begin(call, acl->data, size);
		call->unmarshall++;

		/* 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++;

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

		bp = call->buffer;
2232
		ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
D
David Howells 已提交
2233 2234
		if (ret < 0)
			return ret;
2235
		xdr_decode_AFSVolSync(&bp, call->out_volsync);
D
David Howells 已提交
2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248

		call->unmarshall++;

	case 4:
		break;
	}

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

static void afs_destroy_fs_fetch_acl(struct afs_call *call)
{
2249
	kfree(call->ret_acl);
D
David Howells 已提交
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265
	afs_flat_call_destructor(call);
}

/*
 * 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,
	.destructor	= afs_destroy_fs_fetch_acl,
};

/*
 * Fetch the ACL for a file.
 */
2266 2267
struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc,
				 struct afs_status_cb *scb)
D
David Howells 已提交
2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283
{
	struct afs_vnode *vnode = fc->vnode;
	struct afs_call *call;
	struct afs_net *net = afs_v2net(vnode);
	__be32 *bp;

	_enter(",%x,{%llx:%llu},,",
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);

	call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4);
	if (!call) {
		fc->ac.error = -ENOMEM;
		return ERR_PTR(-ENOMEM);
	}

	call->key = fc->key;
2284
	call->ret_acl = NULL;
2285
	call->out_scb = scb;
2286
	call->out_volsync = NULL;
D
David Howells 已提交
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSFETCHACL);
	bp[1] = htonl(vnode->fid.vid);
	bp[2] = htonl(vnode->fid.vnode);
	bp[3] = htonl(vnode->fid.unique);

	afs_use_fs_server(call, fc->cbi);
	trace_afs_make_fs_call(call, &vnode->fid);
	afs_make_call(&fc->ac, call, GFP_KERNEL);
	return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
}
J
Joe Gorse 已提交
2300

2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314
/*
 * Deliver reply data to any operation that returns file status and volume
 * sync.
 */
static int afs_deliver_fs_file_status_and_vol(struct afs_call *call)
{
	const __be32 *bp;
	int ret;

	ret = afs_transfer_reply(call);
	if (ret < 0)
		return ret;

	bp = call->buffer;
2315
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
2316 2317 2318 2319 2320 2321 2322 2323
	if (ret < 0)
		return ret;
	xdr_decode_AFSVolSync(&bp, call->out_volsync);

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

J
Joe Gorse 已提交
2324 2325 2326 2327 2328 2329
/*
 * FS.StoreACL operation type
 */
static const struct afs_call_type afs_RXFSStoreACL = {
	.name		= "FS.StoreACL",
	.op		= afs_FS_StoreACL,
2330
	.deliver	= afs_deliver_fs_file_status_and_vol,
J
Joe Gorse 已提交
2331 2332 2333 2334 2335 2336
	.destructor	= afs_flat_call_destructor,
};

/*
 * Fetch the ACL for a file.
 */
2337 2338
int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl,
		     struct afs_status_cb *scb)
J
Joe Gorse 已提交
2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357
{
	struct afs_vnode *vnode = fc->vnode;
	struct afs_call *call;
	struct afs_net *net = afs_v2net(vnode);
	size_t size;
	__be32 *bp;

	_enter(",%x,{%llx:%llu},,",
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);

	size = round_up(acl->size, 4);
	call = afs_alloc_flat_call(net, &afs_RXFSStoreACL,
				   5 * 4 + size, (21 + 6) * 4);
	if (!call) {
		fc->ac.error = -ENOMEM;
		return -ENOMEM;
	}

	call->key = fc->key;
2358
	call->out_scb = scb;
2359
	call->out_volsync = NULL;
J
Joe Gorse 已提交
2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374

	/* marshall the parameters */
	bp = call->request;
	bp[0] = htonl(FSSTOREACL);
	bp[1] = htonl(vnode->fid.vid);
	bp[2] = htonl(vnode->fid.vnode);
	bp[3] = htonl(vnode->fid.unique);
	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);

	trace_afs_make_fs_call(call, &vnode->fid);
	afs_make_call(&fc->ac, call, GFP_KERNEL);
	return afs_wait_for_call_to_complete(call, &fc->ac);
2375
}