fsclient.c 56.1 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
			scb->have_error = true;
87
			return 0;
88 89
		}

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

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

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

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

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

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

	data_version  = (u64)ntohl(xdr->data_version_lo);
	data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
130
	status->data_version = data_version;
131
	scb->have_status = true;
132

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

313
	afs_use_fs_server(call, fc->cbi);
314
	trace_afs_make_fs_call(call, &vnode->fid);
315

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

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

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

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

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

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

360 361
		call->unmarshall++;

362
	begin_page:
363
		ASSERTCMP(req->index, <, req->nr_pages);
364 365
		if (req->remain > PAGE_SIZE - req->offset)
			size = PAGE_SIZE - req->offset;
366 367
		else
			size = req->remain;
368 369 370 371 372
		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);
373

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

379
		ret = afs_extract_data(call, true);
380 381
		if (ret < 0)
			return ret;
382 383 384 385 386
		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;
387
			if (req->page_done)
388
				req->page_done(req);
D
David Howells 已提交
389
			req->index++;
390
			if (req->remain > 0)
391
				goto begin_page;
392
		}
393 394 395 396

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

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

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

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

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

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

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

428 429 430
		req->data_version = call->out_scb->status.data_version;
		req->file_size = call->out_scb->status.size;

431
		call->unmarshall++;
L
Linus Torvalds 已提交
432

433
	case 5:
434
		break;
L
Linus Torvalds 已提交
435 436
	}

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

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

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

	afs_put_read(req);
	afs_flat_call_destructor(call);
}

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

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

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

	_enter("");

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

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

	/* 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);
504 505
	bp[4] = htonl(upper_32_bits(req->pos));
	bp[5] = htonl(lower_32_bits(req->pos));
D
David Howells 已提交
506
	bp[6] = 0;
507
	bp[7] = htonl(lower_32_bits(req->len));
D
David Howells 已提交
508

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

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

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

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

537
	_enter("");
L
Linus Torvalds 已提交
538

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

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

	/* marshall the parameters */
549 550 551 552 553
	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);
554 555
	bp[4] = htonl(lower_32_bits(req->pos));
	bp[5] = htonl(lower_32_bits(req->len));
L
Linus Torvalds 已提交
556

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

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

573
	ret = afs_transfer_reply(call);
574 575
	if (ret < 0)
		return ret;
576 577 578

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

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

/*
 * FS.CreateFile and FS.MakeDir operation type
 */
596 597 598 599 600 601 602 603 604 605
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,
606 607 608 609 610 611 612
	.deliver	= afs_deliver_fs_create_vnode,
	.destructor	= afs_flat_call_destructor,
};

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

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

635 636 637 638 639 640
	_enter("");

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

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

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

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

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

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

688
	ret = afs_transfer_reply(call);
689 690
	if (ret < 0)
		return ret;
691 692 693

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

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

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

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

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

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

735 736 737 738 739 740
	_enter("");

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

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

747
	call->key = fc->key;
748
	call->out_dir_scb = dvnode_scb;
749 750 751 752

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

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

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

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

781
	ret = afs_transfer_reply(call);
782 783
	if (ret < 0)
		return ret;
784 785 786

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

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

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

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

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

826 827 828 829 830 831
	_enter("");

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

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

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

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

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

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

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

874
	ret = afs_transfer_reply(call);
875 876
	if (ret < 0)
		return ret;
877 878 879

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

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

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

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

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

923 924 925 926 927 928 929 930 931 932
	_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);

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

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

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(FSSYMLINK);
946 947 948
	*bp++ = htonl(dvnode->fid.vid);
	*bp++ = htonl(dvnode->fid.vnode);
	*bp++ = htonl(dvnode->fid.unique);
949 950 951 952 953 954 955 956 957 958 959 960 961 962
	*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;
	}
963
	*bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
964
	*bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */
965 966 967 968 969
	*bp++ = 0; /* owner */
	*bp++ = 0; /* group */
	*bp++ = htonl(S_IRWXUGO); /* unix mode */
	*bp++ = 0; /* segment size */

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

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

985
	ret = afs_transfer_reply(call);
986 987
	if (ret < 0)
		return ret;
988 989 990

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

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

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

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

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

1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
	_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;

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

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

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

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

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

1098
	_enter("");
1099

1100
	ret = afs_transfer_reply(call);
1101 1102
	if (ret < 0)
		return ret;
1103 1104 1105

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

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

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

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

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

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

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

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

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

1172 1173
	*bp++ = htonl(AFS_SET_MTIME); /* mask */
	*bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
D
David Howells 已提交
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
	*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);

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

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

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

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

1212
	size = (loff_t)to - (loff_t)offset;
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
	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 已提交
1226
	if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
1227
		return afs_fs_store_data64(fc, mapping, first, last, offset, to,
1228
					   size, pos, i_size, scb);
1229

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

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

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

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

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

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

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

1278
	_enter("");
1279

1280
	ret = afs_transfer_reply(call);
1281 1282
	if (ret < 0)
		return ret;
1283 1284 1285

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

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

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

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

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

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

	ASSERT(attr->ia_valid & ATTR_SIZE);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		call->unmarshall++;

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

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

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

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

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

D
David Howells 已提交
1608 1609
	_enter("");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

D
David Howells 已提交
1698 1699
	_enter("");

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

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

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

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

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

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

D
David Howells 已提交
1736 1737
	_enter("");

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

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

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

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

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

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

D
David Howells 已提交
1773 1774
	_enter("");

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

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

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

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

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

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

	_enter("");

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

	call->key = key;

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

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

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

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

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

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

		count = ntohl(call->tmp);

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

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

/*
 * Probe a fileserver for the capabilities that it supports.  This can
 * return up to 196 words.
 */
1902 1903 1904 1905 1906
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)
1907 1908 1909 1910 1911 1912 1913 1914
{
	struct afs_call *call;
	__be32 *bp;

	_enter("");

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

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

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

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

/*
 * 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;
1948
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
1949 1950
	if (ret < 0)
		return ret;
1951 1952
	xdr_decode_AFSCallBack(&bp, call, call->out_scb);
	xdr_decode_AFSVolSync(&bp, call->out_volsync);
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973

	_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,
1974
			struct afs_status_cb *scb,
1975 1976 1977 1978 1979
			struct afs_volsync *volsync)
{
	struct afs_call *call;
	__be32 *bp;

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

1983
	_enter(",%x,{%llx:%llu},,",
1984 1985 1986 1987 1988 1989 1990 1991 1992
	       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;
1993
	call->out_fid = fid;
1994
	call->out_scb = scb;
1995
	call->out_volsync = volsync;
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005

	/* 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);
2006
	afs_set_fc_call(call, fc);
2007 2008
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
2009 2010 2011 2012 2013 2014 2015
}

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

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

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

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

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

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

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

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

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

		call->count = 0;
		call->unmarshall++;
2066
		afs_extract_to_tmp(call);
2067 2068

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

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

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

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

2101
		afs_extract_to_buf(call, 6 * sizeof(__be32));
2102 2103
		call->unmarshall++;

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

		bp = call->buffer;
2111
		xdr_decode_AFSVolSync(&bp, call->out_volsync);
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 2137 2138

		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,
2139
			      struct afs_status_cb *statuses,
2140 2141 2142 2143 2144 2145 2146
			      unsigned int nr_fids,
			      struct afs_volsync *volsync)
{
	struct afs_call *call;
	__be32 *bp;
	int i;

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

2151
	_enter(",%x,{%llx:%llu},%u",
2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162
	       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;
2163
	call->out_scb = statuses;
2164
	call->out_volsync = volsync;
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178
	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]);
2179
	afs_set_fc_call(call, fc);
2180 2181
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
2182
}
D
David Howells 已提交
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 2211 2212

/*
 * 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;
2213
		call->ret_acl = acl;
D
David Howells 已提交
2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233
		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;
2234
		ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
D
David Howells 已提交
2235 2236
		if (ret < 0)
			return ret;
2237
		xdr_decode_AFSVolSync(&bp, call->out_volsync);
D
David Howells 已提交
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250

		call->unmarshall++;

	case 4:
		break;
	}

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

static void afs_destroy_fs_fetch_acl(struct afs_call *call)
{
2251
	kfree(call->ret_acl);
D
David Howells 已提交
2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267
	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.
 */
2268 2269
struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc,
				 struct afs_status_cb *scb)
D
David Howells 已提交
2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285
{
	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;
2286
	call->ret_acl = NULL;
2287
	call->out_scb = scb;
2288
	call->out_volsync = NULL;
D
David Howells 已提交
2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301

	/* 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 已提交
2302

2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316
/*
 * 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;
2317
	ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
2318 2319 2320 2321 2322 2323 2324 2325
	if (ret < 0)
		return ret;
	xdr_decode_AFSVolSync(&bp, call->out_volsync);

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

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

/*
 * Fetch the ACL for a file.
 */
2339 2340
int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl,
		     struct afs_status_cb *scb)
J
Joe Gorse 已提交
2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
{
	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;
2360
	call->out_scb = scb;
2361
	call->out_volsync = NULL;
J
Joe Gorse 已提交
2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376

	/* 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);
2377
}