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

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

18 19
static const struct afs_fid afs_zero_fid;

20
static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
21
{
22
	call->cbi = afs_get_cb_interest(cbi);
23 24
}

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

71 72
	abort_code = ntohl(xdr->abort_code);

D
David Howells 已提交
73
	if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
74 75 76 77 78 79 80 81
		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;
82
			scb->have_error = true;
83
			return 0;
84 85
		}

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

90 91
	if (abort_code != 0 && inline_error) {
		status->abort_code = abort_code;
92
		return 0;
93 94
	}

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

106 107 108 109 110 111 112 113
	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 已提交
114

115 116 117 118
	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 已提交
119 120 121

	size  = (u64)ntohl(xdr->size_lo);
	size |= (u64)ntohl(xdr->size_hi) << 32;
122
	status->size = size;
D
David Howells 已提交
123 124 125

	data_version  = (u64)ntohl(xdr->data_version_lo);
	data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
126
	status->data_version = data_version;
127
	scb->have_status = true;
128

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

309
	afs_use_fs_server(call, fc->cbi);
310
	trace_afs_make_fs_call(call, &vnode->fid);
311

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

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

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

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

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

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

356 357
		call->unmarshall++;

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

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

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

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

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

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

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

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

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

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

424 425 426
		req->data_version = call->out_scb->status.data_version;
		req->file_size = call->out_scb->status.size;

427
		call->unmarshall++;
L
Linus Torvalds 已提交
428

429
	case 5:
430
		break;
L
Linus Torvalds 已提交
431 432
	}

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

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

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

	afs_put_read(req);
	afs_flat_call_destructor(call);
}

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

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

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

	_enter("");

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

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

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

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

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

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

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

533
	_enter("");
L
Linus Torvalds 已提交
534

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

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

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

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

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

569
	ret = afs_transfer_reply(call);
570 571
	if (ret < 0)
		return ret;
572 573 574

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

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

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

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

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

631 632 633 634 635 636
	_enter("");

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

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

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

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

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

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

684
	ret = afs_transfer_reply(call);
685 686
	if (ret < 0)
		return ret;
687 688 689

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

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

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

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

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

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

731 732 733 734 735 736
	_enter("");

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

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

743
	call->key = fc->key;
744
	call->out_dir_scb = dvnode_scb;
745 746 747 748

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

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

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

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

777
	ret = afs_transfer_reply(call);
778 779
	if (ret < 0)
		return ret;
780 781 782

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

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

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

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

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

822 823 824 825 826 827
	_enter("");

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

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

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

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

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

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

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

870
	ret = afs_transfer_reply(call);
871 872
	if (ret < 0)
		return ret;
873 874 875

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

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

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

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

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

919 920 921 922 923 924 925 926 927 928
	_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);

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

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

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

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

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

981
	ret = afs_transfer_reply(call);
982 983
	if (ret < 0)
		return ret;
984 985 986

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

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

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

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

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

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
	_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;

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

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

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

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

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

1094
	_enter("");
1095

1096
	ret = afs_transfer_reply(call);
1097 1098
	if (ret < 0)
		return ret;
1099 1100 1101

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1274
	_enter("");
1275

1276
	ret = afs_transfer_reply(call);
1277 1278
	if (ret < 0)
		return ret;
1279 1280 1281

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

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

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

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

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

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

	ASSERT(attr->ia_valid & ATTR_SIZE);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		call->unmarshall++;

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

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

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

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

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

D
David Howells 已提交
1604 1605
	_enter("");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

D
David Howells 已提交
1694 1695
	_enter("");

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

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

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

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

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

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

D
David Howells 已提交
1732 1733
	_enter("");

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

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

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

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

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

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

D
David Howells 已提交
1769 1770
	_enter("");

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

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

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

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

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

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

	_enter("");

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

	call->key = key;

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

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

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

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

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

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

		count = ntohl(call->tmp);

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

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

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

	_enter("");

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

	call->key = key;
D
David Howells 已提交
1914
	call->server = afs_get_server(server, afs_server_trace_get_caps);
1915
	call->server_index = server_index;
1916
	call->upgrade = true;
1917
	call->async = true;
1918
	call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
1919 1920 1921 1922 1923 1924

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

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

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

	_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,
1970
			struct afs_status_cb *scb,
1971 1972 1973 1974 1975
			struct afs_volsync *volsync)
{
	struct afs_call *call;
	__be32 *bp;

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

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

	/* 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);
2002
	afs_set_fc_call(call, fc);
2003 2004
	afs_make_call(&fc->ac, call, GFP_NOFS);
	return afs_wait_for_call_to_complete(call, &fc->ac);
2005 2006 2007 2008 2009 2010 2011
}

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

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

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

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

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

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

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

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

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

		call->count = 0;
		call->unmarshall++;
2062
		afs_extract_to_tmp(call);
2063 2064

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

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

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

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

2097
		afs_extract_to_buf(call, 6 * sizeof(__be32));
2098 2099
		call->unmarshall++;

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

		bp = call->buffer;
2107
		xdr_decode_AFSVolSync(&bp, call->out_volsync);
2108 2109 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

		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,
2135
			      struct afs_status_cb *statuses,
2136 2137 2138 2139 2140 2141 2142
			      unsigned int nr_fids,
			      struct afs_volsync *volsync)
{
	struct afs_call *call;
	__be32 *bp;
	int i;

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

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

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

		call->unmarshall++;

	case 4:
		break;
	}

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

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

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

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

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

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

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

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