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