brintos

brintos / linux-shallow public Read only

0
0
Text · 48.1 KiB · 024227a Raw
1982 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* YFS File Server client stubs3 *4 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.5 * Written by David Howells (dhowells@redhat.com)6 */7 8#include <linux/init.h>9#include <linux/slab.h>10#include <linux/sched.h>11#include <linux/circ_buf.h>12#include <linux/iversion.h>13#include "internal.h"14#include "afs_fs.h"15#include "xdr_fs.h"16#include "protocol_yfs.h"17 18#define xdr_size(x) (sizeof(*x) / sizeof(__be32))19 20static void xdr_decode_YFSFid(const __be32 **_bp, struct afs_fid *fid)21{22	const struct yfs_xdr_YFSFid *x = (const void *)*_bp;23 24	fid->vid	= xdr_to_u64(x->volume);25	fid->vnode	= xdr_to_u64(x->vnode.lo);26	fid->vnode_hi	= ntohl(x->vnode.hi);27	fid->unique	= ntohl(x->vnode.unique);28	*_bp += xdr_size(x);29}30 31static __be32 *xdr_encode_u32(__be32 *bp, u32 n)32{33	*bp++ = htonl(n);34	return bp;35}36 37static __be32 *xdr_encode_u64(__be32 *bp, u64 n)38{39	struct yfs_xdr_u64 *x = (void *)bp;40 41	*x = u64_to_xdr(n);42	return bp + xdr_size(x);43}44 45static __be32 *xdr_encode_YFSFid(__be32 *bp, struct afs_fid *fid)46{47	struct yfs_xdr_YFSFid *x = (void *)bp;48 49	x->volume	= u64_to_xdr(fid->vid);50	x->vnode.lo	= u64_to_xdr(fid->vnode);51	x->vnode.hi	= htonl(fid->vnode_hi);52	x->vnode.unique	= htonl(fid->unique);53	return bp + xdr_size(x);54}55 56static size_t xdr_strlen(unsigned int len)57{58	return sizeof(__be32) + round_up(len, sizeof(__be32));59}60 61static __be32 *xdr_encode_string(__be32 *bp, const char *p, unsigned int len)62{63	bp = xdr_encode_u32(bp, len);64	bp = memcpy(bp, p, len);65	if (len & 3) {66		unsigned int pad = 4 - (len & 3);67 68		memset((u8 *)bp + len, 0, pad);69		len += pad;70	}71 72	return bp + len / sizeof(__be32);73}74 75static __be32 *xdr_encode_name(__be32 *bp, const struct qstr *p)76{77	return xdr_encode_string(bp, p->name, p->len);78}79 80static s64 linux_to_yfs_time(const struct timespec64 *t)81{82	/* Convert to 100ns intervals. */83	return (u64)t->tv_sec * 10000000 + t->tv_nsec/100;84}85 86static __be32 *xdr_encode_YFSStoreStatus(__be32 *bp, mode_t *mode,87					 const struct timespec64 *t)88{89	struct yfs_xdr_YFSStoreStatus *x = (void *)bp;90	mode_t masked_mode = mode ? *mode & S_IALLUGO : 0;91	s64 mtime = linux_to_yfs_time(t);92	u32 mask = AFS_SET_MTIME;93 94	mask |= mode ? AFS_SET_MODE : 0;95 96	x->mask		= htonl(mask);97	x->mode		= htonl(masked_mode);98	x->mtime_client	= u64_to_xdr(mtime);99	x->owner	= u64_to_xdr(0);100	x->group	= u64_to_xdr(0);101	return bp + xdr_size(x);102}103 104/*105 * Convert a signed 100ns-resolution 64-bit time into a timespec.106 */107static struct timespec64 yfs_time_to_linux(s64 t)108{109	struct timespec64 ts;110	u64 abs_t;111 112	/*113	 * Unfortunately can not use normal 64 bit division on 32 bit arch, but114	 * the alternative, do_div, does not work with negative numbers so have115	 * to special case them116	 */117	if (t < 0) {118		abs_t = -t;119		ts.tv_nsec = (time64_t)(do_div(abs_t, 10000000) * 100);120		ts.tv_nsec = -ts.tv_nsec;121		ts.tv_sec = -abs_t;122	} else {123		abs_t = t;124		ts.tv_nsec = (time64_t)do_div(abs_t, 10000000) * 100;125		ts.tv_sec = abs_t;126	}127 128	return ts;129}130 131static struct timespec64 xdr_to_time(const struct yfs_xdr_u64 xdr)132{133	s64 t = xdr_to_u64(xdr);134 135	return yfs_time_to_linux(t);136}137 138static void yfs_check_req(struct afs_call *call, __be32 *bp)139{140	size_t len = (void *)bp - call->request;141 142	if (len > call->request_size)143		pr_err("kAFS: %s: Request buffer overflow (%zu>%u)\n",144		       call->type->name, len, call->request_size);145	else if (len < call->request_size)146		pr_warn("kAFS: %s: Request buffer underflow (%zu<%u)\n",147			call->type->name, len, call->request_size);148}149 150/*151 * Dump a bad file status record.152 */153static void xdr_dump_bad(const __be32 *bp)154{155	__be32 x[4];156	int i;157 158	pr_notice("YFS XDR: Bad status record\n");159	for (i = 0; i < 6 * 4 * 4; i += 16) {160		memcpy(x, bp, 16);161		bp += 4;162		pr_notice("%03x: %08x %08x %08x %08x\n",163			  i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));164	}165 166	memcpy(x, bp, 8);167	pr_notice("0x60: %08x %08x\n", ntohl(x[0]), ntohl(x[1]));168}169 170/*171 * Decode a YFSFetchStatus block172 */173static void xdr_decode_YFSFetchStatus(const __be32 **_bp,174				      struct afs_call *call,175				      struct afs_status_cb *scb)176{177	const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;178	struct afs_file_status *status = &scb->status;179	u32 type;180 181	status->abort_code = ntohl(xdr->abort_code);182	if (status->abort_code != 0) {183		if (status->abort_code == VNOVNODE)184			status->nlink = 0;185		scb->have_error = true;186		goto advance;187	}188 189	type = ntohl(xdr->type);190	switch (type) {191	case AFS_FTYPE_FILE:192	case AFS_FTYPE_DIR:193	case AFS_FTYPE_SYMLINK:194		status->type = type;195		break;196	default:197		goto bad;198	}199 200	status->nlink		= ntohl(xdr->nlink);201	status->author		= xdr_to_u64(xdr->author);202	status->owner		= xdr_to_u64(xdr->owner);203	status->caller_access	= ntohl(xdr->caller_access); /* Ticket dependent */204	status->anon_access	= ntohl(xdr->anon_access);205	status->mode		= ntohl(xdr->mode) & S_IALLUGO;206	status->group		= xdr_to_u64(xdr->group);207	status->lock_count	= ntohl(xdr->lock_count);208 209	status->mtime_client	= xdr_to_time(xdr->mtime_client);210	status->mtime_server	= xdr_to_time(xdr->mtime_server);211	status->size		= xdr_to_u64(xdr->size);212	status->data_version	= xdr_to_u64(xdr->data_version);213	scb->have_status	= true;214advance:215	*_bp += xdr_size(xdr);216	return;217 218bad:219	xdr_dump_bad(*_bp);220	afs_protocol_error(call, afs_eproto_bad_status);221	goto advance;222}223 224/*225 * Decode a YFSCallBack block226 */227static void xdr_decode_YFSCallBack(const __be32 **_bp,228				   struct afs_call *call,229				   struct afs_status_cb *scb)230{231	struct yfs_xdr_YFSCallBack *x = (void *)*_bp;232	struct afs_callback *cb = &scb->callback;233	ktime_t cb_expiry;234 235	cb_expiry = ktime_add(call->issue_time, xdr_to_u64(x->expiration_time) * 100);236	cb->expires_at	= ktime_divns(cb_expiry, NSEC_PER_SEC);237	scb->have_cb	= true;238	*_bp += xdr_size(x);239}240 241/*242 * Decode a YFSVolSync block243 */244static void xdr_decode_YFSVolSync(const __be32 **_bp,245				  struct afs_volsync *volsync)246{247	struct yfs_xdr_YFSVolSync *x = (void *)*_bp;248	u64 creation, update;249 250	if (volsync) {251		creation = xdr_to_u64(x->vol_creation_date);252		do_div(creation, 10 * 1000 * 1000);253		volsync->creation = creation;254		update = xdr_to_u64(x->vol_update_date);255		do_div(update, 10 * 1000 * 1000);256		volsync->update = update;257	}258 259	*_bp += xdr_size(x);260}261 262/*263 * Encode the requested attributes into a YFSStoreStatus block264 */265static __be32 *xdr_encode_YFS_StoreStatus(__be32 *bp, struct iattr *attr)266{267	struct yfs_xdr_YFSStoreStatus *x = (void *)bp;268	s64 mtime = 0, owner = 0, group = 0;269	u32 mask = 0, mode = 0;270 271	mask = 0;272	if (attr->ia_valid & ATTR_MTIME) {273		mask |= AFS_SET_MTIME;274		mtime = linux_to_yfs_time(&attr->ia_mtime);275	}276 277	if (attr->ia_valid & ATTR_UID) {278		mask |= AFS_SET_OWNER;279		owner = from_kuid(&init_user_ns, attr->ia_uid);280	}281 282	if (attr->ia_valid & ATTR_GID) {283		mask |= AFS_SET_GROUP;284		group = from_kgid(&init_user_ns, attr->ia_gid);285	}286 287	if (attr->ia_valid & ATTR_MODE) {288		mask |= AFS_SET_MODE;289		mode = attr->ia_mode & S_IALLUGO;290	}291 292	x->mask		= htonl(mask);293	x->mode		= htonl(mode);294	x->mtime_client	= u64_to_xdr(mtime);295	x->owner	= u64_to_xdr(owner);296	x->group	= u64_to_xdr(group);297	return bp + xdr_size(x);298}299 300/*301 * Decode a YFSFetchVolumeStatus block.302 */303static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp,304					    struct afs_volume_status *vs)305{306	const struct yfs_xdr_YFSFetchVolumeStatus *x = (const void *)*_bp;307	u32 flags;308 309	vs->vid			= xdr_to_u64(x->vid);310	vs->parent_id		= xdr_to_u64(x->parent_id);311	flags			= ntohl(x->flags);312	vs->online		= flags & yfs_FVSOnline;313	vs->in_service		= flags & yfs_FVSInservice;314	vs->blessed		= flags & yfs_FVSBlessed;315	vs->needs_salvage	= flags & yfs_FVSNeedsSalvage;316	vs->type		= ntohl(x->type);317	vs->min_quota		= 0;318	vs->max_quota		= xdr_to_u64(x->max_quota);319	vs->blocks_in_use	= xdr_to_u64(x->blocks_in_use);320	vs->part_blocks_avail	= xdr_to_u64(x->part_blocks_avail);321	vs->part_max_blocks	= xdr_to_u64(x->part_max_blocks);322	vs->vol_copy_date	= xdr_to_u64(x->vol_copy_date);323	vs->vol_backup_date	= xdr_to_u64(x->vol_backup_date);324	*_bp += sizeof(*x) / sizeof(__be32);325}326 327/*328 * Deliver reply data to operations that just return a file status and a volume329 * sync record.330 */331static int yfs_deliver_status_and_volsync(struct afs_call *call)332{333	struct afs_operation *op = call->op;334	const __be32 *bp;335	int ret;336 337	ret = afs_transfer_reply(call);338	if (ret < 0)339		return ret;340 341	bp = call->buffer;342	xdr_decode_YFSFetchStatus(&bp, call, &op->file[0].scb);343	xdr_decode_YFSVolSync(&bp, &op->volsync);344 345	_leave(" = 0 [done]");346	return 0;347}348 349/*350 * Deliver reply data to an YFS.FetchData64.351 */352static int yfs_deliver_fs_fetch_data64(struct afs_call *call)353{354	struct afs_operation *op = call->op;355	struct afs_vnode_param *vp = &op->file[0];356	struct afs_read *req = op->fetch.req;357	const __be32 *bp;358	size_t count_before;359	int ret;360 361	_enter("{%u,%zu, %zu/%llu}",362	       call->unmarshall, call->iov_len, iov_iter_count(call->iter),363	       req->actual_len);364 365	switch (call->unmarshall) {366	case 0:367		req->actual_len = 0;368		afs_extract_to_tmp64(call);369		call->unmarshall++;370		fallthrough;371 372		/* Extract the returned data length into ->actual_len.  This373		 * may indicate more or less data than was requested will be374		 * returned.375		 */376	case 1:377		_debug("extract data length");378		ret = afs_extract_data(call, true);379		if (ret < 0)380			return ret;381 382		req->actual_len = be64_to_cpu(call->tmp64);383		_debug("DATA length: %llu", req->actual_len);384 385		if (req->actual_len == 0)386			goto no_more_data;387 388		call->iter = req->iter;389		call->iov_len = min(req->actual_len, req->len);390		call->unmarshall++;391		fallthrough;392 393		/* extract the returned data */394	case 2:395		count_before = call->iov_len;396		_debug("extract data %zu/%llu", count_before, req->actual_len);397 398		ret = afs_extract_data(call, true);399		if (req->subreq) {400			req->subreq->transferred += count_before - call->iov_len;401			netfs_read_subreq_progress(req->subreq, false);402		}403		if (ret < 0)404			return ret;405 406		call->iter = &call->def_iter;407		if (req->actual_len <= req->len)408			goto no_more_data;409 410		/* Discard any excess data the server gave us */411		afs_extract_discard(call, req->actual_len - req->len);412		call->unmarshall = 3;413		fallthrough;414 415	case 3:416		_debug("extract discard %zu/%llu",417		       iov_iter_count(call->iter), req->actual_len - req->len);418 419		ret = afs_extract_data(call, true);420		if (ret < 0)421			return ret;422 423	no_more_data:424		call->unmarshall = 4;425		afs_extract_to_buf(call,426				   sizeof(struct yfs_xdr_YFSFetchStatus) +427				   sizeof(struct yfs_xdr_YFSCallBack) +428				   sizeof(struct yfs_xdr_YFSVolSync));429		fallthrough;430 431		/* extract the metadata */432	case 4:433		ret = afs_extract_data(call, false);434		if (ret < 0)435			return ret;436 437		bp = call->buffer;438		xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);439		xdr_decode_YFSCallBack(&bp, call, &vp->scb);440		xdr_decode_YFSVolSync(&bp, &op->volsync);441 442		req->data_version = vp->scb.status.data_version;443		req->file_size = vp->scb.status.size;444 445		call->unmarshall++;446		fallthrough;447 448	case 5:449		break;450	}451 452	_leave(" = 0 [done]");453	return 0;454}455 456/*457 * YFS.FetchData64 operation type458 */459static const struct afs_call_type yfs_RXYFSFetchData64 = {460	.name		= "YFS.FetchData64",461	.op		= yfs_FS_FetchData64,462	.deliver	= yfs_deliver_fs_fetch_data64,463	.destructor	= afs_flat_call_destructor,464};465 466/*467 * Fetch data from a file.468 */469void yfs_fs_fetch_data(struct afs_operation *op)470{471	struct afs_vnode_param *vp = &op->file[0];472	struct afs_read *req = op->fetch.req;473	struct afs_call *call;474	__be32 *bp;475 476	_enter(",%x,{%llx:%llu},%llx,%llx",477	       key_serial(op->key), vp->fid.vid, vp->fid.vnode,478	       req->pos, req->len);479 480	call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchData64,481				   sizeof(__be32) * 2 +482				   sizeof(struct yfs_xdr_YFSFid) +483				   sizeof(struct yfs_xdr_u64) * 2,484				   sizeof(struct yfs_xdr_YFSFetchStatus) +485				   sizeof(struct yfs_xdr_YFSCallBack) +486				   sizeof(struct yfs_xdr_YFSVolSync));487	if (!call)488		return afs_op_nomem(op);489 490	req->call_debug_id = call->debug_id;491 492	/* marshall the parameters */493	bp = call->request;494	bp = xdr_encode_u32(bp, YFSFETCHDATA64);495	bp = xdr_encode_u32(bp, 0); /* RPC flags */496	bp = xdr_encode_YFSFid(bp, &vp->fid);497	bp = xdr_encode_u64(bp, req->pos);498	bp = xdr_encode_u64(bp, req->len);499	yfs_check_req(call, bp);500 501	call->fid = vp->fid;502	trace_afs_make_fs_call(call, &vp->fid);503	afs_make_op_call(op, call, GFP_NOFS);504}505 506/*507 * Deliver reply data for YFS.CreateFile or YFS.MakeDir.508 */509static int yfs_deliver_fs_create_vnode(struct afs_call *call)510{511	struct afs_operation *op = call->op;512	struct afs_vnode_param *dvp = &op->file[0];513	struct afs_vnode_param *vp = &op->file[1];514	const __be32 *bp;515	int ret;516 517	_enter("{%u}", call->unmarshall);518 519	ret = afs_transfer_reply(call);520	if (ret < 0)521		return ret;522 523	/* unmarshall the reply once we've received all of it */524	bp = call->buffer;525	xdr_decode_YFSFid(&bp, &op->file[1].fid);526	xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);527	xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);528	xdr_decode_YFSCallBack(&bp, call, &vp->scb);529	xdr_decode_YFSVolSync(&bp, &op->volsync);530 531	_leave(" = 0 [done]");532	return 0;533}534 535/*536 * FS.CreateFile and FS.MakeDir operation type537 */538static const struct afs_call_type afs_RXFSCreateFile = {539	.name		= "YFS.CreateFile",540	.op		= yfs_FS_CreateFile,541	.deliver	= yfs_deliver_fs_create_vnode,542	.destructor	= afs_flat_call_destructor,543};544 545/*546 * Create a file.547 */548void yfs_fs_create_file(struct afs_operation *op)549{550	const struct qstr *name = &op->dentry->d_name;551	struct afs_vnode_param *dvp = &op->file[0];552	struct afs_call *call;553	size_t reqsz, rplsz;554	__be32 *bp;555 556	_enter("");557 558	reqsz = (sizeof(__be32) +559		 sizeof(__be32) +560		 sizeof(struct yfs_xdr_YFSFid) +561		 xdr_strlen(name->len) +562		 sizeof(struct yfs_xdr_YFSStoreStatus) +563		 sizeof(__be32));564	rplsz = (sizeof(struct yfs_xdr_YFSFid) +565		 sizeof(struct yfs_xdr_YFSFetchStatus) +566		 sizeof(struct yfs_xdr_YFSFetchStatus) +567		 sizeof(struct yfs_xdr_YFSCallBack) +568		 sizeof(struct yfs_xdr_YFSVolSync));569 570	call = afs_alloc_flat_call(op->net, &afs_RXFSCreateFile, reqsz, rplsz);571	if (!call)572		return afs_op_nomem(op);573 574	/* marshall the parameters */575	bp = call->request;576	bp = xdr_encode_u32(bp, YFSCREATEFILE);577	bp = xdr_encode_u32(bp, 0); /* RPC flags */578	bp = xdr_encode_YFSFid(bp, &dvp->fid);579	bp = xdr_encode_name(bp, name);580	bp = xdr_encode_YFSStoreStatus(bp, &op->create.mode, &op->mtime);581	bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */582	yfs_check_req(call, bp);583 584	call->fid = dvp->fid;585	trace_afs_make_fs_call1(call, &dvp->fid, name);586	afs_make_op_call(op, call, GFP_NOFS);587}588 589static const struct afs_call_type yfs_RXFSMakeDir = {590	.name		= "YFS.MakeDir",591	.op		= yfs_FS_MakeDir,592	.deliver	= yfs_deliver_fs_create_vnode,593	.destructor	= afs_flat_call_destructor,594};595 596/*597 * Make a directory.598 */599void yfs_fs_make_dir(struct afs_operation *op)600{601	const struct qstr *name = &op->dentry->d_name;602	struct afs_vnode_param *dvp = &op->file[0];603	struct afs_call *call;604	size_t reqsz, rplsz;605	__be32 *bp;606 607	_enter("");608 609	reqsz = (sizeof(__be32) +610		 sizeof(struct yfs_xdr_RPCFlags) +611		 sizeof(struct yfs_xdr_YFSFid) +612		 xdr_strlen(name->len) +613		 sizeof(struct yfs_xdr_YFSStoreStatus));614	rplsz = (sizeof(struct yfs_xdr_YFSFid) +615		 sizeof(struct yfs_xdr_YFSFetchStatus) +616		 sizeof(struct yfs_xdr_YFSFetchStatus) +617		 sizeof(struct yfs_xdr_YFSCallBack) +618		 sizeof(struct yfs_xdr_YFSVolSync));619 620	call = afs_alloc_flat_call(op->net, &yfs_RXFSMakeDir, reqsz, rplsz);621	if (!call)622		return afs_op_nomem(op);623 624	/* marshall the parameters */625	bp = call->request;626	bp = xdr_encode_u32(bp, YFSMAKEDIR);627	bp = xdr_encode_u32(bp, 0); /* RPC flags */628	bp = xdr_encode_YFSFid(bp, &dvp->fid);629	bp = xdr_encode_name(bp, name);630	bp = xdr_encode_YFSStoreStatus(bp, &op->create.mode, &op->mtime);631	yfs_check_req(call, bp);632 633	call->fid = dvp->fid;634	trace_afs_make_fs_call1(call, &dvp->fid, name);635	afs_make_op_call(op, call, GFP_NOFS);636}637 638/*639 * Deliver reply data to a YFS.RemoveFile2 operation.640 */641static int yfs_deliver_fs_remove_file2(struct afs_call *call)642{643	struct afs_operation *op = call->op;644	struct afs_vnode_param *dvp = &op->file[0];645	struct afs_vnode_param *vp = &op->file[1];646	struct afs_fid fid;647	const __be32 *bp;648	int ret;649 650	_enter("{%u}", call->unmarshall);651 652	ret = afs_transfer_reply(call);653	if (ret < 0)654		return ret;655 656	bp = call->buffer;657	xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);658	xdr_decode_YFSFid(&bp, &fid);659	xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);660	/* Was deleted if vnode->status.abort_code == VNOVNODE. */661 662	xdr_decode_YFSVolSync(&bp, &op->volsync);663	return 0;664}665 666static void yfs_done_fs_remove_file2(struct afs_call *call)667{668	if (call->error == -ECONNABORTED &&669	    call->abort_code == RX_INVALID_OPERATION) {670		set_bit(AFS_SERVER_FL_NO_RM2, &call->server->flags);671		call->op->flags |= AFS_OPERATION_DOWNGRADE;672	}673}674 675/*676 * YFS.RemoveFile2 operation type.677 */678static const struct afs_call_type yfs_RXYFSRemoveFile2 = {679	.name		= "YFS.RemoveFile2",680	.op		= yfs_FS_RemoveFile2,681	.deliver	= yfs_deliver_fs_remove_file2,682	.done		= yfs_done_fs_remove_file2,683	.destructor	= afs_flat_call_destructor,684};685 686/*687 * Remove a file and retrieve new file status.688 */689void yfs_fs_remove_file2(struct afs_operation *op)690{691	struct afs_vnode_param *dvp = &op->file[0];692	const struct qstr *name = &op->dentry->d_name;693	struct afs_call *call;694	__be32 *bp;695 696	_enter("");697 698	call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile2,699				   sizeof(__be32) +700				   sizeof(struct yfs_xdr_RPCFlags) +701				   sizeof(struct yfs_xdr_YFSFid) +702				   xdr_strlen(name->len),703				   sizeof(struct yfs_xdr_YFSFetchStatus) +704				   sizeof(struct yfs_xdr_YFSFid) +705				   sizeof(struct yfs_xdr_YFSFetchStatus) +706				   sizeof(struct yfs_xdr_YFSVolSync));707	if (!call)708		return afs_op_nomem(op);709 710	/* marshall the parameters */711	bp = call->request;712	bp = xdr_encode_u32(bp, YFSREMOVEFILE2);713	bp = xdr_encode_u32(bp, 0); /* RPC flags */714	bp = xdr_encode_YFSFid(bp, &dvp->fid);715	bp = xdr_encode_name(bp, name);716	yfs_check_req(call, bp);717 718	call->fid = dvp->fid;719	trace_afs_make_fs_call1(call, &dvp->fid, name);720	afs_make_op_call(op, call, GFP_NOFS);721}722 723/*724 * Deliver reply data to a YFS.RemoveFile or YFS.RemoveDir operation.725 */726static int yfs_deliver_fs_remove(struct afs_call *call)727{728	struct afs_operation *op = call->op;729	struct afs_vnode_param *dvp = &op->file[0];730	const __be32 *bp;731	int ret;732 733	_enter("{%u}", call->unmarshall);734 735	ret = afs_transfer_reply(call);736	if (ret < 0)737		return ret;738 739	bp = call->buffer;740	xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);741	xdr_decode_YFSVolSync(&bp, &op->volsync);742	return 0;743}744 745/*746 * FS.RemoveDir and FS.RemoveFile operation types.747 */748static const struct afs_call_type yfs_RXYFSRemoveFile = {749	.name		= "YFS.RemoveFile",750	.op		= yfs_FS_RemoveFile,751	.deliver	= yfs_deliver_fs_remove,752	.destructor	= afs_flat_call_destructor,753};754 755/*756 * Remove a file.757 */758void yfs_fs_remove_file(struct afs_operation *op)759{760	const struct qstr *name = &op->dentry->d_name;761	struct afs_vnode_param *dvp = &op->file[0];762	struct afs_call *call;763	__be32 *bp;764 765	_enter("");766 767	if (!test_bit(AFS_SERVER_FL_NO_RM2, &op->server->flags))768		return yfs_fs_remove_file2(op);769 770	call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile,771				   sizeof(__be32) +772				   sizeof(struct yfs_xdr_RPCFlags) +773				   sizeof(struct yfs_xdr_YFSFid) +774				   xdr_strlen(name->len),775				   sizeof(struct yfs_xdr_YFSFetchStatus) +776				   sizeof(struct yfs_xdr_YFSVolSync));777	if (!call)778		return afs_op_nomem(op);779 780	/* marshall the parameters */781	bp = call->request;782	bp = xdr_encode_u32(bp, YFSREMOVEFILE);783	bp = xdr_encode_u32(bp, 0); /* RPC flags */784	bp = xdr_encode_YFSFid(bp, &dvp->fid);785	bp = xdr_encode_name(bp, name);786	yfs_check_req(call, bp);787 788	call->fid = dvp->fid;789	trace_afs_make_fs_call1(call, &dvp->fid, name);790	afs_make_op_call(op, call, GFP_NOFS);791}792 793static const struct afs_call_type yfs_RXYFSRemoveDir = {794	.name		= "YFS.RemoveDir",795	.op		= yfs_FS_RemoveDir,796	.deliver	= yfs_deliver_fs_remove,797	.destructor	= afs_flat_call_destructor,798};799 800/*801 * Remove a directory.802 */803void yfs_fs_remove_dir(struct afs_operation *op)804{805	const struct qstr *name = &op->dentry->d_name;806	struct afs_vnode_param *dvp = &op->file[0];807	struct afs_call *call;808	__be32 *bp;809 810	_enter("");811 812	call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveDir,813				   sizeof(__be32) +814				   sizeof(struct yfs_xdr_RPCFlags) +815				   sizeof(struct yfs_xdr_YFSFid) +816				   xdr_strlen(name->len),817				   sizeof(struct yfs_xdr_YFSFetchStatus) +818				   sizeof(struct yfs_xdr_YFSVolSync));819	if (!call)820		return afs_op_nomem(op);821 822	/* marshall the parameters */823	bp = call->request;824	bp = xdr_encode_u32(bp, YFSREMOVEDIR);825	bp = xdr_encode_u32(bp, 0); /* RPC flags */826	bp = xdr_encode_YFSFid(bp, &dvp->fid);827	bp = xdr_encode_name(bp, name);828	yfs_check_req(call, bp);829 830	call->fid = dvp->fid;831	trace_afs_make_fs_call1(call, &dvp->fid, name);832	afs_make_op_call(op, call, GFP_NOFS);833}834 835/*836 * Deliver reply data to a YFS.Link operation.837 */838static int yfs_deliver_fs_link(struct afs_call *call)839{840	struct afs_operation *op = call->op;841	struct afs_vnode_param *dvp = &op->file[0];842	struct afs_vnode_param *vp = &op->file[1];843	const __be32 *bp;844	int ret;845 846	_enter("{%u}", call->unmarshall);847 848	ret = afs_transfer_reply(call);849	if (ret < 0)850		return ret;851 852	bp = call->buffer;853	xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);854	xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);855	xdr_decode_YFSVolSync(&bp, &op->volsync);856	_leave(" = 0 [done]");857	return 0;858}859 860/*861 * YFS.Link operation type.862 */863static const struct afs_call_type yfs_RXYFSLink = {864	.name		= "YFS.Link",865	.op		= yfs_FS_Link,866	.deliver	= yfs_deliver_fs_link,867	.destructor	= afs_flat_call_destructor,868};869 870/*871 * Make a hard link.872 */873void yfs_fs_link(struct afs_operation *op)874{875	const struct qstr *name = &op->dentry->d_name;876	struct afs_vnode_param *dvp = &op->file[0];877	struct afs_vnode_param *vp = &op->file[1];878	struct afs_call *call;879	__be32 *bp;880 881	_enter("");882 883	call = afs_alloc_flat_call(op->net, &yfs_RXYFSLink,884				   sizeof(__be32) +885				   sizeof(struct yfs_xdr_RPCFlags) +886				   sizeof(struct yfs_xdr_YFSFid) +887				   xdr_strlen(name->len) +888				   sizeof(struct yfs_xdr_YFSFid),889				   sizeof(struct yfs_xdr_YFSFetchStatus) +890				   sizeof(struct yfs_xdr_YFSFetchStatus) +891				   sizeof(struct yfs_xdr_YFSVolSync));892	if (!call)893		return afs_op_nomem(op);894 895	/* marshall the parameters */896	bp = call->request;897	bp = xdr_encode_u32(bp, YFSLINK);898	bp = xdr_encode_u32(bp, 0); /* RPC flags */899	bp = xdr_encode_YFSFid(bp, &dvp->fid);900	bp = xdr_encode_name(bp, name);901	bp = xdr_encode_YFSFid(bp, &vp->fid);902	yfs_check_req(call, bp);903 904	call->fid = vp->fid;905	trace_afs_make_fs_call1(call, &vp->fid, name);906	afs_make_op_call(op, call, GFP_NOFS);907}908 909/*910 * Deliver reply data to a YFS.Symlink operation.911 */912static int yfs_deliver_fs_symlink(struct afs_call *call)913{914	struct afs_operation *op = call->op;915	struct afs_vnode_param *dvp = &op->file[0];916	struct afs_vnode_param *vp = &op->file[1];917	const __be32 *bp;918	int ret;919 920	_enter("{%u}", call->unmarshall);921 922	ret = afs_transfer_reply(call);923	if (ret < 0)924		return ret;925 926	/* unmarshall the reply once we've received all of it */927	bp = call->buffer;928	xdr_decode_YFSFid(&bp, &vp->fid);929	xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);930	xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);931	xdr_decode_YFSVolSync(&bp, &op->volsync);932 933	_leave(" = 0 [done]");934	return 0;935}936 937/*938 * YFS.Symlink operation type939 */940static const struct afs_call_type yfs_RXYFSSymlink = {941	.name		= "YFS.Symlink",942	.op		= yfs_FS_Symlink,943	.deliver	= yfs_deliver_fs_symlink,944	.destructor	= afs_flat_call_destructor,945};946 947/*948 * Create a symbolic link.949 */950void yfs_fs_symlink(struct afs_operation *op)951{952	const struct qstr *name = &op->dentry->d_name;953	struct afs_vnode_param *dvp = &op->file[0];954	struct afs_call *call;955	size_t contents_sz;956	mode_t mode = 0777;957	__be32 *bp;958 959	_enter("");960 961	contents_sz = strlen(op->create.symlink);962	call = afs_alloc_flat_call(op->net, &yfs_RXYFSSymlink,963				   sizeof(__be32) +964				   sizeof(struct yfs_xdr_RPCFlags) +965				   sizeof(struct yfs_xdr_YFSFid) +966				   xdr_strlen(name->len) +967				   xdr_strlen(contents_sz) +968				   sizeof(struct yfs_xdr_YFSStoreStatus),969				   sizeof(struct yfs_xdr_YFSFid) +970				   sizeof(struct yfs_xdr_YFSFetchStatus) +971				   sizeof(struct yfs_xdr_YFSFetchStatus) +972				   sizeof(struct yfs_xdr_YFSVolSync));973	if (!call)974		return afs_op_nomem(op);975 976	/* marshall the parameters */977	bp = call->request;978	bp = xdr_encode_u32(bp, YFSSYMLINK);979	bp = xdr_encode_u32(bp, 0); /* RPC flags */980	bp = xdr_encode_YFSFid(bp, &dvp->fid);981	bp = xdr_encode_name(bp, name);982	bp = xdr_encode_string(bp, op->create.symlink, contents_sz);983	bp = xdr_encode_YFSStoreStatus(bp, &mode, &op->mtime);984	yfs_check_req(call, bp);985 986	call->fid = dvp->fid;987	trace_afs_make_fs_call1(call, &dvp->fid, name);988	afs_make_op_call(op, call, GFP_NOFS);989}990 991/*992 * Deliver reply data to a YFS.Rename operation.993 */994static int yfs_deliver_fs_rename(struct afs_call *call)995{996	struct afs_operation *op = call->op;997	struct afs_vnode_param *orig_dvp = &op->file[0];998	struct afs_vnode_param *new_dvp = &op->file[1];999	const __be32 *bp;1000	int ret;1001 1002	_enter("{%u}", call->unmarshall);1003 1004	ret = afs_transfer_reply(call);1005	if (ret < 0)1006		return ret;1007 1008	bp = call->buffer;1009	/* If the two dirs are the same, we have two copies of the same status1010	 * report, so we just decode it twice.1011	 */1012	xdr_decode_YFSFetchStatus(&bp, call, &orig_dvp->scb);1013	xdr_decode_YFSFetchStatus(&bp, call, &new_dvp->scb);1014	xdr_decode_YFSVolSync(&bp, &op->volsync);1015	_leave(" = 0 [done]");1016	return 0;1017}1018 1019/*1020 * YFS.Rename operation type1021 */1022static const struct afs_call_type yfs_RXYFSRename = {1023	.name		= "FS.Rename",1024	.op		= yfs_FS_Rename,1025	.deliver	= yfs_deliver_fs_rename,1026	.destructor	= afs_flat_call_destructor,1027};1028 1029/*1030 * Rename a file or directory.1031 */1032void yfs_fs_rename(struct afs_operation *op)1033{1034	struct afs_vnode_param *orig_dvp = &op->file[0];1035	struct afs_vnode_param *new_dvp = &op->file[1];1036	const struct qstr *orig_name = &op->dentry->d_name;1037	const struct qstr *new_name = &op->dentry_2->d_name;1038	struct afs_call *call;1039	__be32 *bp;1040 1041	_enter("");1042 1043	call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename,1044				   sizeof(__be32) +1045				   sizeof(struct yfs_xdr_RPCFlags) +1046				   sizeof(struct yfs_xdr_YFSFid) +1047				   xdr_strlen(orig_name->len) +1048				   sizeof(struct yfs_xdr_YFSFid) +1049				   xdr_strlen(new_name->len),1050				   sizeof(struct yfs_xdr_YFSFetchStatus) +1051				   sizeof(struct yfs_xdr_YFSFetchStatus) +1052				   sizeof(struct yfs_xdr_YFSVolSync));1053	if (!call)1054		return afs_op_nomem(op);1055 1056	/* marshall the parameters */1057	bp = call->request;1058	bp = xdr_encode_u32(bp, YFSRENAME);1059	bp = xdr_encode_u32(bp, 0); /* RPC flags */1060	bp = xdr_encode_YFSFid(bp, &orig_dvp->fid);1061	bp = xdr_encode_name(bp, orig_name);1062	bp = xdr_encode_YFSFid(bp, &new_dvp->fid);1063	bp = xdr_encode_name(bp, new_name);1064	yfs_check_req(call, bp);1065 1066	call->fid = orig_dvp->fid;1067	trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name);1068	afs_make_op_call(op, call, GFP_NOFS);1069}1070 1071/*1072 * YFS.StoreData64 operation type.1073 */1074static const struct afs_call_type yfs_RXYFSStoreData64 = {1075	.name		= "YFS.StoreData64",1076	.op		= yfs_FS_StoreData64,1077	.deliver	= yfs_deliver_status_and_volsync,1078	.destructor	= afs_flat_call_destructor,1079};1080 1081/*1082 * Store a set of pages to a large file.1083 */1084void yfs_fs_store_data(struct afs_operation *op)1085{1086	struct afs_vnode_param *vp = &op->file[0];1087	struct afs_call *call;1088	__be32 *bp;1089 1090	_enter(",%x,{%llx:%llu},,",1091	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);1092 1093	_debug("size %llx, at %llx, i_size %llx",1094	       (unsigned long long)op->store.size,1095	       (unsigned long long)op->store.pos,1096	       (unsigned long long)op->store.i_size);1097 1098	call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64,1099				   sizeof(__be32) +1100				   sizeof(__be32) +1101				   sizeof(struct yfs_xdr_YFSFid) +1102				   sizeof(struct yfs_xdr_YFSStoreStatus) +1103				   sizeof(struct yfs_xdr_u64) * 3,1104				   sizeof(struct yfs_xdr_YFSFetchStatus) +1105				   sizeof(struct yfs_xdr_YFSVolSync));1106	if (!call)1107		return afs_op_nomem(op);1108 1109	call->write_iter = op->store.write_iter;1110 1111	/* marshall the parameters */1112	bp = call->request;1113	bp = xdr_encode_u32(bp, YFSSTOREDATA64);1114	bp = xdr_encode_u32(bp, 0); /* RPC flags */1115	bp = xdr_encode_YFSFid(bp, &vp->fid);1116	bp = xdr_encode_YFSStoreStatus(bp, NULL, &op->mtime);1117	bp = xdr_encode_u64(bp, op->store.pos);1118	bp = xdr_encode_u64(bp, op->store.size);1119	bp = xdr_encode_u64(bp, op->store.i_size);1120	yfs_check_req(call, bp);1121 1122	call->fid = vp->fid;1123	trace_afs_make_fs_call(call, &vp->fid);1124	afs_make_op_call(op, call, GFP_NOFS);1125}1126 1127/*1128 * YFS.StoreStatus operation type1129 */1130static const struct afs_call_type yfs_RXYFSStoreStatus = {1131	.name		= "YFS.StoreStatus",1132	.op		= yfs_FS_StoreStatus,1133	.deliver	= yfs_deliver_status_and_volsync,1134	.destructor	= afs_flat_call_destructor,1135};1136 1137static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = {1138	.name		= "YFS.StoreData64",1139	.op		= yfs_FS_StoreData64,1140	.deliver	= yfs_deliver_status_and_volsync,1141	.destructor	= afs_flat_call_destructor,1142};1143 1144/*1145 * Set the attributes on a file, using YFS.StoreData64 rather than1146 * YFS.StoreStatus so as to alter the file size also.1147 */1148static void yfs_fs_setattr_size(struct afs_operation *op)1149{1150	struct afs_vnode_param *vp = &op->file[0];1151	struct afs_call *call;1152	struct iattr *attr = op->setattr.attr;1153	__be32 *bp;1154 1155	_enter(",%x,{%llx:%llu},,",1156	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);1157 1158	call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64_as_Status,1159				   sizeof(__be32) * 2 +1160				   sizeof(struct yfs_xdr_YFSFid) +1161				   sizeof(struct yfs_xdr_YFSStoreStatus) +1162				   sizeof(struct yfs_xdr_u64) * 3,1163				   sizeof(struct yfs_xdr_YFSFetchStatus) +1164				   sizeof(struct yfs_xdr_YFSVolSync));1165	if (!call)1166		return afs_op_nomem(op);1167 1168	/* marshall the parameters */1169	bp = call->request;1170	bp = xdr_encode_u32(bp, YFSSTOREDATA64);1171	bp = xdr_encode_u32(bp, 0); /* RPC flags */1172	bp = xdr_encode_YFSFid(bp, &vp->fid);1173	bp = xdr_encode_YFS_StoreStatus(bp, attr);1174	bp = xdr_encode_u64(bp, attr->ia_size);	/* position of start of write */1175	bp = xdr_encode_u64(bp, 0);		/* size of write */1176	bp = xdr_encode_u64(bp, attr->ia_size);	/* new file length */1177	yfs_check_req(call, bp);1178 1179	call->fid = vp->fid;1180	trace_afs_make_fs_call(call, &vp->fid);1181	afs_make_op_call(op, call, GFP_NOFS);1182}1183 1184/*1185 * Set the attributes on a file, using YFS.StoreData64 if there's a change in1186 * file size, and YFS.StoreStatus otherwise.1187 */1188void yfs_fs_setattr(struct afs_operation *op)1189{1190	struct afs_vnode_param *vp = &op->file[0];1191	struct afs_call *call;1192	struct iattr *attr = op->setattr.attr;1193	__be32 *bp;1194 1195	if (attr->ia_valid & ATTR_SIZE)1196		return yfs_fs_setattr_size(op);1197 1198	_enter(",%x,{%llx:%llu},,",1199	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);1200 1201	call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreStatus,1202				   sizeof(__be32) * 2 +1203				   sizeof(struct yfs_xdr_YFSFid) +1204				   sizeof(struct yfs_xdr_YFSStoreStatus),1205				   sizeof(struct yfs_xdr_YFSFetchStatus) +1206				   sizeof(struct yfs_xdr_YFSVolSync));1207	if (!call)1208		return afs_op_nomem(op);1209 1210	/* marshall the parameters */1211	bp = call->request;1212	bp = xdr_encode_u32(bp, YFSSTORESTATUS);1213	bp = xdr_encode_u32(bp, 0); /* RPC flags */1214	bp = xdr_encode_YFSFid(bp, &vp->fid);1215	bp = xdr_encode_YFS_StoreStatus(bp, attr);1216	yfs_check_req(call, bp);1217 1218	call->fid = vp->fid;1219	trace_afs_make_fs_call(call, &vp->fid);1220	afs_make_op_call(op, call, GFP_NOFS);1221}1222 1223/*1224 * Deliver reply data to a YFS.GetVolumeStatus operation.1225 */1226static int yfs_deliver_fs_get_volume_status(struct afs_call *call)1227{1228	struct afs_operation *op = call->op;1229	const __be32 *bp;1230	char *p;1231	u32 size;1232	int ret;1233 1234	_enter("{%u}", call->unmarshall);1235 1236	switch (call->unmarshall) {1237	case 0:1238		call->unmarshall++;1239		afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus));1240		fallthrough;1241 1242		/* extract the returned status record */1243	case 1:1244		_debug("extract status");1245		ret = afs_extract_data(call, true);1246		if (ret < 0)1247			return ret;1248 1249		bp = call->buffer;1250		xdr_decode_YFSFetchVolumeStatus(&bp, &op->volstatus.vs);1251		call->unmarshall++;1252		afs_extract_to_tmp(call);1253		fallthrough;1254 1255		/* extract the volume name length */1256	case 2:1257		ret = afs_extract_data(call, true);1258		if (ret < 0)1259			return ret;1260 1261		call->count = ntohl(call->tmp);1262		_debug("volname length: %u", call->count);1263		if (call->count >= AFSNAMEMAX)1264			return afs_protocol_error(call, afs_eproto_volname_len);1265		size = (call->count + 3) & ~3; /* It's padded */1266		afs_extract_to_buf(call, size);1267		call->unmarshall++;1268		fallthrough;1269 1270		/* extract the volume name */1271	case 3:1272		_debug("extract volname");1273		ret = afs_extract_data(call, true);1274		if (ret < 0)1275			return ret;1276 1277		p = call->buffer;1278		p[call->count] = 0;1279		_debug("volname '%s'", p);1280		afs_extract_to_tmp(call);1281		call->unmarshall++;1282		fallthrough;1283 1284		/* extract the offline message length */1285	case 4:1286		ret = afs_extract_data(call, true);1287		if (ret < 0)1288			return ret;1289 1290		call->count = ntohl(call->tmp);1291		_debug("offline msg length: %u", call->count);1292		if (call->count >= AFSNAMEMAX)1293			return afs_protocol_error(call, afs_eproto_offline_msg_len);1294		size = (call->count + 3) & ~3; /* It's padded */1295		afs_extract_to_buf(call, size);1296		call->unmarshall++;1297		fallthrough;1298 1299		/* extract the offline message */1300	case 5:1301		_debug("extract offline");1302		ret = afs_extract_data(call, true);1303		if (ret < 0)1304			return ret;1305 1306		p = call->buffer;1307		p[call->count] = 0;1308		_debug("offline '%s'", p);1309 1310		afs_extract_to_tmp(call);1311		call->unmarshall++;1312		fallthrough;1313 1314		/* extract the message of the day length */1315	case 6:1316		ret = afs_extract_data(call, true);1317		if (ret < 0)1318			return ret;1319 1320		call->count = ntohl(call->tmp);1321		_debug("motd length: %u", call->count);1322		if (call->count >= AFSNAMEMAX)1323			return afs_protocol_error(call, afs_eproto_motd_len);1324		size = (call->count + 3) & ~3; /* It's padded */1325		afs_extract_to_buf(call, size);1326		call->unmarshall++;1327		fallthrough;1328 1329		/* extract the message of the day */1330	case 7:1331		_debug("extract motd");1332		ret = afs_extract_data(call, false);1333		if (ret < 0)1334			return ret;1335 1336		p = call->buffer;1337		p[call->count] = 0;1338		_debug("motd '%s'", p);1339 1340		call->unmarshall++;1341		fallthrough;1342 1343	case 8:1344		break;1345	}1346 1347	_leave(" = 0 [done]");1348	return 0;1349}1350 1351/*1352 * YFS.GetVolumeStatus operation type1353 */1354static const struct afs_call_type yfs_RXYFSGetVolumeStatus = {1355	.name		= "YFS.GetVolumeStatus",1356	.op		= yfs_FS_GetVolumeStatus,1357	.deliver	= yfs_deliver_fs_get_volume_status,1358	.destructor	= afs_flat_call_destructor,1359};1360 1361/*1362 * fetch the status of a volume1363 */1364void yfs_fs_get_volume_status(struct afs_operation *op)1365{1366	struct afs_vnode_param *vp = &op->file[0];1367	struct afs_call *call;1368	__be32 *bp;1369 1370	_enter("");1371 1372	call = afs_alloc_flat_call(op->net, &yfs_RXYFSGetVolumeStatus,1373				   sizeof(__be32) * 2 +1374				   sizeof(struct yfs_xdr_u64),1375				   max_t(size_t,1376					 sizeof(struct yfs_xdr_YFSFetchVolumeStatus) +1377					 sizeof(__be32),1378					 AFSOPAQUEMAX + 1));1379	if (!call)1380		return afs_op_nomem(op);1381 1382	/* marshall the parameters */1383	bp = call->request;1384	bp = xdr_encode_u32(bp, YFSGETVOLUMESTATUS);1385	bp = xdr_encode_u32(bp, 0); /* RPC flags */1386	bp = xdr_encode_u64(bp, vp->fid.vid);1387	yfs_check_req(call, bp);1388 1389	call->fid = vp->fid;1390	trace_afs_make_fs_call(call, &vp->fid);1391	afs_make_op_call(op, call, GFP_NOFS);1392}1393 1394/*1395 * YFS.SetLock operation type1396 */1397static const struct afs_call_type yfs_RXYFSSetLock = {1398	.name		= "YFS.SetLock",1399	.op		= yfs_FS_SetLock,1400	.deliver	= yfs_deliver_status_and_volsync,1401	.done		= afs_lock_op_done,1402	.destructor	= afs_flat_call_destructor,1403};1404 1405/*1406 * YFS.ExtendLock operation type1407 */1408static const struct afs_call_type yfs_RXYFSExtendLock = {1409	.name		= "YFS.ExtendLock",1410	.op		= yfs_FS_ExtendLock,1411	.deliver	= yfs_deliver_status_and_volsync,1412	.done		= afs_lock_op_done,1413	.destructor	= afs_flat_call_destructor,1414};1415 1416/*1417 * YFS.ReleaseLock operation type1418 */1419static const struct afs_call_type yfs_RXYFSReleaseLock = {1420	.name		= "YFS.ReleaseLock",1421	.op		= yfs_FS_ReleaseLock,1422	.deliver	= yfs_deliver_status_and_volsync,1423	.destructor	= afs_flat_call_destructor,1424};1425 1426/*1427 * Set a lock on a file1428 */1429void yfs_fs_set_lock(struct afs_operation *op)1430{1431	struct afs_vnode_param *vp = &op->file[0];1432	struct afs_call *call;1433	__be32 *bp;1434 1435	_enter("");1436 1437	call = afs_alloc_flat_call(op->net, &yfs_RXYFSSetLock,1438				   sizeof(__be32) * 2 +1439				   sizeof(struct yfs_xdr_YFSFid) +1440				   sizeof(__be32),1441				   sizeof(struct yfs_xdr_YFSFetchStatus) +1442				   sizeof(struct yfs_xdr_YFSVolSync));1443	if (!call)1444		return afs_op_nomem(op);1445 1446	/* marshall the parameters */1447	bp = call->request;1448	bp = xdr_encode_u32(bp, YFSSETLOCK);1449	bp = xdr_encode_u32(bp, 0); /* RPC flags */1450	bp = xdr_encode_YFSFid(bp, &vp->fid);1451	bp = xdr_encode_u32(bp, op->lock.type);1452	yfs_check_req(call, bp);1453 1454	call->fid = vp->fid;1455	trace_afs_make_fs_calli(call, &vp->fid, op->lock.type);1456	afs_make_op_call(op, call, GFP_NOFS);1457}1458 1459/*1460 * extend a lock on a file1461 */1462void yfs_fs_extend_lock(struct afs_operation *op)1463{1464	struct afs_vnode_param *vp = &op->file[0];1465	struct afs_call *call;1466	__be32 *bp;1467 1468	_enter("");1469 1470	call = afs_alloc_flat_call(op->net, &yfs_RXYFSExtendLock,1471				   sizeof(__be32) * 2 +1472				   sizeof(struct yfs_xdr_YFSFid),1473				   sizeof(struct yfs_xdr_YFSFetchStatus) +1474				   sizeof(struct yfs_xdr_YFSVolSync));1475	if (!call)1476		return afs_op_nomem(op);1477 1478	/* marshall the parameters */1479	bp = call->request;1480	bp = xdr_encode_u32(bp, YFSEXTENDLOCK);1481	bp = xdr_encode_u32(bp, 0); /* RPC flags */1482	bp = xdr_encode_YFSFid(bp, &vp->fid);1483	yfs_check_req(call, bp);1484 1485	call->fid = vp->fid;1486	trace_afs_make_fs_call(call, &vp->fid);1487	afs_make_op_call(op, call, GFP_NOFS);1488}1489 1490/*1491 * release a lock on a file1492 */1493void yfs_fs_release_lock(struct afs_operation *op)1494{1495	struct afs_vnode_param *vp = &op->file[0];1496	struct afs_call *call;1497	__be32 *bp;1498 1499	_enter("");1500 1501	call = afs_alloc_flat_call(op->net, &yfs_RXYFSReleaseLock,1502				   sizeof(__be32) * 2 +1503				   sizeof(struct yfs_xdr_YFSFid),1504				   sizeof(struct yfs_xdr_YFSFetchStatus) +1505				   sizeof(struct yfs_xdr_YFSVolSync));1506	if (!call)1507		return afs_op_nomem(op);1508 1509	/* marshall the parameters */1510	bp = call->request;1511	bp = xdr_encode_u32(bp, YFSRELEASELOCK);1512	bp = xdr_encode_u32(bp, 0); /* RPC flags */1513	bp = xdr_encode_YFSFid(bp, &vp->fid);1514	yfs_check_req(call, bp);1515 1516	call->fid = vp->fid;1517	trace_afs_make_fs_call(call, &vp->fid);1518	afs_make_op_call(op, call, GFP_NOFS);1519}1520 1521/*1522 * Deliver a reply to YFS.FetchStatus1523 */1524static int yfs_deliver_fs_fetch_status(struct afs_call *call)1525{1526	struct afs_operation *op = call->op;1527	struct afs_vnode_param *vp = &op->file[op->fetch_status.which];1528	const __be32 *bp;1529	int ret;1530 1531	ret = afs_transfer_reply(call);1532	if (ret < 0)1533		return ret;1534 1535	/* unmarshall the reply once we've received all of it */1536	bp = call->buffer;1537	xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);1538	xdr_decode_YFSCallBack(&bp, call, &vp->scb);1539	xdr_decode_YFSVolSync(&bp, &op->volsync);1540 1541	_leave(" = 0 [done]");1542	return 0;1543}1544 1545/*1546 * YFS.FetchStatus operation type1547 */1548static const struct afs_call_type yfs_RXYFSFetchStatus = {1549	.name		= "YFS.FetchStatus",1550	.op		= yfs_FS_FetchStatus,1551	.deliver	= yfs_deliver_fs_fetch_status,1552	.destructor	= afs_flat_call_destructor,1553};1554 1555/*1556 * Fetch the status information for a fid without needing a vnode handle.1557 */1558void yfs_fs_fetch_status(struct afs_operation *op)1559{1560	struct afs_vnode_param *vp = &op->file[op->fetch_status.which];1561	struct afs_call *call;1562	__be32 *bp;1563 1564	_enter(",%x,{%llx:%llu},,",1565	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);1566 1567	call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchStatus,1568				   sizeof(__be32) * 2 +1569				   sizeof(struct yfs_xdr_YFSFid),1570				   sizeof(struct yfs_xdr_YFSFetchStatus) +1571				   sizeof(struct yfs_xdr_YFSCallBack) +1572				   sizeof(struct yfs_xdr_YFSVolSync));1573	if (!call)1574		return afs_op_nomem(op);1575 1576	/* marshall the parameters */1577	bp = call->request;1578	bp = xdr_encode_u32(bp, YFSFETCHSTATUS);1579	bp = xdr_encode_u32(bp, 0); /* RPC flags */1580	bp = xdr_encode_YFSFid(bp, &vp->fid);1581	yfs_check_req(call, bp);1582 1583	call->fid = vp->fid;1584	trace_afs_make_fs_call(call, &vp->fid);1585	afs_make_op_call(op, call, GFP_NOFS);1586}1587 1588/*1589 * Deliver reply data to an YFS.InlineBulkStatus call1590 */1591static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)1592{1593	struct afs_operation *op = call->op;1594	struct afs_status_cb *scb;1595	const __be32 *bp;1596	u32 tmp;1597	int ret;1598 1599	_enter("{%u}", call->unmarshall);1600 1601	switch (call->unmarshall) {1602	case 0:1603		afs_extract_to_tmp(call);1604		call->unmarshall++;1605		fallthrough;1606 1607		/* Extract the file status count and array in two steps */1608	case 1:1609		_debug("extract status count");1610		ret = afs_extract_data(call, true);1611		if (ret < 0)1612			return ret;1613 1614		tmp = ntohl(call->tmp);1615		_debug("status count: %u/%u", tmp, op->nr_files);1616		if (tmp != op->nr_files)1617			return afs_protocol_error(call, afs_eproto_ibulkst_count);1618 1619		call->count = 0;1620		call->unmarshall++;1621	more_counts:1622		afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus));1623		fallthrough;1624 1625	case 2:1626		_debug("extract status array %u", call->count);1627		ret = afs_extract_data(call, true);1628		if (ret < 0)1629			return ret;1630 1631		switch (call->count) {1632		case 0:1633			scb = &op->file[0].scb;1634			break;1635		case 1:1636			scb = &op->file[1].scb;1637			break;1638		default:1639			scb = &op->more_files[call->count - 2].scb;1640			break;1641		}1642 1643		bp = call->buffer;1644		xdr_decode_YFSFetchStatus(&bp, call, scb);1645 1646		call->count++;1647		if (call->count < op->nr_files)1648			goto more_counts;1649 1650		call->count = 0;1651		call->unmarshall++;1652		afs_extract_to_tmp(call);1653		fallthrough;1654 1655		/* Extract the callback count and array in two steps */1656	case 3:1657		_debug("extract CB count");1658		ret = afs_extract_data(call, true);1659		if (ret < 0)1660			return ret;1661 1662		tmp = ntohl(call->tmp);1663		_debug("CB count: %u", tmp);1664		if (tmp != op->nr_files)1665			return afs_protocol_error(call, afs_eproto_ibulkst_cb_count);1666		call->count = 0;1667		call->unmarshall++;1668	more_cbs:1669		afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack));1670		fallthrough;1671 1672	case 4:1673		_debug("extract CB array");1674		ret = afs_extract_data(call, true);1675		if (ret < 0)1676			return ret;1677 1678		_debug("unmarshall CB array");1679		switch (call->count) {1680		case 0:1681			scb = &op->file[0].scb;1682			break;1683		case 1:1684			scb = &op->file[1].scb;1685			break;1686		default:1687			scb = &op->more_files[call->count - 2].scb;1688			break;1689		}1690 1691		bp = call->buffer;1692		xdr_decode_YFSCallBack(&bp, call, scb);1693		call->count++;1694		if (call->count < op->nr_files)1695			goto more_cbs;1696 1697		afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync));1698		call->unmarshall++;1699		fallthrough;1700 1701	case 5:1702		ret = afs_extract_data(call, false);1703		if (ret < 0)1704			return ret;1705 1706		bp = call->buffer;1707		xdr_decode_YFSVolSync(&bp, &op->volsync);1708 1709		call->unmarshall++;1710		fallthrough;1711 1712	case 6:1713		break;1714	}1715 1716	_leave(" = 0 [done]");1717	return 0;1718}1719 1720/*1721 * FS.InlineBulkStatus operation type1722 */1723static const struct afs_call_type yfs_RXYFSInlineBulkStatus = {1724	.name		= "YFS.InlineBulkStatus",1725	.op		= yfs_FS_InlineBulkStatus,1726	.deliver	= yfs_deliver_fs_inline_bulk_status,1727	.destructor	= afs_flat_call_destructor,1728};1729 1730/*1731 * Fetch the status information for up to 1024 files1732 */1733void yfs_fs_inline_bulk_status(struct afs_operation *op)1734{1735	struct afs_vnode_param *dvp = &op->file[0];1736	struct afs_vnode_param *vp = &op->file[1];1737	struct afs_call *call;1738	__be32 *bp;1739	int i;1740 1741	_enter(",%x,{%llx:%llu},%u",1742	       key_serial(op->key), vp->fid.vid, vp->fid.vnode, op->nr_files);1743 1744	call = afs_alloc_flat_call(op->net, &yfs_RXYFSInlineBulkStatus,1745				   sizeof(__be32) +1746				   sizeof(__be32) +1747				   sizeof(__be32) +1748				   sizeof(struct yfs_xdr_YFSFid) * op->nr_files,1749				   sizeof(struct yfs_xdr_YFSFetchStatus));1750	if (!call)1751		return afs_op_nomem(op);1752 1753	/* marshall the parameters */1754	bp = call->request;1755	bp = xdr_encode_u32(bp, YFSINLINEBULKSTATUS);1756	bp = xdr_encode_u32(bp, 0); /* RPCFlags */1757	bp = xdr_encode_u32(bp, op->nr_files);1758	bp = xdr_encode_YFSFid(bp, &dvp->fid);1759	bp = xdr_encode_YFSFid(bp, &vp->fid);1760	for (i = 0; i < op->nr_files - 2; i++)1761		bp = xdr_encode_YFSFid(bp, &op->more_files[i].fid);1762	yfs_check_req(call, bp);1763 1764	call->fid = vp->fid;1765	trace_afs_make_fs_call(call, &vp->fid);1766	afs_make_op_call(op, call, GFP_NOFS);1767}1768 1769/*1770 * Deliver reply data to an YFS.FetchOpaqueACL.1771 */1772static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)1773{1774	struct afs_operation *op = call->op;1775	struct afs_vnode_param *vp = &op->file[0];1776	struct yfs_acl *yacl = op->yacl;1777	struct afs_acl *acl;1778	const __be32 *bp;1779	unsigned int size;1780	int ret;1781 1782	_enter("{%u}", call->unmarshall);1783 1784	switch (call->unmarshall) {1785	case 0:1786		afs_extract_to_tmp(call);1787		call->unmarshall++;1788		fallthrough;1789 1790		/* Extract the file ACL length */1791	case 1:1792		ret = afs_extract_data(call, true);1793		if (ret < 0)1794			return ret;1795 1796		size = call->count2 = ntohl(call->tmp);1797		size = round_up(size, 4);1798 1799		if (yacl->flags & YFS_ACL_WANT_ACL) {1800			acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);1801			if (!acl)1802				return -ENOMEM;1803			yacl->acl = acl;1804			acl->size = call->count2;1805			afs_extract_begin(call, acl->data, size);1806		} else {1807			afs_extract_discard(call, size);1808		}1809		call->unmarshall++;1810		fallthrough;1811 1812		/* Extract the file ACL */1813	case 2:1814		ret = afs_extract_data(call, true);1815		if (ret < 0)1816			return ret;1817 1818		afs_extract_to_tmp(call);1819		call->unmarshall++;1820		fallthrough;1821 1822		/* Extract the volume ACL length */1823	case 3:1824		ret = afs_extract_data(call, true);1825		if (ret < 0)1826			return ret;1827 1828		size = call->count2 = ntohl(call->tmp);1829		size = round_up(size, 4);1830 1831		if (yacl->flags & YFS_ACL_WANT_VOL_ACL) {1832			acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);1833			if (!acl)1834				return -ENOMEM;1835			yacl->vol_acl = acl;1836			acl->size = call->count2;1837			afs_extract_begin(call, acl->data, size);1838		} else {1839			afs_extract_discard(call, size);1840		}1841		call->unmarshall++;1842		fallthrough;1843 1844		/* Extract the volume ACL */1845	case 4:1846		ret = afs_extract_data(call, true);1847		if (ret < 0)1848			return ret;1849 1850		afs_extract_to_buf(call,1851				   sizeof(__be32) * 2 +1852				   sizeof(struct yfs_xdr_YFSFetchStatus) +1853				   sizeof(struct yfs_xdr_YFSVolSync));1854		call->unmarshall++;1855		fallthrough;1856 1857		/* extract the metadata */1858	case 5:1859		ret = afs_extract_data(call, false);1860		if (ret < 0)1861			return ret;1862 1863		bp = call->buffer;1864		yacl->inherit_flag = ntohl(*bp++);1865		yacl->num_cleaned = ntohl(*bp++);1866		xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);1867		xdr_decode_YFSVolSync(&bp, &op->volsync);1868 1869		call->unmarshall++;1870		fallthrough;1871 1872	case 6:1873		break;1874	}1875 1876	_leave(" = 0 [done]");1877	return 0;1878}1879 1880void yfs_free_opaque_acl(struct yfs_acl *yacl)1881{1882	if (yacl) {1883		kfree(yacl->acl);1884		kfree(yacl->vol_acl);1885		kfree(yacl);1886	}1887}1888 1889/*1890 * YFS.FetchOpaqueACL operation type1891 */1892static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = {1893	.name		= "YFS.FetchOpaqueACL",1894	.op		= yfs_FS_FetchOpaqueACL,1895	.deliver	= yfs_deliver_fs_fetch_opaque_acl,1896	.destructor	= afs_flat_call_destructor,1897};1898 1899/*1900 * Fetch the YFS advanced ACLs for a file.1901 */1902void yfs_fs_fetch_opaque_acl(struct afs_operation *op)1903{1904	struct afs_vnode_param *vp = &op->file[0];1905	struct afs_call *call;1906	__be32 *bp;1907 1908	_enter(",%x,{%llx:%llu},,",1909	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);1910 1911	call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchOpaqueACL,1912				   sizeof(__be32) * 2 +1913				   sizeof(struct yfs_xdr_YFSFid),1914				   sizeof(__be32) * 2 +1915				   sizeof(struct yfs_xdr_YFSFetchStatus) +1916				   sizeof(struct yfs_xdr_YFSVolSync));1917	if (!call)1918		return afs_op_nomem(op);1919 1920	/* marshall the parameters */1921	bp = call->request;1922	bp = xdr_encode_u32(bp, YFSFETCHOPAQUEACL);1923	bp = xdr_encode_u32(bp, 0); /* RPC flags */1924	bp = xdr_encode_YFSFid(bp, &vp->fid);1925	yfs_check_req(call, bp);1926 1927	call->fid = vp->fid;1928	trace_afs_make_fs_call(call, &vp->fid);1929	afs_make_op_call(op, call, GFP_KERNEL);1930}1931 1932/*1933 * YFS.StoreOpaqueACL2 operation type1934 */1935static const struct afs_call_type yfs_RXYFSStoreOpaqueACL2 = {1936	.name		= "YFS.StoreOpaqueACL2",1937	.op		= yfs_FS_StoreOpaqueACL2,1938	.deliver	= yfs_deliver_status_and_volsync,1939	.destructor	= afs_flat_call_destructor,1940};1941 1942/*1943 * Fetch the YFS ACL for a file.1944 */1945void yfs_fs_store_opaque_acl2(struct afs_operation *op)1946{1947	struct afs_vnode_param *vp = &op->file[0];1948	struct afs_call *call;1949	struct afs_acl *acl = op->acl;1950	size_t size;1951	__be32 *bp;1952 1953	_enter(",%x,{%llx:%llu},,",1954	       key_serial(op->key), vp->fid.vid, vp->fid.vnode);1955 1956	size = round_up(acl->size, 4);1957	call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreOpaqueACL2,1958				   sizeof(__be32) * 2 +1959				   sizeof(struct yfs_xdr_YFSFid) +1960				   sizeof(__be32) + size,1961				   sizeof(struct yfs_xdr_YFSFetchStatus) +1962				   sizeof(struct yfs_xdr_YFSVolSync));1963	if (!call)1964		return afs_op_nomem(op);1965 1966	/* marshall the parameters */1967	bp = call->request;1968	bp = xdr_encode_u32(bp, YFSSTOREOPAQUEACL2);1969	bp = xdr_encode_u32(bp, 0); /* RPC flags */1970	bp = xdr_encode_YFSFid(bp, &vp->fid);1971	bp = xdr_encode_u32(bp, acl->size);1972	memcpy(bp, acl->data, acl->size);1973	if (acl->size != size)1974		memset((void *)bp + acl->size, 0, size - acl->size);1975	bp += size / sizeof(__be32);1976	yfs_check_req(call, bp);1977 1978	call->fid = vp->fid;1979	trace_afs_make_fs_call(call, &vp->fid);1980	afs_make_op_call(op, call, GFP_KERNEL);1981}1982