12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 208e0e7c8SDavid Howells /* AFS File Server client stubs 31da177e4SLinus Torvalds * 408e0e7c8SDavid Howells * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved. 51da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds #include <linux/init.h> 95a0e3ad6STejun Heo #include <linux/slab.h> 101da177e4SLinus Torvalds #include <linux/sched.h> 1108e0e7c8SDavid Howells #include <linux/circ_buf.h> 12a01179e6SJeff Layton #include <linux/iversion.h> 131da177e4SLinus Torvalds #include "internal.h" 1408e0e7c8SDavid Howells #include "afs_fs.h" 15dd9fbcb8SDavid Howells #include "xdr_fs.h" 1630062bd1SDavid Howells #include "protocol_yfs.h" 171da177e4SLinus Torvalds 18025db80cSDavid Howells static const struct afs_fid afs_zero_fid; 19025db80cSDavid Howells 20d2ddc776SDavid Howells static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi) 21c435ee34SDavid Howells { 22d2ddc776SDavid Howells call->cbi = afs_get_cb_interest(cbi); 23c435ee34SDavid Howells } 24c435ee34SDavid Howells 256db3ac3cSDavid Howells /* 26260a9803SDavid Howells * decode an AFSFid block 27260a9803SDavid Howells */ 28260a9803SDavid Howells static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid) 29260a9803SDavid Howells { 30260a9803SDavid Howells const __be32 *bp = *_bp; 31260a9803SDavid Howells 32260a9803SDavid Howells fid->vid = ntohl(*bp++); 33260a9803SDavid Howells fid->vnode = ntohl(*bp++); 34260a9803SDavid Howells fid->unique = ntohl(*bp++); 35260a9803SDavid Howells *_bp = bp; 36260a9803SDavid Howells } 37260a9803SDavid Howells 38260a9803SDavid Howells /* 39888b3384SDavid Howells * Dump a bad file status record. 40888b3384SDavid Howells */ 41888b3384SDavid Howells static void xdr_dump_bad(const __be32 *bp) 42888b3384SDavid Howells { 43888b3384SDavid Howells __be32 x[4]; 44888b3384SDavid Howells int i; 45888b3384SDavid Howells 46888b3384SDavid Howells pr_notice("AFS XDR: Bad status record\n"); 47888b3384SDavid Howells for (i = 0; i < 5 * 4 * 4; i += 16) { 48888b3384SDavid Howells memcpy(x, bp, 16); 49888b3384SDavid Howells bp += 4; 50888b3384SDavid Howells pr_notice("%03x: %08x %08x %08x %08x\n", 51888b3384SDavid Howells i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3])); 52888b3384SDavid Howells } 53888b3384SDavid Howells 54888b3384SDavid Howells memcpy(x, bp, 4); 55888b3384SDavid Howells pr_notice("0x50: %08x\n", ntohl(x[0])); 56888b3384SDavid Howells } 57888b3384SDavid Howells 58888b3384SDavid Howells /* 59dd9fbcb8SDavid Howells * decode an AFSFetchStatus block 60dd9fbcb8SDavid Howells */ 61a58823acSDavid Howells static int xdr_decode_AFSFetchStatus(const __be32 **_bp, 62a58823acSDavid Howells struct afs_call *call, 63a58823acSDavid Howells struct afs_status_cb *scb) 64dd9fbcb8SDavid Howells { 65dd9fbcb8SDavid Howells const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp; 66a58823acSDavid Howells struct afs_file_status *status = &scb->status; 67684b0f68SDavid Howells bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus); 68dd9fbcb8SDavid Howells u64 data_version, size; 69dd9fbcb8SDavid Howells u32 type, abort_code; 70dd9fbcb8SDavid Howells 71684b0f68SDavid Howells abort_code = ntohl(xdr->abort_code); 72684b0f68SDavid Howells 73dd9fbcb8SDavid Howells if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { 74684b0f68SDavid Howells if (xdr->if_version == htonl(0) && 75684b0f68SDavid Howells abort_code != 0 && 76684b0f68SDavid Howells inline_error) { 77684b0f68SDavid Howells /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus 78684b0f68SDavid Howells * whereby it doesn't set the interface version in the error 79684b0f68SDavid Howells * case. 80684b0f68SDavid Howells */ 81684b0f68SDavid Howells status->abort_code = abort_code; 82a38a7558SDavid Howells scb->have_error = true; 83de52cf92SAl Viro return 0; 84684b0f68SDavid Howells } 85684b0f68SDavid Howells 86dd9fbcb8SDavid Howells pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); 87dd9fbcb8SDavid Howells goto bad; 88dd9fbcb8SDavid Howells } 89dd9fbcb8SDavid Howells 90684b0f68SDavid Howells if (abort_code != 0 && inline_error) { 91684b0f68SDavid Howells status->abort_code = abort_code; 92de52cf92SAl Viro return 0; 93684b0f68SDavid Howells } 94684b0f68SDavid Howells 95dd9fbcb8SDavid Howells type = ntohl(xdr->type); 96dd9fbcb8SDavid Howells switch (type) { 97dd9fbcb8SDavid Howells case AFS_FTYPE_FILE: 98dd9fbcb8SDavid Howells case AFS_FTYPE_DIR: 99dd9fbcb8SDavid Howells case AFS_FTYPE_SYMLINK: 100dd9fbcb8SDavid Howells status->type = type; 101dd9fbcb8SDavid Howells break; 102dd9fbcb8SDavid Howells default: 103dd9fbcb8SDavid Howells goto bad; 104dd9fbcb8SDavid Howells } 105dd9fbcb8SDavid Howells 106a58823acSDavid Howells status->nlink = ntohl(xdr->nlink); 107a58823acSDavid Howells status->author = ntohl(xdr->author); 108a58823acSDavid Howells status->owner = ntohl(xdr->owner); 109a58823acSDavid Howells status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */ 110a58823acSDavid Howells status->anon_access = ntohl(xdr->anon_access); 111a58823acSDavid Howells status->mode = ntohl(xdr->mode) & S_IALLUGO; 112a58823acSDavid Howells status->group = ntohl(xdr->group); 113a58823acSDavid Howells status->lock_count = ntohl(xdr->lock_count); 114dd9fbcb8SDavid Howells 115d4936803SDavid Howells status->mtime_client.tv_sec = ntohl(xdr->mtime_client); 116d4936803SDavid Howells status->mtime_client.tv_nsec = 0; 117d4936803SDavid Howells status->mtime_server.tv_sec = ntohl(xdr->mtime_server); 118d4936803SDavid Howells status->mtime_server.tv_nsec = 0; 119dd9fbcb8SDavid Howells 120dd9fbcb8SDavid Howells size = (u64)ntohl(xdr->size_lo); 121dd9fbcb8SDavid Howells size |= (u64)ntohl(xdr->size_hi) << 32; 122dd9fbcb8SDavid Howells status->size = size; 123dd9fbcb8SDavid Howells 124dd9fbcb8SDavid Howells data_version = (u64)ntohl(xdr->data_version_lo); 125dd9fbcb8SDavid Howells data_version |= (u64)ntohl(xdr->data_version_hi) << 32; 126dd9fbcb8SDavid Howells status->data_version = data_version; 127a38a7558SDavid Howells scb->have_status = true; 128dd9fbcb8SDavid Howells 129dd9fbcb8SDavid Howells *_bp = (const void *)*_bp + sizeof(*xdr); 130c875c76aSDavid Howells return 0; 131dd9fbcb8SDavid Howells 132dd9fbcb8SDavid Howells bad: 133dd9fbcb8SDavid Howells xdr_dump_bad(*_bp); 134160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); 135c875c76aSDavid Howells } 136c875c76aSDavid Howells 13778107055SDavid Howells static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) 13878107055SDavid Howells { 13978107055SDavid Howells return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; 14078107055SDavid Howells } 14178107055SDavid Howells 142a58823acSDavid Howells static void xdr_decode_AFSCallBack(const __be32 **_bp, 143a58823acSDavid Howells struct afs_call *call, 144a58823acSDavid Howells struct afs_status_cb *scb) 14578107055SDavid Howells { 146a58823acSDavid Howells struct afs_callback *cb = &scb->callback; 14778107055SDavid Howells const __be32 *bp = *_bp; 14878107055SDavid Howells 1497c712458SDavid Howells bp++; /* version */ 15078107055SDavid Howells cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); 1517c712458SDavid Howells bp++; /* type */ 152a58823acSDavid Howells scb->have_cb = true; 15378107055SDavid Howells *_bp = bp; 15478107055SDavid Howells } 15578107055SDavid Howells 1561da177e4SLinus Torvalds /* 15708e0e7c8SDavid Howells * decode an AFSVolSync block 1581da177e4SLinus Torvalds */ 15908e0e7c8SDavid Howells static void xdr_decode_AFSVolSync(const __be32 **_bp, 16008e0e7c8SDavid Howells struct afs_volsync *volsync) 1611da177e4SLinus Torvalds { 16208e0e7c8SDavid Howells const __be32 *bp = *_bp; 16330062bd1SDavid Howells u32 creation; 1641da177e4SLinus Torvalds 16530062bd1SDavid Howells creation = ntohl(*bp++); 16608e0e7c8SDavid Howells bp++; /* spare2 */ 16708e0e7c8SDavid Howells bp++; /* spare3 */ 16808e0e7c8SDavid Howells bp++; /* spare4 */ 16908e0e7c8SDavid Howells bp++; /* spare5 */ 17008e0e7c8SDavid Howells bp++; /* spare6 */ 17108e0e7c8SDavid Howells *_bp = bp; 17230062bd1SDavid Howells 17330062bd1SDavid Howells if (volsync) 17430062bd1SDavid Howells volsync->creation = creation; 1751da177e4SLinus Torvalds } 1761da177e4SLinus Torvalds 17708e0e7c8SDavid Howells /* 17831143d5dSDavid Howells * encode the requested attributes into an AFSStoreStatus block 17931143d5dSDavid Howells */ 18031143d5dSDavid Howells static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr) 18131143d5dSDavid Howells { 18231143d5dSDavid Howells __be32 *bp = *_bp; 18331143d5dSDavid Howells u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0; 18431143d5dSDavid Howells 18531143d5dSDavid Howells mask = 0; 18631143d5dSDavid Howells if (attr->ia_valid & ATTR_MTIME) { 18731143d5dSDavid Howells mask |= AFS_SET_MTIME; 18831143d5dSDavid Howells mtime = attr->ia_mtime.tv_sec; 18931143d5dSDavid Howells } 19031143d5dSDavid Howells 19131143d5dSDavid Howells if (attr->ia_valid & ATTR_UID) { 19231143d5dSDavid Howells mask |= AFS_SET_OWNER; 193a0a5386aSEric W. Biederman owner = from_kuid(&init_user_ns, attr->ia_uid); 19431143d5dSDavid Howells } 19531143d5dSDavid Howells 19631143d5dSDavid Howells if (attr->ia_valid & ATTR_GID) { 19731143d5dSDavid Howells mask |= AFS_SET_GROUP; 198a0a5386aSEric W. Biederman group = from_kgid(&init_user_ns, attr->ia_gid); 19931143d5dSDavid Howells } 20031143d5dSDavid Howells 20131143d5dSDavid Howells if (attr->ia_valid & ATTR_MODE) { 20231143d5dSDavid Howells mask |= AFS_SET_MODE; 20331143d5dSDavid Howells mode = attr->ia_mode & S_IALLUGO; 20431143d5dSDavid Howells } 20531143d5dSDavid Howells 20631143d5dSDavid Howells *bp++ = htonl(mask); 20731143d5dSDavid Howells *bp++ = htonl(mtime); 20831143d5dSDavid Howells *bp++ = htonl(owner); 20931143d5dSDavid Howells *bp++ = htonl(group); 21031143d5dSDavid Howells *bp++ = htonl(mode); 21131143d5dSDavid Howells *bp++ = 0; /* segment size */ 21231143d5dSDavid Howells *_bp = bp; 21331143d5dSDavid Howells } 21431143d5dSDavid Howells 21531143d5dSDavid Howells /* 21645222b9eSDavid Howells * decode an AFSFetchVolumeStatus block 21745222b9eSDavid Howells */ 21845222b9eSDavid Howells static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, 21945222b9eSDavid Howells struct afs_volume_status *vs) 22045222b9eSDavid Howells { 22145222b9eSDavid Howells const __be32 *bp = *_bp; 22245222b9eSDavid Howells 22345222b9eSDavid Howells vs->vid = ntohl(*bp++); 22445222b9eSDavid Howells vs->parent_id = ntohl(*bp++); 22545222b9eSDavid Howells vs->online = ntohl(*bp++); 22645222b9eSDavid Howells vs->in_service = ntohl(*bp++); 22745222b9eSDavid Howells vs->blessed = ntohl(*bp++); 22845222b9eSDavid Howells vs->needs_salvage = ntohl(*bp++); 22945222b9eSDavid Howells vs->type = ntohl(*bp++); 23045222b9eSDavid Howells vs->min_quota = ntohl(*bp++); 23145222b9eSDavid Howells vs->max_quota = ntohl(*bp++); 23245222b9eSDavid Howells vs->blocks_in_use = ntohl(*bp++); 23345222b9eSDavid Howells vs->part_blocks_avail = ntohl(*bp++); 23445222b9eSDavid Howells vs->part_max_blocks = ntohl(*bp++); 23530062bd1SDavid Howells vs->vol_copy_date = 0; 23630062bd1SDavid Howells vs->vol_backup_date = 0; 23745222b9eSDavid Howells *_bp = bp; 23845222b9eSDavid Howells } 23945222b9eSDavid Howells 24045222b9eSDavid Howells /* 24108e0e7c8SDavid Howells * deliver reply data to an FS.FetchStatus 24208e0e7c8SDavid Howells */ 2435cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) 24408e0e7c8SDavid Howells { 24508e0e7c8SDavid Howells const __be32 *bp; 246372ee163SDavid Howells int ret; 2471da177e4SLinus Torvalds 248d001648eSDavid Howells ret = afs_transfer_reply(call); 249372ee163SDavid Howells if (ret < 0) 250372ee163SDavid Howells return ret; 2511da177e4SLinus Torvalds 25208e0e7c8SDavid Howells /* unmarshall the reply once we've received all of it */ 25308e0e7c8SDavid Howells bp = call->buffer; 254a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 255160cb957SDavid Howells if (ret < 0) 256160cb957SDavid Howells return ret; 257a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 258ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2591da177e4SLinus Torvalds 26008e0e7c8SDavid Howells _leave(" = 0 [done]"); 26108e0e7c8SDavid Howells return 0; 262ec26815aSDavid Howells } 26308e0e7c8SDavid Howells 26408e0e7c8SDavid Howells /* 26508e0e7c8SDavid Howells * FS.FetchStatus operation type 26608e0e7c8SDavid Howells */ 2675cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus_vnode = { 2685cf9dd55SDavid Howells .name = "FS.FetchStatus(vnode)", 269025db80cSDavid Howells .op = afs_FS_FetchStatus, 2705cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status_vnode, 27108e0e7c8SDavid Howells .destructor = afs_flat_call_destructor, 27208e0e7c8SDavid Howells }; 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds /* 2751da177e4SLinus Torvalds * fetch the status information for a file 2761da177e4SLinus Torvalds */ 277a58823acSDavid Howells int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb, 278a58823acSDavid Howells struct afs_volsync *volsync) 2791da177e4SLinus Torvalds { 280d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 28108e0e7c8SDavid Howells struct afs_call *call; 282f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 2831da177e4SLinus Torvalds __be32 *bp; 2841da177e4SLinus Torvalds 28530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 286a58823acSDavid Howells return yfs_fs_fetch_file_status(fc, scb, volsync); 28730062bd1SDavid Howells 2883b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 289d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2901da177e4SLinus Torvalds 2915cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode, 2925cf9dd55SDavid Howells 16, (21 + 3 + 6) * 4); 293d2ddc776SDavid Howells if (!call) { 294d2ddc776SDavid Howells fc->ac.error = -ENOMEM; 29508e0e7c8SDavid Howells return -ENOMEM; 296d2ddc776SDavid Howells } 2971da177e4SLinus Torvalds 298d2ddc776SDavid Howells call->key = fc->key; 299a58823acSDavid Howells call->out_scb = scb; 300ffba718eSDavid Howells call->out_volsync = volsync; 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds /* marshall the parameters */ 30308e0e7c8SDavid Howells bp = call->request; 3041da177e4SLinus Torvalds bp[0] = htonl(FSFETCHSTATUS); 3051da177e4SLinus Torvalds bp[1] = htonl(vnode->fid.vid); 3061da177e4SLinus Torvalds bp[2] = htonl(vnode->fid.vnode); 3071da177e4SLinus Torvalds bp[3] = htonl(vnode->fid.unique); 3081da177e4SLinus Torvalds 309d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 310025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 3110b9bf381SDavid Howells 31220b8391fSDavid Howells afs_set_fc_call(call, fc); 3130b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 3140b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 315ec26815aSDavid Howells } 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /* 31808e0e7c8SDavid Howells * deliver reply data to an FS.FetchData 3191da177e4SLinus Torvalds */ 320d001648eSDavid Howells static int afs_deliver_fs_fetch_data(struct afs_call *call) 3211da177e4SLinus Torvalds { 322ffba718eSDavid Howells struct afs_read *req = call->read_request; 32308e0e7c8SDavid Howells const __be32 *bp; 324196ee9cdSDavid Howells unsigned int size; 3251da177e4SLinus Torvalds int ret; 3261da177e4SLinus Torvalds 32712bdcf33SDavid Howells _enter("{%u,%zu/%llu}", 32812bdcf33SDavid Howells call->unmarshall, iov_iter_count(&call->iter), req->actual_len); 3291da177e4SLinus Torvalds 33008e0e7c8SDavid Howells switch (call->unmarshall) { 33108e0e7c8SDavid Howells case 0: 332196ee9cdSDavid Howells req->actual_len = 0; 33312bdcf33SDavid Howells req->index = 0; 33412bdcf33SDavid Howells req->offset = req->pos & (PAGE_SIZE - 1); 33508e0e7c8SDavid Howells call->unmarshall++; 33612bdcf33SDavid Howells if (call->operation_ID == FSFETCHDATA64) { 33712bdcf33SDavid Howells afs_extract_to_tmp64(call); 33812bdcf33SDavid Howells } else { 33912bdcf33SDavid Howells call->tmp_u = htonl(0); 34012bdcf33SDavid Howells afs_extract_to_tmp(call); 341b9b1f8d5SDavid Howells } 3421da177e4SLinus Torvalds 343e690c9e3SGustavo A. R. Silva /* Fall through - and extract the returned data length */ 34412bdcf33SDavid Howells case 1: 34508e0e7c8SDavid Howells _debug("extract data length"); 34612bdcf33SDavid Howells ret = afs_extract_data(call, true); 347372ee163SDavid Howells if (ret < 0) 348372ee163SDavid Howells return ret; 3491da177e4SLinus Torvalds 35012bdcf33SDavid Howells req->actual_len = be64_to_cpu(call->tmp64); 351196ee9cdSDavid Howells _debug("DATA length: %llu", req->actual_len); 35212bdcf33SDavid Howells req->remain = min(req->len, req->actual_len); 35312bdcf33SDavid Howells if (req->remain == 0) 354196ee9cdSDavid Howells goto no_more_data; 35512bdcf33SDavid Howells 35608e0e7c8SDavid Howells call->unmarshall++; 3571da177e4SLinus Torvalds 358196ee9cdSDavid Howells begin_page: 3596db3ac3cSDavid Howells ASSERTCMP(req->index, <, req->nr_pages); 36012bdcf33SDavid Howells if (req->remain > PAGE_SIZE - req->offset) 36112bdcf33SDavid Howells size = PAGE_SIZE - req->offset; 362196ee9cdSDavid Howells else 363196ee9cdSDavid Howells size = req->remain; 36412bdcf33SDavid Howells call->bvec[0].bv_len = size; 36512bdcf33SDavid Howells call->bvec[0].bv_offset = req->offset; 36612bdcf33SDavid Howells call->bvec[0].bv_page = req->pages[req->index]; 36712bdcf33SDavid Howells iov_iter_bvec(&call->iter, READ, call->bvec, 1, size); 36812bdcf33SDavid Howells ASSERTCMP(size, <=, PAGE_SIZE); 369196ee9cdSDavid Howells 370e690c9e3SGustavo A. R. Silva /* Fall through - and extract the returned data */ 37112bdcf33SDavid Howells case 2: 37212bdcf33SDavid Howells _debug("extract data %zu/%llu", 37312bdcf33SDavid Howells iov_iter_count(&call->iter), req->remain); 374196ee9cdSDavid Howells 37512bdcf33SDavid Howells ret = afs_extract_data(call, true); 376372ee163SDavid Howells if (ret < 0) 377372ee163SDavid Howells return ret; 37812bdcf33SDavid Howells req->remain -= call->bvec[0].bv_len; 37912bdcf33SDavid Howells req->offset += call->bvec[0].bv_len; 38012bdcf33SDavid Howells ASSERTCMP(req->offset, <=, PAGE_SIZE); 38112bdcf33SDavid Howells if (req->offset == PAGE_SIZE) { 38212bdcf33SDavid Howells req->offset = 0; 383196ee9cdSDavid Howells if (req->page_done) 384a58823acSDavid Howells req->page_done(req); 38529f06985SDavid Howells req->index++; 38612bdcf33SDavid Howells if (req->remain > 0) 387196ee9cdSDavid Howells goto begin_page; 388196ee9cdSDavid Howells } 38912bdcf33SDavid Howells 39012bdcf33SDavid Howells ASSERTCMP(req->remain, ==, 0); 39112bdcf33SDavid Howells if (req->actual_len <= req->len) 3926db3ac3cSDavid Howells goto no_more_data; 3936db3ac3cSDavid Howells 3946db3ac3cSDavid Howells /* Discard any excess data the server gave us */ 39512bdcf33SDavid Howells iov_iter_discard(&call->iter, READ, req->actual_len - req->len); 39612bdcf33SDavid Howells call->unmarshall = 3; 397e690c9e3SGustavo A. R. Silva 398e690c9e3SGustavo A. R. Silva /* Fall through */ 39912bdcf33SDavid Howells case 3: 40012bdcf33SDavid Howells _debug("extract discard %zu/%llu", 40112bdcf33SDavid Howells iov_iter_count(&call->iter), req->actual_len - req->len); 4026db3ac3cSDavid Howells 40312bdcf33SDavid Howells ret = afs_extract_data(call, true); 4046db3ac3cSDavid Howells if (ret < 0) 4056db3ac3cSDavid Howells return ret; 4061da177e4SLinus Torvalds 407196ee9cdSDavid Howells no_more_data: 40812bdcf33SDavid Howells call->unmarshall = 4; 40912bdcf33SDavid Howells afs_extract_to_buf(call, (21 + 3 + 6) * 4); 41008e0e7c8SDavid Howells 411e690c9e3SGustavo A. R. Silva /* Fall through - and extract the metadata */ 41212bdcf33SDavid Howells case 4: 41312bdcf33SDavid Howells ret = afs_extract_data(call, false); 414372ee163SDavid Howells if (ret < 0) 415372ee163SDavid Howells return ret; 4161da177e4SLinus Torvalds 41708e0e7c8SDavid Howells bp = call->buffer; 418a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 419160cb957SDavid Howells if (ret < 0) 420160cb957SDavid Howells return ret; 421a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 422ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 4231da177e4SLinus Torvalds 424a58823acSDavid Howells req->data_version = call->out_scb->status.data_version; 425a58823acSDavid Howells req->file_size = call->out_scb->status.size; 426a58823acSDavid Howells 42708e0e7c8SDavid Howells call->unmarshall++; 4281da177e4SLinus Torvalds 42912bdcf33SDavid Howells case 5: 4301da177e4SLinus Torvalds break; 4311da177e4SLinus Torvalds } 4321da177e4SLinus Torvalds 4336db3ac3cSDavid Howells for (; req->index < req->nr_pages; req->index++) { 43412bdcf33SDavid Howells if (req->offset < PAGE_SIZE) 4356db3ac3cSDavid Howells zero_user_segment(req->pages[req->index], 43612bdcf33SDavid Howells req->offset, PAGE_SIZE); 437196ee9cdSDavid Howells if (req->page_done) 438a58823acSDavid Howells req->page_done(req); 43912bdcf33SDavid Howells req->offset = 0; 440416351f2SDavid Howells } 441416351f2SDavid Howells 44208e0e7c8SDavid Howells _leave(" = 0 [done]"); 44308e0e7c8SDavid Howells return 0; 444ec26815aSDavid Howells } 4451da177e4SLinus Torvalds 446196ee9cdSDavid Howells static void afs_fetch_data_destructor(struct afs_call *call) 447196ee9cdSDavid Howells { 448ffba718eSDavid Howells struct afs_read *req = call->read_request; 449196ee9cdSDavid Howells 450196ee9cdSDavid Howells afs_put_read(req); 451196ee9cdSDavid Howells afs_flat_call_destructor(call); 452196ee9cdSDavid Howells } 453196ee9cdSDavid Howells 4541da177e4SLinus Torvalds /* 45508e0e7c8SDavid Howells * FS.FetchData operation type 4561da177e4SLinus Torvalds */ 45708e0e7c8SDavid Howells static const struct afs_call_type afs_RXFSFetchData = { 45800d3b7a4SDavid Howells .name = "FS.FetchData", 459025db80cSDavid Howells .op = afs_FS_FetchData, 46008e0e7c8SDavid Howells .deliver = afs_deliver_fs_fetch_data, 461196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 46208e0e7c8SDavid Howells }; 46308e0e7c8SDavid Howells 464b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSFetchData64 = { 465b9b1f8d5SDavid Howells .name = "FS.FetchData64", 466025db80cSDavid Howells .op = afs_FS_FetchData64, 467b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_fetch_data, 468196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 469b9b1f8d5SDavid Howells }; 470b9b1f8d5SDavid Howells 471b9b1f8d5SDavid Howells /* 472b9b1f8d5SDavid Howells * fetch data from a very large file 473b9b1f8d5SDavid Howells */ 474a58823acSDavid Howells static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, 475a58823acSDavid Howells struct afs_status_cb *scb, 476a58823acSDavid Howells struct afs_read *req) 477b9b1f8d5SDavid Howells { 478d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 479b9b1f8d5SDavid Howells struct afs_call *call; 480f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 481b9b1f8d5SDavid Howells __be32 *bp; 482b9b1f8d5SDavid Howells 483b9b1f8d5SDavid Howells _enter(""); 484b9b1f8d5SDavid Howells 485f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4); 486b9b1f8d5SDavid Howells if (!call) 487b9b1f8d5SDavid Howells return -ENOMEM; 488b9b1f8d5SDavid Howells 489d2ddc776SDavid Howells call->key = fc->key; 490a58823acSDavid Howells call->out_scb = scb; 491ffba718eSDavid Howells call->out_volsync = NULL; 492ffba718eSDavid Howells call->read_request = req; 493b9b1f8d5SDavid Howells 494b9b1f8d5SDavid Howells /* marshall the parameters */ 495b9b1f8d5SDavid Howells bp = call->request; 496b9b1f8d5SDavid Howells bp[0] = htonl(FSFETCHDATA64); 497b9b1f8d5SDavid Howells bp[1] = htonl(vnode->fid.vid); 498b9b1f8d5SDavid Howells bp[2] = htonl(vnode->fid.vnode); 499b9b1f8d5SDavid Howells bp[3] = htonl(vnode->fid.unique); 500196ee9cdSDavid Howells bp[4] = htonl(upper_32_bits(req->pos)); 501196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->pos)); 502b9b1f8d5SDavid Howells bp[6] = 0; 503196ee9cdSDavid Howells bp[7] = htonl(lower_32_bits(req->len)); 504b9b1f8d5SDavid Howells 505f3ddee8dSDavid Howells refcount_inc(&req->usage); 506d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 507025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 50820b8391fSDavid Howells afs_set_fc_call(call, fc); 5090b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5100b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 511b9b1f8d5SDavid Howells } 512b9b1f8d5SDavid Howells 51308e0e7c8SDavid Howells /* 51408e0e7c8SDavid Howells * fetch data from a file 51508e0e7c8SDavid Howells */ 516a58823acSDavid Howells int afs_fs_fetch_data(struct afs_fs_cursor *fc, 517a58823acSDavid Howells struct afs_status_cb *scb, 518a58823acSDavid Howells struct afs_read *req) 5191da177e4SLinus Torvalds { 520d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 52108e0e7c8SDavid Howells struct afs_call *call; 522f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 52308e0e7c8SDavid Howells __be32 *bp; 5241da177e4SLinus Torvalds 52530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 526a58823acSDavid Howells return yfs_fs_fetch_data(fc, scb, req); 52730062bd1SDavid Howells 528196ee9cdSDavid Howells if (upper_32_bits(req->pos) || 529196ee9cdSDavid Howells upper_32_bits(req->len) || 530196ee9cdSDavid Howells upper_32_bits(req->pos + req->len)) 531a58823acSDavid Howells return afs_fs_fetch_data64(fc, scb, req); 532b9b1f8d5SDavid Howells 53308e0e7c8SDavid Howells _enter(""); 5341da177e4SLinus Torvalds 535f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4); 53608e0e7c8SDavid Howells if (!call) 53708e0e7c8SDavid Howells return -ENOMEM; 5381da177e4SLinus Torvalds 539d2ddc776SDavid Howells call->key = fc->key; 540a58823acSDavid Howells call->out_scb = scb; 541ffba718eSDavid Howells call->out_volsync = NULL; 542ffba718eSDavid Howells call->read_request = req; 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds /* marshall the parameters */ 54508e0e7c8SDavid Howells bp = call->request; 54608e0e7c8SDavid Howells bp[0] = htonl(FSFETCHDATA); 54708e0e7c8SDavid Howells bp[1] = htonl(vnode->fid.vid); 54808e0e7c8SDavid Howells bp[2] = htonl(vnode->fid.vnode); 54908e0e7c8SDavid Howells bp[3] = htonl(vnode->fid.unique); 550196ee9cdSDavid Howells bp[4] = htonl(lower_32_bits(req->pos)); 551196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->len)); 5521da177e4SLinus Torvalds 553f3ddee8dSDavid Howells refcount_inc(&req->usage); 554d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 555025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 55620b8391fSDavid Howells afs_set_fc_call(call, fc); 5570b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5580b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 55908e0e7c8SDavid Howells } 560260a9803SDavid Howells 561260a9803SDavid Howells /* 562260a9803SDavid Howells * deliver reply data to an FS.CreateFile or an FS.MakeDir 563260a9803SDavid Howells */ 564d001648eSDavid Howells static int afs_deliver_fs_create_vnode(struct afs_call *call) 565260a9803SDavid Howells { 566260a9803SDavid Howells const __be32 *bp; 567372ee163SDavid Howells int ret; 568260a9803SDavid Howells 569d001648eSDavid Howells ret = afs_transfer_reply(call); 570372ee163SDavid Howells if (ret < 0) 571372ee163SDavid Howells return ret; 572260a9803SDavid Howells 573260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 574260a9803SDavid Howells bp = call->buffer; 575ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 576a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 577160cb957SDavid Howells if (ret < 0) 578160cb957SDavid Howells return ret; 579a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 580160cb957SDavid Howells if (ret < 0) 581160cb957SDavid Howells return ret; 582a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 583ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 584260a9803SDavid Howells 585260a9803SDavid Howells _leave(" = 0 [done]"); 586260a9803SDavid Howells return 0; 587260a9803SDavid Howells } 588260a9803SDavid Howells 589260a9803SDavid Howells /* 590260a9803SDavid Howells * FS.CreateFile and FS.MakeDir operation type 591260a9803SDavid Howells */ 592025db80cSDavid Howells static const struct afs_call_type afs_RXFSCreateFile = { 593025db80cSDavid Howells .name = "FS.CreateFile", 594025db80cSDavid Howells .op = afs_FS_CreateFile, 595025db80cSDavid Howells .deliver = afs_deliver_fs_create_vnode, 596025db80cSDavid Howells .destructor = afs_flat_call_destructor, 597025db80cSDavid Howells }; 598025db80cSDavid Howells 599025db80cSDavid Howells static const struct afs_call_type afs_RXFSMakeDir = { 600025db80cSDavid Howells .name = "FS.MakeDir", 601025db80cSDavid Howells .op = afs_FS_MakeDir, 602260a9803SDavid Howells .deliver = afs_deliver_fs_create_vnode, 603260a9803SDavid Howells .destructor = afs_flat_call_destructor, 604260a9803SDavid Howells }; 605260a9803SDavid Howells 606260a9803SDavid Howells /* 607260a9803SDavid Howells * create a file or make a directory 608260a9803SDavid Howells */ 6098b2a464cSDavid Howells int afs_fs_create(struct afs_fs_cursor *fc, 610260a9803SDavid Howells const char *name, 611260a9803SDavid Howells umode_t mode, 612a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 613260a9803SDavid Howells struct afs_fid *newfid, 614a58823acSDavid Howells struct afs_status_cb *new_scb) 615260a9803SDavid Howells { 616ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 617260a9803SDavid Howells struct afs_call *call; 618ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 619260a9803SDavid Howells size_t namesz, reqsz, padsz; 620260a9803SDavid Howells __be32 *bp; 621260a9803SDavid Howells 62230062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){ 62330062bd1SDavid Howells if (S_ISDIR(mode)) 624a58823acSDavid Howells return yfs_fs_make_dir(fc, name, mode, dvnode_scb, 625a58823acSDavid Howells newfid, new_scb); 62630062bd1SDavid Howells else 627a58823acSDavid Howells return yfs_fs_create_file(fc, name, mode, dvnode_scb, 628a58823acSDavid Howells newfid, new_scb); 62930062bd1SDavid Howells } 63030062bd1SDavid Howells 631260a9803SDavid Howells _enter(""); 632260a9803SDavid Howells 633260a9803SDavid Howells namesz = strlen(name); 634260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 635260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (6 * 4); 636260a9803SDavid Howells 637025db80cSDavid Howells call = afs_alloc_flat_call( 638025db80cSDavid Howells net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile, 639025db80cSDavid Howells reqsz, (3 + 21 + 21 + 3 + 6) * 4); 640260a9803SDavid Howells if (!call) 641260a9803SDavid Howells return -ENOMEM; 642260a9803SDavid Howells 643d2ddc776SDavid Howells call->key = fc->key; 644a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 645ffba718eSDavid Howells call->out_fid = newfid; 646a58823acSDavid Howells call->out_scb = new_scb; 647260a9803SDavid Howells 648260a9803SDavid Howells /* marshall the parameters */ 649260a9803SDavid Howells bp = call->request; 650260a9803SDavid Howells *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); 651ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 652ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 653ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 654260a9803SDavid Howells *bp++ = htonl(namesz); 655260a9803SDavid Howells memcpy(bp, name, namesz); 656260a9803SDavid Howells bp = (void *) bp + namesz; 657260a9803SDavid Howells if (padsz > 0) { 658260a9803SDavid Howells memset(bp, 0, padsz); 659260a9803SDavid Howells bp = (void *) bp + padsz; 660260a9803SDavid Howells } 661ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 662ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 663260a9803SDavid Howells *bp++ = 0; /* owner */ 664260a9803SDavid Howells *bp++ = 0; /* group */ 665260a9803SDavid Howells *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ 666260a9803SDavid Howells *bp++ = 0; /* segment size */ 667260a9803SDavid Howells 668d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 669ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 67020b8391fSDavid Howells afs_set_fc_call(call, fc); 6710b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 6720b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 673260a9803SDavid Howells } 674260a9803SDavid Howells 675260a9803SDavid Howells /* 676ffba718eSDavid Howells * Deliver reply data to any operation that returns directory status and volume 677b10494afSJoe Gorse * sync. 678260a9803SDavid Howells */ 679ffba718eSDavid Howells static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call) 680260a9803SDavid Howells { 681260a9803SDavid Howells const __be32 *bp; 682372ee163SDavid Howells int ret; 683260a9803SDavid Howells 684d001648eSDavid Howells ret = afs_transfer_reply(call); 685372ee163SDavid Howells if (ret < 0) 686372ee163SDavid Howells return ret; 687260a9803SDavid Howells 688260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 689260a9803SDavid Howells bp = call->buffer; 690a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 691160cb957SDavid Howells if (ret < 0) 692160cb957SDavid Howells return ret; 693ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 694260a9803SDavid Howells 695260a9803SDavid Howells _leave(" = 0 [done]"); 696260a9803SDavid Howells return 0; 697260a9803SDavid Howells } 698260a9803SDavid Howells 699260a9803SDavid Howells /* 700260a9803SDavid Howells * FS.RemoveDir/FS.RemoveFile operation type 701260a9803SDavid Howells */ 702025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveFile = { 703025db80cSDavid Howells .name = "FS.RemoveFile", 704025db80cSDavid Howells .op = afs_FS_RemoveFile, 705ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 706025db80cSDavid Howells .destructor = afs_flat_call_destructor, 707025db80cSDavid Howells }; 708025db80cSDavid Howells 709025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveDir = { 710025db80cSDavid Howells .name = "FS.RemoveDir", 711025db80cSDavid Howells .op = afs_FS_RemoveDir, 712ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 713260a9803SDavid Howells .destructor = afs_flat_call_destructor, 714260a9803SDavid Howells }; 715260a9803SDavid Howells 716260a9803SDavid Howells /* 717260a9803SDavid Howells * remove a file or directory 718260a9803SDavid Howells */ 71930062bd1SDavid Howells int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 720a58823acSDavid Howells const char *name, bool isdir, struct afs_status_cb *dvnode_scb) 721260a9803SDavid Howells { 72230062bd1SDavid Howells struct afs_vnode *dvnode = fc->vnode; 723260a9803SDavid Howells struct afs_call *call; 72430062bd1SDavid Howells struct afs_net *net = afs_v2net(dvnode); 725260a9803SDavid Howells size_t namesz, reqsz, padsz; 726260a9803SDavid Howells __be32 *bp; 727260a9803SDavid Howells 72830062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 729a58823acSDavid Howells return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb); 73030062bd1SDavid Howells 731260a9803SDavid Howells _enter(""); 732260a9803SDavid Howells 733260a9803SDavid Howells namesz = strlen(name); 734260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 735260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz; 736260a9803SDavid Howells 737025db80cSDavid Howells call = afs_alloc_flat_call( 738025db80cSDavid Howells net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile, 739025db80cSDavid Howells reqsz, (21 + 6) * 4); 740260a9803SDavid Howells if (!call) 741260a9803SDavid Howells return -ENOMEM; 742260a9803SDavid Howells 743d2ddc776SDavid Howells call->key = fc->key; 744a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 745260a9803SDavid Howells 746260a9803SDavid Howells /* marshall the parameters */ 747260a9803SDavid Howells bp = call->request; 748260a9803SDavid Howells *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); 74930062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vid); 75030062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 75130062bd1SDavid Howells *bp++ = htonl(dvnode->fid.unique); 752260a9803SDavid Howells *bp++ = htonl(namesz); 753260a9803SDavid Howells memcpy(bp, name, namesz); 754260a9803SDavid Howells bp = (void *) bp + namesz; 755260a9803SDavid Howells if (padsz > 0) { 756260a9803SDavid Howells memset(bp, 0, padsz); 757260a9803SDavid Howells bp = (void *) bp + padsz; 758260a9803SDavid Howells } 759260a9803SDavid Howells 760d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 76180548b03SDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 76220b8391fSDavid Howells afs_set_fc_call(call, fc); 7630b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 7640b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 765260a9803SDavid Howells } 766260a9803SDavid Howells 767260a9803SDavid Howells /* 768260a9803SDavid Howells * deliver reply data to an FS.Link 769260a9803SDavid Howells */ 770d001648eSDavid Howells static int afs_deliver_fs_link(struct afs_call *call) 771260a9803SDavid Howells { 772260a9803SDavid Howells const __be32 *bp; 773372ee163SDavid Howells int ret; 774260a9803SDavid Howells 775d001648eSDavid Howells _enter("{%u}", call->unmarshall); 776260a9803SDavid Howells 777d001648eSDavid Howells ret = afs_transfer_reply(call); 778372ee163SDavid Howells if (ret < 0) 779372ee163SDavid Howells return ret; 780260a9803SDavid Howells 781260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 782260a9803SDavid Howells bp = call->buffer; 783a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 784160cb957SDavid Howells if (ret < 0) 785160cb957SDavid Howells return ret; 786a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 787160cb957SDavid Howells if (ret < 0) 788160cb957SDavid Howells return ret; 789ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 790260a9803SDavid Howells 791260a9803SDavid Howells _leave(" = 0 [done]"); 792260a9803SDavid Howells return 0; 793260a9803SDavid Howells } 794260a9803SDavid Howells 795260a9803SDavid Howells /* 796260a9803SDavid Howells * FS.Link operation type 797260a9803SDavid Howells */ 798260a9803SDavid Howells static const struct afs_call_type afs_RXFSLink = { 799260a9803SDavid Howells .name = "FS.Link", 800025db80cSDavid Howells .op = afs_FS_Link, 801260a9803SDavid Howells .deliver = afs_deliver_fs_link, 802260a9803SDavid Howells .destructor = afs_flat_call_destructor, 803260a9803SDavid Howells }; 804260a9803SDavid Howells 805260a9803SDavid Howells /* 806260a9803SDavid Howells * make a hard link 807260a9803SDavid Howells */ 808d2ddc776SDavid Howells int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 809a58823acSDavid Howells const char *name, 810a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 811a58823acSDavid Howells struct afs_status_cb *vnode_scb) 812260a9803SDavid Howells { 813d2ddc776SDavid Howells struct afs_vnode *dvnode = fc->vnode; 814260a9803SDavid Howells struct afs_call *call; 815f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 816260a9803SDavid Howells size_t namesz, reqsz, padsz; 817260a9803SDavid Howells __be32 *bp; 818260a9803SDavid Howells 81930062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 820a58823acSDavid Howells return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb); 82130062bd1SDavid Howells 822260a9803SDavid Howells _enter(""); 823260a9803SDavid Howells 824260a9803SDavid Howells namesz = strlen(name); 825260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 826260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (3 * 4); 827260a9803SDavid Howells 828f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4); 829260a9803SDavid Howells if (!call) 830260a9803SDavid Howells return -ENOMEM; 831260a9803SDavid Howells 832d2ddc776SDavid Howells call->key = fc->key; 833a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 834a58823acSDavid Howells call->out_scb = vnode_scb; 835260a9803SDavid Howells 836260a9803SDavid Howells /* marshall the parameters */ 837260a9803SDavid Howells bp = call->request; 838260a9803SDavid Howells *bp++ = htonl(FSLINK); 839260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vid); 840260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 841260a9803SDavid Howells *bp++ = htonl(dvnode->fid.unique); 842260a9803SDavid Howells *bp++ = htonl(namesz); 843260a9803SDavid Howells memcpy(bp, name, namesz); 844260a9803SDavid Howells bp = (void *) bp + namesz; 845260a9803SDavid Howells if (padsz > 0) { 846260a9803SDavid Howells memset(bp, 0, padsz); 847260a9803SDavid Howells bp = (void *) bp + padsz; 848260a9803SDavid Howells } 849260a9803SDavid Howells *bp++ = htonl(vnode->fid.vid); 850260a9803SDavid Howells *bp++ = htonl(vnode->fid.vnode); 851260a9803SDavid Howells *bp++ = htonl(vnode->fid.unique); 852260a9803SDavid Howells 853d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 85480548b03SDavid Howells trace_afs_make_fs_call1(call, &vnode->fid, name); 85520b8391fSDavid Howells afs_set_fc_call(call, fc); 8560b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 8570b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 858260a9803SDavid Howells } 859260a9803SDavid Howells 860260a9803SDavid Howells /* 861260a9803SDavid Howells * deliver reply data to an FS.Symlink 862260a9803SDavid Howells */ 863d001648eSDavid Howells static int afs_deliver_fs_symlink(struct afs_call *call) 864260a9803SDavid Howells { 865260a9803SDavid Howells const __be32 *bp; 866372ee163SDavid Howells int ret; 867260a9803SDavid Howells 868d001648eSDavid Howells _enter("{%u}", call->unmarshall); 869260a9803SDavid Howells 870d001648eSDavid Howells ret = afs_transfer_reply(call); 871372ee163SDavid Howells if (ret < 0) 872372ee163SDavid Howells return ret; 873260a9803SDavid Howells 874260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 875260a9803SDavid Howells bp = call->buffer; 876ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 877a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 878160cb957SDavid Howells if (ret < 0) 879160cb957SDavid Howells return ret; 880a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 881160cb957SDavid Howells if (ret < 0) 882160cb957SDavid Howells return ret; 883ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 884260a9803SDavid Howells 885260a9803SDavid Howells _leave(" = 0 [done]"); 886260a9803SDavid Howells return 0; 887260a9803SDavid Howells } 888260a9803SDavid Howells 889260a9803SDavid Howells /* 890260a9803SDavid Howells * FS.Symlink operation type 891260a9803SDavid Howells */ 892260a9803SDavid Howells static const struct afs_call_type afs_RXFSSymlink = { 893260a9803SDavid Howells .name = "FS.Symlink", 894025db80cSDavid Howells .op = afs_FS_Symlink, 895260a9803SDavid Howells .deliver = afs_deliver_fs_symlink, 896260a9803SDavid Howells .destructor = afs_flat_call_destructor, 897260a9803SDavid Howells }; 898260a9803SDavid Howells 899260a9803SDavid Howells /* 900260a9803SDavid Howells * create a symbolic link 901260a9803SDavid Howells */ 9028b2a464cSDavid Howells int afs_fs_symlink(struct afs_fs_cursor *fc, 903260a9803SDavid Howells const char *name, 904260a9803SDavid Howells const char *contents, 905a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 906260a9803SDavid Howells struct afs_fid *newfid, 907a58823acSDavid Howells struct afs_status_cb *new_scb) 908260a9803SDavid Howells { 909ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 910260a9803SDavid Howells struct afs_call *call; 911ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 912260a9803SDavid Howells size_t namesz, reqsz, padsz, c_namesz, c_padsz; 913260a9803SDavid Howells __be32 *bp; 914260a9803SDavid Howells 91530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 916a58823acSDavid Howells return yfs_fs_symlink(fc, name, contents, dvnode_scb, 917a58823acSDavid Howells newfid, new_scb); 91830062bd1SDavid Howells 919260a9803SDavid Howells _enter(""); 920260a9803SDavid Howells 921260a9803SDavid Howells namesz = strlen(name); 922260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 923260a9803SDavid Howells 924260a9803SDavid Howells c_namesz = strlen(contents); 925260a9803SDavid Howells c_padsz = (4 - (c_namesz & 3)) & 3; 926260a9803SDavid Howells 927260a9803SDavid Howells reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4); 928260a9803SDavid Howells 929f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz, 930260a9803SDavid Howells (3 + 21 + 21 + 6) * 4); 931260a9803SDavid Howells if (!call) 932260a9803SDavid Howells return -ENOMEM; 933260a9803SDavid Howells 934d2ddc776SDavid Howells call->key = fc->key; 935a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 936ffba718eSDavid Howells call->out_fid = newfid; 937a58823acSDavid Howells call->out_scb = new_scb; 938260a9803SDavid Howells 939260a9803SDavid Howells /* marshall the parameters */ 940260a9803SDavid Howells bp = call->request; 941260a9803SDavid Howells *bp++ = htonl(FSSYMLINK); 942ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 943ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 944ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 945260a9803SDavid Howells *bp++ = htonl(namesz); 946260a9803SDavid Howells memcpy(bp, name, namesz); 947260a9803SDavid Howells bp = (void *) bp + namesz; 948260a9803SDavid Howells if (padsz > 0) { 949260a9803SDavid Howells memset(bp, 0, padsz); 950260a9803SDavid Howells bp = (void *) bp + padsz; 951260a9803SDavid Howells } 952260a9803SDavid Howells *bp++ = htonl(c_namesz); 953260a9803SDavid Howells memcpy(bp, contents, c_namesz); 954260a9803SDavid Howells bp = (void *) bp + c_namesz; 955260a9803SDavid Howells if (c_padsz > 0) { 956260a9803SDavid Howells memset(bp, 0, c_padsz); 957260a9803SDavid Howells bp = (void *) bp + c_padsz; 958260a9803SDavid Howells } 959ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 960ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 961260a9803SDavid Howells *bp++ = 0; /* owner */ 962260a9803SDavid Howells *bp++ = 0; /* group */ 963260a9803SDavid Howells *bp++ = htonl(S_IRWXUGO); /* unix mode */ 964260a9803SDavid Howells *bp++ = 0; /* segment size */ 965260a9803SDavid Howells 966d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 967ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 96820b8391fSDavid Howells afs_set_fc_call(call, fc); 9690b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 9700b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 971260a9803SDavid Howells } 972260a9803SDavid Howells 973260a9803SDavid Howells /* 974260a9803SDavid Howells * deliver reply data to an FS.Rename 975260a9803SDavid Howells */ 976d001648eSDavid Howells static int afs_deliver_fs_rename(struct afs_call *call) 977260a9803SDavid Howells { 978260a9803SDavid Howells const __be32 *bp; 979372ee163SDavid Howells int ret; 980260a9803SDavid Howells 981d001648eSDavid Howells ret = afs_transfer_reply(call); 982372ee163SDavid Howells if (ret < 0) 983372ee163SDavid Howells return ret; 984260a9803SDavid Howells 985260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 986260a9803SDavid Howells bp = call->buffer; 987a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 988160cb957SDavid Howells if (ret < 0) 989160cb957SDavid Howells return ret; 990a58823acSDavid Howells if (call->out_dir_scb != call->out_scb) { 991a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 992160cb957SDavid Howells if (ret < 0) 993160cb957SDavid Howells return ret; 994160cb957SDavid Howells } 995ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 996260a9803SDavid Howells 997260a9803SDavid Howells _leave(" = 0 [done]"); 998260a9803SDavid Howells return 0; 999260a9803SDavid Howells } 1000260a9803SDavid Howells 1001260a9803SDavid Howells /* 1002260a9803SDavid Howells * FS.Rename operation type 1003260a9803SDavid Howells */ 1004260a9803SDavid Howells static const struct afs_call_type afs_RXFSRename = { 1005260a9803SDavid Howells .name = "FS.Rename", 1006025db80cSDavid Howells .op = afs_FS_Rename, 1007260a9803SDavid Howells .deliver = afs_deliver_fs_rename, 1008260a9803SDavid Howells .destructor = afs_flat_call_destructor, 1009260a9803SDavid Howells }; 1010260a9803SDavid Howells 1011260a9803SDavid Howells /* 1012a58823acSDavid Howells * Rename/move a file or directory. 1013260a9803SDavid Howells */ 10148b2a464cSDavid Howells int afs_fs_rename(struct afs_fs_cursor *fc, 1015260a9803SDavid Howells const char *orig_name, 1016260a9803SDavid Howells struct afs_vnode *new_dvnode, 101763a4681fSDavid Howells const char *new_name, 1018a58823acSDavid Howells struct afs_status_cb *orig_dvnode_scb, 1019a58823acSDavid Howells struct afs_status_cb *new_dvnode_scb) 1020260a9803SDavid Howells { 1021d2ddc776SDavid Howells struct afs_vnode *orig_dvnode = fc->vnode; 1022260a9803SDavid Howells struct afs_call *call; 1023f044c884SDavid Howells struct afs_net *net = afs_v2net(orig_dvnode); 1024260a9803SDavid Howells size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; 1025260a9803SDavid Howells __be32 *bp; 1026260a9803SDavid Howells 102730062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 102830062bd1SDavid Howells return yfs_fs_rename(fc, orig_name, 102930062bd1SDavid Howells new_dvnode, new_name, 1030a58823acSDavid Howells orig_dvnode_scb, 1031a58823acSDavid Howells new_dvnode_scb); 103230062bd1SDavid Howells 1033260a9803SDavid Howells _enter(""); 1034260a9803SDavid Howells 1035260a9803SDavid Howells o_namesz = strlen(orig_name); 1036260a9803SDavid Howells o_padsz = (4 - (o_namesz & 3)) & 3; 1037260a9803SDavid Howells 1038260a9803SDavid Howells n_namesz = strlen(new_name); 1039260a9803SDavid Howells n_padsz = (4 - (n_namesz & 3)) & 3; 1040260a9803SDavid Howells 1041260a9803SDavid Howells reqsz = (4 * 4) + 1042260a9803SDavid Howells 4 + o_namesz + o_padsz + 1043260a9803SDavid Howells (3 * 4) + 1044260a9803SDavid Howells 4 + n_namesz + n_padsz; 1045260a9803SDavid Howells 1046f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4); 1047260a9803SDavid Howells if (!call) 1048260a9803SDavid Howells return -ENOMEM; 1049260a9803SDavid Howells 1050d2ddc776SDavid Howells call->key = fc->key; 1051a58823acSDavid Howells call->out_dir_scb = orig_dvnode_scb; 1052a58823acSDavid Howells call->out_scb = new_dvnode_scb; 1053260a9803SDavid Howells 1054260a9803SDavid Howells /* marshall the parameters */ 1055260a9803SDavid Howells bp = call->request; 1056260a9803SDavid Howells *bp++ = htonl(FSRENAME); 1057260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vid); 1058260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vnode); 1059260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.unique); 1060260a9803SDavid Howells *bp++ = htonl(o_namesz); 1061260a9803SDavid Howells memcpy(bp, orig_name, o_namesz); 1062260a9803SDavid Howells bp = (void *) bp + o_namesz; 1063260a9803SDavid Howells if (o_padsz > 0) { 1064260a9803SDavid Howells memset(bp, 0, o_padsz); 1065260a9803SDavid Howells bp = (void *) bp + o_padsz; 1066260a9803SDavid Howells } 1067260a9803SDavid Howells 1068260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vid); 1069260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vnode); 1070260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.unique); 1071260a9803SDavid Howells *bp++ = htonl(n_namesz); 1072260a9803SDavid Howells memcpy(bp, new_name, n_namesz); 1073260a9803SDavid Howells bp = (void *) bp + n_namesz; 1074260a9803SDavid Howells if (n_padsz > 0) { 1075260a9803SDavid Howells memset(bp, 0, n_padsz); 1076260a9803SDavid Howells bp = (void *) bp + n_padsz; 1077260a9803SDavid Howells } 1078260a9803SDavid Howells 1079d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 108080548b03SDavid Howells trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name); 108120b8391fSDavid Howells afs_set_fc_call(call, fc); 10820b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 10830b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1084260a9803SDavid Howells } 108531143d5dSDavid Howells 108631143d5dSDavid Howells /* 108731143d5dSDavid Howells * deliver reply data to an FS.StoreData 108831143d5dSDavid Howells */ 1089d001648eSDavid Howells static int afs_deliver_fs_store_data(struct afs_call *call) 109031143d5dSDavid Howells { 109131143d5dSDavid Howells const __be32 *bp; 1092372ee163SDavid Howells int ret; 109331143d5dSDavid Howells 1094d001648eSDavid Howells _enter(""); 109531143d5dSDavid Howells 1096d001648eSDavid Howells ret = afs_transfer_reply(call); 1097372ee163SDavid Howells if (ret < 0) 1098372ee163SDavid Howells return ret; 109931143d5dSDavid Howells 110031143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 110131143d5dSDavid Howells bp = call->buffer; 1102a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1103160cb957SDavid Howells if (ret < 0) 1104160cb957SDavid Howells return ret; 1105ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 110631143d5dSDavid Howells 110731143d5dSDavid Howells _leave(" = 0 [done]"); 110831143d5dSDavid Howells return 0; 110931143d5dSDavid Howells } 111031143d5dSDavid Howells 111131143d5dSDavid Howells /* 111231143d5dSDavid Howells * FS.StoreData operation type 111331143d5dSDavid Howells */ 111431143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData = { 111531143d5dSDavid Howells .name = "FS.StoreData", 1116025db80cSDavid Howells .op = afs_FS_StoreData, 111731143d5dSDavid Howells .deliver = afs_deliver_fs_store_data, 111831143d5dSDavid Howells .destructor = afs_flat_call_destructor, 111931143d5dSDavid Howells }; 112031143d5dSDavid Howells 1121b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64 = { 1122b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1123025db80cSDavid Howells .op = afs_FS_StoreData64, 1124b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_data, 1125b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1126b9b1f8d5SDavid Howells }; 1127b9b1f8d5SDavid Howells 1128b9b1f8d5SDavid Howells /* 1129b9b1f8d5SDavid Howells * store a set of pages to a very large file 1130b9b1f8d5SDavid Howells */ 11318b2a464cSDavid Howells static int afs_fs_store_data64(struct afs_fs_cursor *fc, 11324343d008SDavid Howells struct address_space *mapping, 1133b9b1f8d5SDavid Howells pgoff_t first, pgoff_t last, 1134b9b1f8d5SDavid Howells unsigned offset, unsigned to, 1135a58823acSDavid Howells loff_t size, loff_t pos, loff_t i_size, 1136a58823acSDavid Howells struct afs_status_cb *scb) 1137b9b1f8d5SDavid Howells { 11384343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 1139b9b1f8d5SDavid Howells struct afs_call *call; 1140f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1141b9b1f8d5SDavid Howells __be32 *bp; 1142b9b1f8d5SDavid Howells 11433b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 11444343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1145b9b1f8d5SDavid Howells 1146f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64, 1147b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1148b9b1f8d5SDavid Howells (21 + 6) * 4); 1149b9b1f8d5SDavid Howells if (!call) 1150b9b1f8d5SDavid Howells return -ENOMEM; 1151b9b1f8d5SDavid Howells 11524343d008SDavid Howells call->key = fc->key; 11534343d008SDavid Howells call->mapping = mapping; 1154b9b1f8d5SDavid Howells call->first = first; 1155b9b1f8d5SDavid Howells call->last = last; 1156b9b1f8d5SDavid Howells call->first_offset = offset; 1157b9b1f8d5SDavid Howells call->last_to = to; 1158b9b1f8d5SDavid Howells call->send_pages = true; 1159a58823acSDavid Howells call->out_scb = scb; 1160b9b1f8d5SDavid Howells 1161b9b1f8d5SDavid Howells /* marshall the parameters */ 1162b9b1f8d5SDavid Howells bp = call->request; 1163b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1164b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1165b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1166b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1167b9b1f8d5SDavid Howells 1168ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1169ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 1170b9b1f8d5SDavid Howells *bp++ = 0; /* owner */ 1171b9b1f8d5SDavid Howells *bp++ = 0; /* group */ 1172b9b1f8d5SDavid Howells *bp++ = 0; /* unix mode */ 1173b9b1f8d5SDavid Howells *bp++ = 0; /* segment size */ 1174b9b1f8d5SDavid Howells 1175b9b1f8d5SDavid Howells *bp++ = htonl(pos >> 32); 1176b9b1f8d5SDavid Howells *bp++ = htonl((u32) pos); 1177b9b1f8d5SDavid Howells *bp++ = htonl(size >> 32); 1178b9b1f8d5SDavid Howells *bp++ = htonl((u32) size); 1179b9b1f8d5SDavid Howells *bp++ = htonl(i_size >> 32); 1180b9b1f8d5SDavid Howells *bp++ = htonl((u32) i_size); 1181b9b1f8d5SDavid Howells 1182025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 118320b8391fSDavid Howells afs_set_fc_call(call, fc); 11840b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 11850b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1186b9b1f8d5SDavid Howells } 1187b9b1f8d5SDavid Howells 118831143d5dSDavid Howells /* 118931143d5dSDavid Howells * store a set of pages 119031143d5dSDavid Howells */ 11914343d008SDavid Howells int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, 119231143d5dSDavid Howells pgoff_t first, pgoff_t last, 1193a58823acSDavid Howells unsigned offset, unsigned to, 1194a58823acSDavid Howells struct afs_status_cb *scb) 119531143d5dSDavid Howells { 11964343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 119731143d5dSDavid Howells struct afs_call *call; 1198f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 119931143d5dSDavid Howells loff_t size, pos, i_size; 120031143d5dSDavid Howells __be32 *bp; 120131143d5dSDavid Howells 120230062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1203a58823acSDavid Howells return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb); 120430062bd1SDavid Howells 12053b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 12064343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 120731143d5dSDavid Howells 1208146a1192SDavid Howells size = (loff_t)to - (loff_t)offset; 120931143d5dSDavid Howells if (first != last) 121031143d5dSDavid Howells size += (loff_t)(last - first) << PAGE_SHIFT; 121131143d5dSDavid Howells pos = (loff_t)first << PAGE_SHIFT; 121231143d5dSDavid Howells pos += offset; 121331143d5dSDavid Howells 121431143d5dSDavid Howells i_size = i_size_read(&vnode->vfs_inode); 121531143d5dSDavid Howells if (pos + size > i_size) 121631143d5dSDavid Howells i_size = size + pos; 121731143d5dSDavid Howells 121831143d5dSDavid Howells _debug("size %llx, at %llx, i_size %llx", 121931143d5dSDavid Howells (unsigned long long) size, (unsigned long long) pos, 122031143d5dSDavid Howells (unsigned long long) i_size); 122131143d5dSDavid Howells 1222b9b1f8d5SDavid Howells if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32) 12234343d008SDavid Howells return afs_fs_store_data64(fc, mapping, first, last, offset, to, 1224a58823acSDavid Howells size, pos, i_size, scb); 122531143d5dSDavid Howells 1226f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData, 122731143d5dSDavid Howells (4 + 6 + 3) * 4, 122831143d5dSDavid Howells (21 + 6) * 4); 122931143d5dSDavid Howells if (!call) 123031143d5dSDavid Howells return -ENOMEM; 123131143d5dSDavid Howells 12324343d008SDavid Howells call->key = fc->key; 12334343d008SDavid Howells call->mapping = mapping; 123431143d5dSDavid Howells call->first = first; 123531143d5dSDavid Howells call->last = last; 123631143d5dSDavid Howells call->first_offset = offset; 123731143d5dSDavid Howells call->last_to = to; 123831143d5dSDavid Howells call->send_pages = true; 1239a58823acSDavid Howells call->out_scb = scb; 124031143d5dSDavid Howells 124131143d5dSDavid Howells /* marshall the parameters */ 124231143d5dSDavid Howells bp = call->request; 124331143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 124431143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 124531143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 124631143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 124731143d5dSDavid Howells 1248ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1249ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 125031143d5dSDavid Howells *bp++ = 0; /* owner */ 125131143d5dSDavid Howells *bp++ = 0; /* group */ 125231143d5dSDavid Howells *bp++ = 0; /* unix mode */ 125331143d5dSDavid Howells *bp++ = 0; /* segment size */ 125431143d5dSDavid Howells 125531143d5dSDavid Howells *bp++ = htonl(pos); 125631143d5dSDavid Howells *bp++ = htonl(size); 125731143d5dSDavid Howells *bp++ = htonl(i_size); 125831143d5dSDavid Howells 1259d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1260025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 126120b8391fSDavid Howells afs_set_fc_call(call, fc); 12620b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 12630b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 126431143d5dSDavid Howells } 126531143d5dSDavid Howells 126631143d5dSDavid Howells /* 126731143d5dSDavid Howells * deliver reply data to an FS.StoreStatus 126831143d5dSDavid Howells */ 1269d001648eSDavid Howells static int afs_deliver_fs_store_status(struct afs_call *call) 127031143d5dSDavid Howells { 127131143d5dSDavid Howells const __be32 *bp; 1272372ee163SDavid Howells int ret; 127331143d5dSDavid Howells 1274d001648eSDavid Howells _enter(""); 127531143d5dSDavid Howells 1276d001648eSDavid Howells ret = afs_transfer_reply(call); 1277372ee163SDavid Howells if (ret < 0) 1278372ee163SDavid Howells return ret; 127931143d5dSDavid Howells 128031143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 128131143d5dSDavid Howells bp = call->buffer; 1282a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1283160cb957SDavid Howells if (ret < 0) 1284160cb957SDavid Howells return ret; 1285ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 128631143d5dSDavid Howells 128731143d5dSDavid Howells _leave(" = 0 [done]"); 128831143d5dSDavid Howells return 0; 128931143d5dSDavid Howells } 129031143d5dSDavid Howells 129131143d5dSDavid Howells /* 129231143d5dSDavid Howells * FS.StoreStatus operation type 129331143d5dSDavid Howells */ 129431143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreStatus = { 129531143d5dSDavid Howells .name = "FS.StoreStatus", 1296025db80cSDavid Howells .op = afs_FS_StoreStatus, 129731143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 129831143d5dSDavid Howells .destructor = afs_flat_call_destructor, 129931143d5dSDavid Howells }; 130031143d5dSDavid Howells 130131143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData_as_Status = { 130231143d5dSDavid Howells .name = "FS.StoreData", 1303025db80cSDavid Howells .op = afs_FS_StoreData, 130431143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 130531143d5dSDavid Howells .destructor = afs_flat_call_destructor, 130631143d5dSDavid Howells }; 130731143d5dSDavid Howells 1308b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64_as_Status = { 1309b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1310025db80cSDavid Howells .op = afs_FS_StoreData64, 1311b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_status, 1312b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1313b9b1f8d5SDavid Howells }; 1314b9b1f8d5SDavid Howells 1315b9b1f8d5SDavid Howells /* 1316b9b1f8d5SDavid Howells * set the attributes on a very large file, using FS.StoreData rather than 1317b9b1f8d5SDavid Howells * FS.StoreStatus so as to alter the file size also 1318b9b1f8d5SDavid Howells */ 1319a58823acSDavid Howells static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr, 1320a58823acSDavid Howells struct afs_status_cb *scb) 1321b9b1f8d5SDavid Howells { 1322d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1323b9b1f8d5SDavid Howells struct afs_call *call; 1324f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1325b9b1f8d5SDavid Howells __be32 *bp; 1326b9b1f8d5SDavid Howells 13273b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1328d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1329b9b1f8d5SDavid Howells 1330b9b1f8d5SDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1331b9b1f8d5SDavid Howells 1332f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status, 1333b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1334b9b1f8d5SDavid Howells (21 + 6) * 4); 1335b9b1f8d5SDavid Howells if (!call) 1336b9b1f8d5SDavid Howells return -ENOMEM; 1337b9b1f8d5SDavid Howells 1338d2ddc776SDavid Howells call->key = fc->key; 1339a58823acSDavid Howells call->out_scb = scb; 1340b9b1f8d5SDavid Howells 1341b9b1f8d5SDavid Howells /* marshall the parameters */ 1342b9b1f8d5SDavid Howells bp = call->request; 1343b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1344b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1345b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1346b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1347b9b1f8d5SDavid Howells 1348b9b1f8d5SDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 1349b9b1f8d5SDavid Howells 13508c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* position of start of write */ 13518c7ae38dSDavid Howells *bp++ = htonl((u32) attr->ia_size); 1352b9b1f8d5SDavid Howells *bp++ = 0; /* size of write */ 1353b9b1f8d5SDavid Howells *bp++ = 0; 1354b9b1f8d5SDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* new file length */ 1355b9b1f8d5SDavid Howells *bp++ = htonl((u32) attr->ia_size); 1356b9b1f8d5SDavid Howells 1357d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1358025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 135920b8391fSDavid Howells afs_set_fc_call(call, fc); 13600b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 13610b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1362b9b1f8d5SDavid Howells } 1363b9b1f8d5SDavid Howells 136431143d5dSDavid Howells /* 136531143d5dSDavid Howells * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus 136631143d5dSDavid Howells * so as to alter the file size also 136731143d5dSDavid Howells */ 1368a58823acSDavid Howells static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr, 1369a58823acSDavid Howells struct afs_status_cb *scb) 137031143d5dSDavid Howells { 1371d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 137231143d5dSDavid Howells struct afs_call *call; 1373f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 137431143d5dSDavid Howells __be32 *bp; 137531143d5dSDavid Howells 13763b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1377d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 137831143d5dSDavid Howells 137931143d5dSDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1380b9b1f8d5SDavid Howells if (attr->ia_size >> 32) 1381a58823acSDavid Howells return afs_fs_setattr_size64(fc, attr, scb); 138231143d5dSDavid Howells 1383f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status, 138431143d5dSDavid Howells (4 + 6 + 3) * 4, 138531143d5dSDavid Howells (21 + 6) * 4); 138631143d5dSDavid Howells if (!call) 138731143d5dSDavid Howells return -ENOMEM; 138831143d5dSDavid Howells 1389d2ddc776SDavid Howells call->key = fc->key; 1390a58823acSDavid Howells call->out_scb = scb; 139131143d5dSDavid Howells 139231143d5dSDavid Howells /* marshall the parameters */ 139331143d5dSDavid Howells bp = call->request; 139431143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 139531143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 139631143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 139731143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 139831143d5dSDavid Howells 139931143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 140031143d5dSDavid Howells 14018c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size); /* position of start of write */ 140231143d5dSDavid Howells *bp++ = 0; /* size of write */ 140331143d5dSDavid Howells *bp++ = htonl(attr->ia_size); /* new file length */ 140431143d5dSDavid Howells 1405d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1406025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 140720b8391fSDavid Howells afs_set_fc_call(call, fc); 14080b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14090b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 141031143d5dSDavid Howells } 141131143d5dSDavid Howells 141231143d5dSDavid Howells /* 141331143d5dSDavid Howells * set the attributes on a file, using FS.StoreData if there's a change in file 141431143d5dSDavid Howells * size, and FS.StoreStatus otherwise 141531143d5dSDavid Howells */ 1416a58823acSDavid Howells int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr, 1417a58823acSDavid Howells struct afs_status_cb *scb) 141831143d5dSDavid Howells { 1419d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 142031143d5dSDavid Howells struct afs_call *call; 1421f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 142231143d5dSDavid Howells __be32 *bp; 142331143d5dSDavid Howells 142430062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1425a58823acSDavid Howells return yfs_fs_setattr(fc, attr, scb); 142630062bd1SDavid Howells 142731143d5dSDavid Howells if (attr->ia_valid & ATTR_SIZE) 1428a58823acSDavid Howells return afs_fs_setattr_size(fc, attr, scb); 142931143d5dSDavid Howells 14303b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1431d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 143231143d5dSDavid Howells 1433f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus, 143431143d5dSDavid Howells (4 + 6) * 4, 143531143d5dSDavid Howells (21 + 6) * 4); 143631143d5dSDavid Howells if (!call) 143731143d5dSDavid Howells return -ENOMEM; 143831143d5dSDavid Howells 1439d2ddc776SDavid Howells call->key = fc->key; 1440a58823acSDavid Howells call->out_scb = scb; 144131143d5dSDavid Howells 144231143d5dSDavid Howells /* marshall the parameters */ 144331143d5dSDavid Howells bp = call->request; 144431143d5dSDavid Howells *bp++ = htonl(FSSTORESTATUS); 144531143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 144631143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 144731143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 144831143d5dSDavid Howells 144931143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 145031143d5dSDavid Howells 1451d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1452025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 145320b8391fSDavid Howells afs_set_fc_call(call, fc); 14540b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14550b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 145631143d5dSDavid Howells } 145745222b9eSDavid Howells 145845222b9eSDavid Howells /* 145945222b9eSDavid Howells * deliver reply data to an FS.GetVolumeStatus 146045222b9eSDavid Howells */ 1461d001648eSDavid Howells static int afs_deliver_fs_get_volume_status(struct afs_call *call) 146245222b9eSDavid Howells { 146345222b9eSDavid Howells const __be32 *bp; 146445222b9eSDavid Howells char *p; 146512bdcf33SDavid Howells u32 size; 146645222b9eSDavid Howells int ret; 146745222b9eSDavid Howells 1468d001648eSDavid Howells _enter("{%u}", call->unmarshall); 146945222b9eSDavid Howells 147045222b9eSDavid Howells switch (call->unmarshall) { 147145222b9eSDavid Howells case 0: 147245222b9eSDavid Howells call->unmarshall++; 147312bdcf33SDavid Howells afs_extract_to_buf(call, 12 * 4); 147445222b9eSDavid Howells 1475e690c9e3SGustavo A. R. Silva /* Fall through - and extract the returned status record */ 147645222b9eSDavid Howells case 1: 147745222b9eSDavid Howells _debug("extract status"); 147812bdcf33SDavid Howells ret = afs_extract_data(call, true); 1479372ee163SDavid Howells if (ret < 0) 1480372ee163SDavid Howells return ret; 148145222b9eSDavid Howells 148245222b9eSDavid Howells bp = call->buffer; 1483ffba718eSDavid Howells xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus); 148445222b9eSDavid Howells call->unmarshall++; 148512bdcf33SDavid Howells afs_extract_to_tmp(call); 148645222b9eSDavid Howells 1487e690c9e3SGustavo A. R. Silva /* Fall through - and extract the volume name length */ 148845222b9eSDavid Howells case 2: 148912bdcf33SDavid Howells ret = afs_extract_data(call, true); 1490372ee163SDavid Howells if (ret < 0) 1491372ee163SDavid Howells return ret; 149245222b9eSDavid Howells 149345222b9eSDavid Howells call->count = ntohl(call->tmp); 149445222b9eSDavid Howells _debug("volname length: %u", call->count); 149545222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1496160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1497160cb957SDavid Howells afs_eproto_volname_len); 149812bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1499ffba718eSDavid Howells afs_extract_to_buf(call, size); 150045222b9eSDavid Howells call->unmarshall++; 150145222b9eSDavid Howells 1502e690c9e3SGustavo A. R. Silva /* Fall through - and extract the volume name */ 150345222b9eSDavid Howells case 3: 150445222b9eSDavid Howells _debug("extract volname"); 150512bdcf33SDavid Howells ret = afs_extract_data(call, true); 1506372ee163SDavid Howells if (ret < 0) 1507372ee163SDavid Howells return ret; 150845222b9eSDavid Howells 1509ffba718eSDavid Howells p = call->buffer; 151045222b9eSDavid Howells p[call->count] = 0; 151145222b9eSDavid Howells _debug("volname '%s'", p); 151212bdcf33SDavid Howells afs_extract_to_tmp(call); 151345222b9eSDavid Howells call->unmarshall++; 151445222b9eSDavid Howells 1515e690c9e3SGustavo A. R. Silva /* Fall through - and extract the offline message length */ 151612bdcf33SDavid Howells case 4: 151712bdcf33SDavid Howells ret = afs_extract_data(call, true); 1518372ee163SDavid Howells if (ret < 0) 1519372ee163SDavid Howells return ret; 152045222b9eSDavid Howells 152145222b9eSDavid Howells call->count = ntohl(call->tmp); 152245222b9eSDavid Howells _debug("offline msg length: %u", call->count); 152345222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1524160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1525160cb957SDavid Howells afs_eproto_offline_msg_len); 152612bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1527ffba718eSDavid Howells afs_extract_to_buf(call, size); 152845222b9eSDavid Howells call->unmarshall++; 152945222b9eSDavid Howells 1530e690c9e3SGustavo A. R. Silva /* Fall through - and extract the offline message */ 153112bdcf33SDavid Howells case 5: 153245222b9eSDavid Howells _debug("extract offline"); 153312bdcf33SDavid Howells ret = afs_extract_data(call, true); 1534372ee163SDavid Howells if (ret < 0) 1535372ee163SDavid Howells return ret; 153645222b9eSDavid Howells 1537ffba718eSDavid Howells p = call->buffer; 153845222b9eSDavid Howells p[call->count] = 0; 153945222b9eSDavid Howells _debug("offline '%s'", p); 154045222b9eSDavid Howells 154112bdcf33SDavid Howells afs_extract_to_tmp(call); 154245222b9eSDavid Howells call->unmarshall++; 154345222b9eSDavid Howells 1544e690c9e3SGustavo A. R. Silva /* Fall through - and extract the message of the day length */ 154512bdcf33SDavid Howells case 6: 154612bdcf33SDavid Howells ret = afs_extract_data(call, true); 1547372ee163SDavid Howells if (ret < 0) 1548372ee163SDavid Howells return ret; 154945222b9eSDavid Howells 155045222b9eSDavid Howells call->count = ntohl(call->tmp); 155145222b9eSDavid Howells _debug("motd length: %u", call->count); 155245222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1553160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1554160cb957SDavid Howells afs_eproto_motd_len); 155512bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1556ffba718eSDavid Howells afs_extract_to_buf(call, size); 155745222b9eSDavid Howells call->unmarshall++; 155845222b9eSDavid Howells 1559e690c9e3SGustavo A. R. Silva /* Fall through - and extract the message of the day */ 156012bdcf33SDavid Howells case 7: 156145222b9eSDavid Howells _debug("extract motd"); 156212bdcf33SDavid Howells ret = afs_extract_data(call, false); 1563372ee163SDavid Howells if (ret < 0) 1564372ee163SDavid Howells return ret; 156545222b9eSDavid Howells 1566ffba718eSDavid Howells p = call->buffer; 156745222b9eSDavid Howells p[call->count] = 0; 156845222b9eSDavid Howells _debug("motd '%s'", p); 156945222b9eSDavid Howells 157045222b9eSDavid Howells call->unmarshall++; 157145222b9eSDavid Howells 157212bdcf33SDavid Howells case 8: 157345222b9eSDavid Howells break; 157445222b9eSDavid Howells } 157545222b9eSDavid Howells 157645222b9eSDavid Howells _leave(" = 0 [done]"); 157745222b9eSDavid Howells return 0; 157845222b9eSDavid Howells } 157945222b9eSDavid Howells 158045222b9eSDavid Howells /* 158145222b9eSDavid Howells * FS.GetVolumeStatus operation type 158245222b9eSDavid Howells */ 158345222b9eSDavid Howells static const struct afs_call_type afs_RXFSGetVolumeStatus = { 158445222b9eSDavid Howells .name = "FS.GetVolumeStatus", 1585025db80cSDavid Howells .op = afs_FS_GetVolumeStatus, 158645222b9eSDavid Howells .deliver = afs_deliver_fs_get_volume_status, 1587ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 158845222b9eSDavid Howells }; 158945222b9eSDavid Howells 159045222b9eSDavid Howells /* 159145222b9eSDavid Howells * fetch the status of a volume 159245222b9eSDavid Howells */ 15938b2a464cSDavid Howells int afs_fs_get_volume_status(struct afs_fs_cursor *fc, 1594d2ddc776SDavid Howells struct afs_volume_status *vs) 159545222b9eSDavid Howells { 1596d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 159745222b9eSDavid Howells struct afs_call *call; 1598f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 159945222b9eSDavid Howells __be32 *bp; 160045222b9eSDavid Howells 160130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 160230062bd1SDavid Howells return yfs_fs_get_volume_status(fc, vs); 160330062bd1SDavid Howells 160445222b9eSDavid Howells _enter(""); 160545222b9eSDavid Howells 1606ffba718eSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 1607ffba718eSDavid Howells max(12 * 4, AFSOPAQUEMAX + 1)); 1608ffba718eSDavid Howells if (!call) 160945222b9eSDavid Howells return -ENOMEM; 161045222b9eSDavid Howells 1611d2ddc776SDavid Howells call->key = fc->key; 1612ffba718eSDavid Howells call->out_volstatus = vs; 161345222b9eSDavid Howells 161445222b9eSDavid Howells /* marshall the parameters */ 161545222b9eSDavid Howells bp = call->request; 161645222b9eSDavid Howells bp[0] = htonl(FSGETVOLUMESTATUS); 161745222b9eSDavid Howells bp[1] = htonl(vnode->fid.vid); 161845222b9eSDavid Howells 1619d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1620025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 162120b8391fSDavid Howells afs_set_fc_call(call, fc); 16220b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 16230b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 162445222b9eSDavid Howells } 1625e8d6c554SDavid Howells 1626e8d6c554SDavid Howells /* 1627e8d6c554SDavid Howells * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock 1628e8d6c554SDavid Howells */ 1629d001648eSDavid Howells static int afs_deliver_fs_xxxx_lock(struct afs_call *call) 1630e8d6c554SDavid Howells { 1631e8d6c554SDavid Howells const __be32 *bp; 1632372ee163SDavid Howells int ret; 1633e8d6c554SDavid Howells 1634d001648eSDavid Howells _enter("{%u}", call->unmarshall); 1635e8d6c554SDavid Howells 1636d001648eSDavid Howells ret = afs_transfer_reply(call); 1637372ee163SDavid Howells if (ret < 0) 1638372ee163SDavid Howells return ret; 1639e8d6c554SDavid Howells 1640e8d6c554SDavid Howells /* unmarshall the reply once we've received all of it */ 1641e8d6c554SDavid Howells bp = call->buffer; 1642ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 1643e8d6c554SDavid Howells 1644e8d6c554SDavid Howells _leave(" = 0 [done]"); 1645e8d6c554SDavid Howells return 0; 1646e8d6c554SDavid Howells } 1647e8d6c554SDavid Howells 1648e8d6c554SDavid Howells /* 1649e8d6c554SDavid Howells * FS.SetLock operation type 1650e8d6c554SDavid Howells */ 1651e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSSetLock = { 1652e8d6c554SDavid Howells .name = "FS.SetLock", 1653025db80cSDavid Howells .op = afs_FS_SetLock, 1654e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1655a690f60aSDavid Howells .done = afs_lock_op_done, 1656e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1657e8d6c554SDavid Howells }; 1658e8d6c554SDavid Howells 1659e8d6c554SDavid Howells /* 1660e8d6c554SDavid Howells * FS.ExtendLock operation type 1661e8d6c554SDavid Howells */ 1662e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSExtendLock = { 1663e8d6c554SDavid Howells .name = "FS.ExtendLock", 1664025db80cSDavid Howells .op = afs_FS_ExtendLock, 1665e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1666a690f60aSDavid Howells .done = afs_lock_op_done, 1667e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1668e8d6c554SDavid Howells }; 1669e8d6c554SDavid Howells 1670e8d6c554SDavid Howells /* 1671e8d6c554SDavid Howells * FS.ReleaseLock operation type 1672e8d6c554SDavid Howells */ 1673e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSReleaseLock = { 1674e8d6c554SDavid Howells .name = "FS.ReleaseLock", 1675025db80cSDavid Howells .op = afs_FS_ReleaseLock, 1676e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1677e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1678e8d6c554SDavid Howells }; 1679e8d6c554SDavid Howells 1680e8d6c554SDavid Howells /* 1681d2ddc776SDavid Howells * Set a lock on a file 1682e8d6c554SDavid Howells */ 1683a58823acSDavid Howells int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type, 1684a58823acSDavid Howells struct afs_status_cb *scb) 1685e8d6c554SDavid Howells { 1686d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1687e8d6c554SDavid Howells struct afs_call *call; 1688f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1689e8d6c554SDavid Howells __be32 *bp; 1690e8d6c554SDavid Howells 169130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1692a58823acSDavid Howells return yfs_fs_set_lock(fc, type, scb); 169330062bd1SDavid Howells 1694e8d6c554SDavid Howells _enter(""); 1695e8d6c554SDavid Howells 1696f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4); 1697e8d6c554SDavid Howells if (!call) 1698e8d6c554SDavid Howells return -ENOMEM; 1699e8d6c554SDavid Howells 1700d2ddc776SDavid Howells call->key = fc->key; 1701a58823acSDavid Howells call->lvnode = vnode; 1702a58823acSDavid Howells call->out_scb = scb; 1703e8d6c554SDavid Howells 1704e8d6c554SDavid Howells /* marshall the parameters */ 1705e8d6c554SDavid Howells bp = call->request; 1706e8d6c554SDavid Howells *bp++ = htonl(FSSETLOCK); 1707e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1708e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1709e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1710e8d6c554SDavid Howells *bp++ = htonl(type); 1711e8d6c554SDavid Howells 1712d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 17136c6c1d63SDavid Howells trace_afs_make_fs_calli(call, &vnode->fid, type); 171420b8391fSDavid Howells afs_set_fc_call(call, fc); 17150b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17160b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1717e8d6c554SDavid Howells } 1718e8d6c554SDavid Howells 1719e8d6c554SDavid Howells /* 1720e8d6c554SDavid Howells * extend a lock on a file 1721e8d6c554SDavid Howells */ 1722a58823acSDavid Howells int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1723e8d6c554SDavid Howells { 1724d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1725e8d6c554SDavid Howells struct afs_call *call; 1726f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1727e8d6c554SDavid Howells __be32 *bp; 1728e8d6c554SDavid Howells 172930062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1730a58823acSDavid Howells return yfs_fs_extend_lock(fc, scb); 173130062bd1SDavid Howells 1732e8d6c554SDavid Howells _enter(""); 1733e8d6c554SDavid Howells 1734f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4); 1735e8d6c554SDavid Howells if (!call) 1736e8d6c554SDavid Howells return -ENOMEM; 1737e8d6c554SDavid Howells 1738d2ddc776SDavid Howells call->key = fc->key; 1739a58823acSDavid Howells call->lvnode = vnode; 1740a58823acSDavid Howells call->out_scb = scb; 1741e8d6c554SDavid Howells 1742e8d6c554SDavid Howells /* marshall the parameters */ 1743e8d6c554SDavid Howells bp = call->request; 1744e8d6c554SDavid Howells *bp++ = htonl(FSEXTENDLOCK); 1745e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1746e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1747e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1748e8d6c554SDavid Howells 1749d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1750025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 175120b8391fSDavid Howells afs_set_fc_call(call, fc); 17520b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17530b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1754e8d6c554SDavid Howells } 1755e8d6c554SDavid Howells 1756e8d6c554SDavid Howells /* 1757e8d6c554SDavid Howells * release a lock on a file 1758e8d6c554SDavid Howells */ 1759a58823acSDavid Howells int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1760e8d6c554SDavid Howells { 1761d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1762e8d6c554SDavid Howells struct afs_call *call; 1763f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1764e8d6c554SDavid Howells __be32 *bp; 1765e8d6c554SDavid Howells 176630062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1767a58823acSDavid Howells return yfs_fs_release_lock(fc, scb); 176830062bd1SDavid Howells 1769e8d6c554SDavid Howells _enter(""); 1770e8d6c554SDavid Howells 1771f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4); 1772e8d6c554SDavid Howells if (!call) 1773e8d6c554SDavid Howells return -ENOMEM; 1774e8d6c554SDavid Howells 1775d2ddc776SDavid Howells call->key = fc->key; 1776a58823acSDavid Howells call->lvnode = vnode; 1777a58823acSDavid Howells call->out_scb = scb; 1778e8d6c554SDavid Howells 1779e8d6c554SDavid Howells /* marshall the parameters */ 1780e8d6c554SDavid Howells bp = call->request; 1781e8d6c554SDavid Howells *bp++ = htonl(FSRELEASELOCK); 1782e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1783e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1784e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1785e8d6c554SDavid Howells 1786d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1787025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 178820b8391fSDavid Howells afs_set_fc_call(call, fc); 17890b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17900b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1791c435ee34SDavid Howells } 1792c435ee34SDavid Howells 1793c435ee34SDavid Howells /* 1794c435ee34SDavid Howells * Deliver reply data to an FS.GiveUpAllCallBacks operation. 1795c435ee34SDavid Howells */ 1796c435ee34SDavid Howells static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call) 1797c435ee34SDavid Howells { 1798c435ee34SDavid Howells return afs_transfer_reply(call); 1799c435ee34SDavid Howells } 1800c435ee34SDavid Howells 1801c435ee34SDavid Howells /* 1802c435ee34SDavid Howells * FS.GiveUpAllCallBacks operation type 1803c435ee34SDavid Howells */ 1804c435ee34SDavid Howells static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = { 1805c435ee34SDavid Howells .name = "FS.GiveUpAllCallBacks", 1806025db80cSDavid Howells .op = afs_FS_GiveUpAllCallBacks, 1807c435ee34SDavid Howells .deliver = afs_deliver_fs_give_up_all_callbacks, 1808c435ee34SDavid Howells .destructor = afs_flat_call_destructor, 1809c435ee34SDavid Howells }; 1810c435ee34SDavid Howells 1811c435ee34SDavid Howells /* 1812c435ee34SDavid Howells * Flush all the callbacks we have on a server. 1813c435ee34SDavid Howells */ 1814d2ddc776SDavid Howells int afs_fs_give_up_all_callbacks(struct afs_net *net, 1815d2ddc776SDavid Howells struct afs_server *server, 18168b2a464cSDavid Howells struct afs_addr_cursor *ac, 1817d2ddc776SDavid Howells struct key *key) 1818c435ee34SDavid Howells { 1819c435ee34SDavid Howells struct afs_call *call; 1820c435ee34SDavid Howells __be32 *bp; 1821c435ee34SDavid Howells 1822c435ee34SDavid Howells _enter(""); 1823c435ee34SDavid Howells 1824d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0); 1825c435ee34SDavid Howells if (!call) 1826c435ee34SDavid Howells return -ENOMEM; 1827c435ee34SDavid Howells 1828c435ee34SDavid Howells call->key = key; 1829c435ee34SDavid Howells 1830c435ee34SDavid Howells /* marshall the parameters */ 1831c435ee34SDavid Howells bp = call->request; 1832c435ee34SDavid Howells *bp++ = htonl(FSGIVEUPALLCALLBACKS); 1833c435ee34SDavid Howells 1834c435ee34SDavid Howells /* Can't take a ref on server */ 18350b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 18360b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, ac); 1837d2ddc776SDavid Howells } 1838d2ddc776SDavid Howells 1839d2ddc776SDavid Howells /* 1840d2ddc776SDavid Howells * Deliver reply data to an FS.GetCapabilities operation. 1841d2ddc776SDavid Howells */ 1842d2ddc776SDavid Howells static int afs_deliver_fs_get_capabilities(struct afs_call *call) 1843d2ddc776SDavid Howells { 1844d2ddc776SDavid Howells u32 count; 1845d2ddc776SDavid Howells int ret; 1846d2ddc776SDavid Howells 184712bdcf33SDavid Howells _enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter)); 1848d2ddc776SDavid Howells 1849d2ddc776SDavid Howells switch (call->unmarshall) { 1850d2ddc776SDavid Howells case 0: 185112bdcf33SDavid Howells afs_extract_to_tmp(call); 1852d2ddc776SDavid Howells call->unmarshall++; 1853d2ddc776SDavid Howells 1854e690c9e3SGustavo A. R. Silva /* Fall through - and extract the capabilities word count */ 1855d2ddc776SDavid Howells case 1: 185612bdcf33SDavid Howells ret = afs_extract_data(call, true); 1857d2ddc776SDavid Howells if (ret < 0) 1858d2ddc776SDavid Howells return ret; 1859d2ddc776SDavid Howells 1860d2ddc776SDavid Howells count = ntohl(call->tmp); 1861d2ddc776SDavid Howells 1862d2ddc776SDavid Howells call->count = count; 1863d2ddc776SDavid Howells call->count2 = count; 186412bdcf33SDavid Howells iov_iter_discard(&call->iter, READ, count * sizeof(__be32)); 1865d2ddc776SDavid Howells call->unmarshall++; 1866d2ddc776SDavid Howells 1867e690c9e3SGustavo A. R. Silva /* Fall through - and extract capabilities words */ 1868d2ddc776SDavid Howells case 2: 186912bdcf33SDavid Howells ret = afs_extract_data(call, false); 1870d2ddc776SDavid Howells if (ret < 0) 1871d2ddc776SDavid Howells return ret; 1872d2ddc776SDavid Howells 1873d2ddc776SDavid Howells /* TODO: Examine capabilities */ 1874d2ddc776SDavid Howells 1875d2ddc776SDavid Howells call->unmarshall++; 1876d2ddc776SDavid Howells break; 1877d2ddc776SDavid Howells } 1878d2ddc776SDavid Howells 1879d2ddc776SDavid Howells _leave(" = 0 [done]"); 1880d2ddc776SDavid Howells return 0; 1881d2ddc776SDavid Howells } 1882d2ddc776SDavid Howells 1883d2ddc776SDavid Howells /* 1884d2ddc776SDavid Howells * FS.GetCapabilities operation type 1885d2ddc776SDavid Howells */ 1886d2ddc776SDavid Howells static const struct afs_call_type afs_RXFSGetCapabilities = { 1887d2ddc776SDavid Howells .name = "FS.GetCapabilities", 1888025db80cSDavid Howells .op = afs_FS_GetCapabilities, 1889d2ddc776SDavid Howells .deliver = afs_deliver_fs_get_capabilities, 18903bf0fb6fSDavid Howells .done = afs_fileserver_probe_result, 1891ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 1892d2ddc776SDavid Howells }; 1893d2ddc776SDavid Howells 1894d2ddc776SDavid Howells /* 1895d2ddc776SDavid Howells * Probe a fileserver for the capabilities that it supports. This can 1896d2ddc776SDavid Howells * return up to 196 words. 1897d2ddc776SDavid Howells */ 18980b9bf381SDavid Howells struct afs_call *afs_fs_get_capabilities(struct afs_net *net, 1899d2ddc776SDavid Howells struct afs_server *server, 1900d2ddc776SDavid Howells struct afs_addr_cursor *ac, 19013bf0fb6fSDavid Howells struct key *key, 19020b9bf381SDavid Howells unsigned int server_index) 1903d2ddc776SDavid Howells { 1904d2ddc776SDavid Howells struct afs_call *call; 1905d2ddc776SDavid Howells __be32 *bp; 1906d2ddc776SDavid Howells 1907d2ddc776SDavid Howells _enter(""); 1908d2ddc776SDavid Howells 1909d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4); 1910d2ddc776SDavid Howells if (!call) 19110b9bf381SDavid Howells return ERR_PTR(-ENOMEM); 1912d2ddc776SDavid Howells 1913d2ddc776SDavid Howells call->key = key; 1914ffba718eSDavid Howells call->server = afs_get_server(server); 1915ffba718eSDavid Howells call->server_index = server_index; 191630062bd1SDavid Howells call->upgrade = true; 19170b9bf381SDavid Howells call->async = true; 191894f699c9SDavid Howells call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; 1919d2ddc776SDavid Howells 1920d2ddc776SDavid Howells /* marshall the parameters */ 1921d2ddc776SDavid Howells bp = call->request; 1922d2ddc776SDavid Howells *bp++ = htonl(FSGETCAPABILITIES); 1923d2ddc776SDavid Howells 1924d2ddc776SDavid Howells /* Can't take a ref on server */ 1925025db80cSDavid Howells trace_afs_make_fs_call(call, NULL); 19260b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 19270b9bf381SDavid Howells return call; 1928e8d6c554SDavid Howells } 19295cf9dd55SDavid Howells 19305cf9dd55SDavid Howells /* 19315cf9dd55SDavid Howells * Deliver reply data to an FS.FetchStatus with no vnode. 19325cf9dd55SDavid Howells */ 19335cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status(struct afs_call *call) 19345cf9dd55SDavid Howells { 19355cf9dd55SDavid Howells const __be32 *bp; 19365cf9dd55SDavid Howells int ret; 19375cf9dd55SDavid Howells 19385cf9dd55SDavid Howells ret = afs_transfer_reply(call); 19395cf9dd55SDavid Howells if (ret < 0) 19405cf9dd55SDavid Howells return ret; 19415cf9dd55SDavid Howells 19425cf9dd55SDavid Howells /* unmarshall the reply once we've received all of it */ 19435cf9dd55SDavid Howells bp = call->buffer; 1944a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1945160cb957SDavid Howells if (ret < 0) 1946160cb957SDavid Howells return ret; 1947a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 1948a58823acSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 19495cf9dd55SDavid Howells 19505cf9dd55SDavid Howells _leave(" = 0 [done]"); 19515cf9dd55SDavid Howells return 0; 19525cf9dd55SDavid Howells } 19535cf9dd55SDavid Howells 19545cf9dd55SDavid Howells /* 19555cf9dd55SDavid Howells * FS.FetchStatus operation type 19565cf9dd55SDavid Howells */ 19575cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus = { 19585cf9dd55SDavid Howells .name = "FS.FetchStatus", 19595cf9dd55SDavid Howells .op = afs_FS_FetchStatus, 19605cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status, 19615cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 19625cf9dd55SDavid Howells }; 19635cf9dd55SDavid Howells 19645cf9dd55SDavid Howells /* 19655cf9dd55SDavid Howells * Fetch the status information for a fid without needing a vnode handle. 19665cf9dd55SDavid Howells */ 19675cf9dd55SDavid Howells int afs_fs_fetch_status(struct afs_fs_cursor *fc, 19685cf9dd55SDavid Howells struct afs_net *net, 19695cf9dd55SDavid Howells struct afs_fid *fid, 1970a58823acSDavid Howells struct afs_status_cb *scb, 19715cf9dd55SDavid Howells struct afs_volsync *volsync) 19725cf9dd55SDavid Howells { 19735cf9dd55SDavid Howells struct afs_call *call; 19745cf9dd55SDavid Howells __be32 *bp; 19755cf9dd55SDavid Howells 197630062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1977a58823acSDavid Howells return yfs_fs_fetch_status(fc, net, fid, scb, volsync); 197830062bd1SDavid Howells 19793b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 19805cf9dd55SDavid Howells key_serial(fc->key), fid->vid, fid->vnode); 19815cf9dd55SDavid Howells 19825cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); 19835cf9dd55SDavid Howells if (!call) { 19845cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 19855cf9dd55SDavid Howells return -ENOMEM; 19865cf9dd55SDavid Howells } 19875cf9dd55SDavid Howells 19885cf9dd55SDavid Howells call->key = fc->key; 1989ffba718eSDavid Howells call->out_fid = fid; 1990a58823acSDavid Howells call->out_scb = scb; 1991ffba718eSDavid Howells call->out_volsync = volsync; 19925cf9dd55SDavid Howells 19935cf9dd55SDavid Howells /* marshall the parameters */ 19945cf9dd55SDavid Howells bp = call->request; 19955cf9dd55SDavid Howells bp[0] = htonl(FSFETCHSTATUS); 19965cf9dd55SDavid Howells bp[1] = htonl(fid->vid); 19975cf9dd55SDavid Howells bp[2] = htonl(fid->vnode); 19985cf9dd55SDavid Howells bp[3] = htonl(fid->unique); 19995cf9dd55SDavid Howells 20005cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 20015cf9dd55SDavid Howells trace_afs_make_fs_call(call, fid); 200220b8391fSDavid Howells afs_set_fc_call(call, fc); 20030b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 20040b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 20055cf9dd55SDavid Howells } 20065cf9dd55SDavid Howells 20075cf9dd55SDavid Howells /* 20085cf9dd55SDavid Howells * Deliver reply data to an FS.InlineBulkStatus call 20095cf9dd55SDavid Howells */ 20105cf9dd55SDavid Howells static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) 20115cf9dd55SDavid Howells { 201287182759SDavid Howells struct afs_status_cb *scb; 20135cf9dd55SDavid Howells const __be32 *bp; 20145cf9dd55SDavid Howells u32 tmp; 20155cf9dd55SDavid Howells int ret; 20165cf9dd55SDavid Howells 20175cf9dd55SDavid Howells _enter("{%u}", call->unmarshall); 20185cf9dd55SDavid Howells 20195cf9dd55SDavid Howells switch (call->unmarshall) { 20205cf9dd55SDavid Howells case 0: 202112bdcf33SDavid Howells afs_extract_to_tmp(call); 20225cf9dd55SDavid Howells call->unmarshall++; 20235cf9dd55SDavid Howells 20245cf9dd55SDavid Howells /* Extract the file status count and array in two steps */ 2025e690c9e3SGustavo A. R. Silva /* Fall through */ 20265cf9dd55SDavid Howells case 1: 20275cf9dd55SDavid Howells _debug("extract status count"); 202812bdcf33SDavid Howells ret = afs_extract_data(call, true); 20295cf9dd55SDavid Howells if (ret < 0) 20305cf9dd55SDavid Howells return ret; 20315cf9dd55SDavid Howells 20325cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20335cf9dd55SDavid Howells _debug("status count: %u/%u", tmp, call->count2); 20345cf9dd55SDavid Howells if (tmp != call->count2) 2035160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2036160cb957SDavid Howells afs_eproto_ibulkst_count); 20375cf9dd55SDavid Howells 20385cf9dd55SDavid Howells call->count = 0; 20395cf9dd55SDavid Howells call->unmarshall++; 20405cf9dd55SDavid Howells more_counts: 204112bdcf33SDavid Howells afs_extract_to_buf(call, 21 * sizeof(__be32)); 20425cf9dd55SDavid Howells 2043e690c9e3SGustavo A. R. Silva /* Fall through */ 20445cf9dd55SDavid Howells case 2: 20455cf9dd55SDavid Howells _debug("extract status array %u", call->count); 204612bdcf33SDavid Howells ret = afs_extract_data(call, true); 20475cf9dd55SDavid Howells if (ret < 0) 20485cf9dd55SDavid Howells return ret; 20495cf9dd55SDavid Howells 20505cf9dd55SDavid Howells bp = call->buffer; 205187182759SDavid Howells scb = &call->out_scb[call->count]; 2052a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, scb); 2053160cb957SDavid Howells if (ret < 0) 2054160cb957SDavid Howells return ret; 20555cf9dd55SDavid Howells 20565cf9dd55SDavid Howells call->count++; 20575cf9dd55SDavid Howells if (call->count < call->count2) 20585cf9dd55SDavid Howells goto more_counts; 20595cf9dd55SDavid Howells 20605cf9dd55SDavid Howells call->count = 0; 20615cf9dd55SDavid Howells call->unmarshall++; 206212bdcf33SDavid Howells afs_extract_to_tmp(call); 20635cf9dd55SDavid Howells 20645cf9dd55SDavid Howells /* Extract the callback count and array in two steps */ 2065e690c9e3SGustavo A. R. Silva /* Fall through */ 20665cf9dd55SDavid Howells case 3: 20675cf9dd55SDavid Howells _debug("extract CB count"); 206812bdcf33SDavid Howells ret = afs_extract_data(call, true); 20695cf9dd55SDavid Howells if (ret < 0) 20705cf9dd55SDavid Howells return ret; 20715cf9dd55SDavid Howells 20725cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20735cf9dd55SDavid Howells _debug("CB count: %u", tmp); 20745cf9dd55SDavid Howells if (tmp != call->count2) 2075160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2076160cb957SDavid Howells afs_eproto_ibulkst_cb_count); 20775cf9dd55SDavid Howells call->count = 0; 20785cf9dd55SDavid Howells call->unmarshall++; 20795cf9dd55SDavid Howells more_cbs: 208012bdcf33SDavid Howells afs_extract_to_buf(call, 3 * sizeof(__be32)); 20815cf9dd55SDavid Howells 2082e690c9e3SGustavo A. R. Silva /* Fall through */ 20835cf9dd55SDavid Howells case 4: 20845cf9dd55SDavid Howells _debug("extract CB array"); 208512bdcf33SDavid Howells ret = afs_extract_data(call, true); 20865cf9dd55SDavid Howells if (ret < 0) 20875cf9dd55SDavid Howells return ret; 20885cf9dd55SDavid Howells 20895cf9dd55SDavid Howells _debug("unmarshall CB array"); 20905cf9dd55SDavid Howells bp = call->buffer; 209187182759SDavid Howells scb = &call->out_scb[call->count]; 2092a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, scb); 20935cf9dd55SDavid Howells call->count++; 20945cf9dd55SDavid Howells if (call->count < call->count2) 20955cf9dd55SDavid Howells goto more_cbs; 20965cf9dd55SDavid Howells 209712bdcf33SDavid Howells afs_extract_to_buf(call, 6 * sizeof(__be32)); 20985cf9dd55SDavid Howells call->unmarshall++; 20995cf9dd55SDavid Howells 2100e690c9e3SGustavo A. R. Silva /* Fall through */ 21015cf9dd55SDavid Howells case 5: 210212bdcf33SDavid Howells ret = afs_extract_data(call, false); 21035cf9dd55SDavid Howells if (ret < 0) 21045cf9dd55SDavid Howells return ret; 21055cf9dd55SDavid Howells 21065cf9dd55SDavid Howells bp = call->buffer; 2107ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 21085cf9dd55SDavid Howells 21095cf9dd55SDavid Howells call->unmarshall++; 21105cf9dd55SDavid Howells 21115cf9dd55SDavid Howells case 6: 21125cf9dd55SDavid Howells break; 21135cf9dd55SDavid Howells } 21145cf9dd55SDavid Howells 21155cf9dd55SDavid Howells _leave(" = 0 [done]"); 21165cf9dd55SDavid Howells return 0; 21175cf9dd55SDavid Howells } 21185cf9dd55SDavid Howells 21195cf9dd55SDavid Howells /* 21205cf9dd55SDavid Howells * FS.InlineBulkStatus operation type 21215cf9dd55SDavid Howells */ 21225cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSInlineBulkStatus = { 21235cf9dd55SDavid Howells .name = "FS.InlineBulkStatus", 21245cf9dd55SDavid Howells .op = afs_FS_InlineBulkStatus, 21255cf9dd55SDavid Howells .deliver = afs_deliver_fs_inline_bulk_status, 21265cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 21275cf9dd55SDavid Howells }; 21285cf9dd55SDavid Howells 21295cf9dd55SDavid Howells /* 21305cf9dd55SDavid Howells * Fetch the status information for up to 50 files 21315cf9dd55SDavid Howells */ 21325cf9dd55SDavid Howells int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, 21335cf9dd55SDavid Howells struct afs_net *net, 21345cf9dd55SDavid Howells struct afs_fid *fids, 213587182759SDavid Howells struct afs_status_cb *statuses, 21365cf9dd55SDavid Howells unsigned int nr_fids, 21375cf9dd55SDavid Howells struct afs_volsync *volsync) 21385cf9dd55SDavid Howells { 21395cf9dd55SDavid Howells struct afs_call *call; 21405cf9dd55SDavid Howells __be32 *bp; 21415cf9dd55SDavid Howells int i; 21425cf9dd55SDavid Howells 214330062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 214487182759SDavid Howells return yfs_fs_inline_bulk_status(fc, net, fids, statuses, 214530062bd1SDavid Howells nr_fids, volsync); 214630062bd1SDavid Howells 21473b6492dfSDavid Howells _enter(",%x,{%llx:%llu},%u", 21485cf9dd55SDavid Howells key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); 21495cf9dd55SDavid Howells 21505cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus, 21515cf9dd55SDavid Howells (2 + nr_fids * 3) * 4, 21525cf9dd55SDavid Howells 21 * 4); 21535cf9dd55SDavid Howells if (!call) { 21545cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 21555cf9dd55SDavid Howells return -ENOMEM; 21565cf9dd55SDavid Howells } 21575cf9dd55SDavid Howells 21585cf9dd55SDavid Howells call->key = fc->key; 215987182759SDavid Howells call->out_scb = statuses; 2160ffba718eSDavid Howells call->out_volsync = volsync; 21615cf9dd55SDavid Howells call->count2 = nr_fids; 21625cf9dd55SDavid Howells 21635cf9dd55SDavid Howells /* marshall the parameters */ 21645cf9dd55SDavid Howells bp = call->request; 21655cf9dd55SDavid Howells *bp++ = htonl(FSINLINEBULKSTATUS); 21665cf9dd55SDavid Howells *bp++ = htonl(nr_fids); 21675cf9dd55SDavid Howells for (i = 0; i < nr_fids; i++) { 21685cf9dd55SDavid Howells *bp++ = htonl(fids[i].vid); 21695cf9dd55SDavid Howells *bp++ = htonl(fids[i].vnode); 21705cf9dd55SDavid Howells *bp++ = htonl(fids[i].unique); 21715cf9dd55SDavid Howells } 21725cf9dd55SDavid Howells 21735cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 21745cf9dd55SDavid Howells trace_afs_make_fs_call(call, &fids[0]); 217520b8391fSDavid Howells afs_set_fc_call(call, fc); 21760b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 21770b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 21785cf9dd55SDavid Howells } 2179260f082bSDavid Howells 2180260f082bSDavid Howells /* 2181260f082bSDavid Howells * deliver reply data to an FS.FetchACL 2182260f082bSDavid Howells */ 2183260f082bSDavid Howells static int afs_deliver_fs_fetch_acl(struct afs_call *call) 2184260f082bSDavid Howells { 2185260f082bSDavid Howells struct afs_acl *acl; 2186260f082bSDavid Howells const __be32 *bp; 2187260f082bSDavid Howells unsigned int size; 2188260f082bSDavid Howells int ret; 2189260f082bSDavid Howells 2190260f082bSDavid Howells _enter("{%u}", call->unmarshall); 2191260f082bSDavid Howells 2192260f082bSDavid Howells switch (call->unmarshall) { 2193260f082bSDavid Howells case 0: 2194260f082bSDavid Howells afs_extract_to_tmp(call); 2195260f082bSDavid Howells call->unmarshall++; 2196260f082bSDavid Howells 2197260f082bSDavid Howells /* extract the returned data length */ 2198260f082bSDavid Howells case 1: 2199260f082bSDavid Howells ret = afs_extract_data(call, true); 2200260f082bSDavid Howells if (ret < 0) 2201260f082bSDavid Howells return ret; 2202260f082bSDavid Howells 2203260f082bSDavid Howells size = call->count2 = ntohl(call->tmp); 2204260f082bSDavid Howells size = round_up(size, 4); 2205260f082bSDavid Howells 2206260f082bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); 2207260f082bSDavid Howells if (!acl) 2208260f082bSDavid Howells return -ENOMEM; 2209ffba718eSDavid Howells call->ret_acl = acl; 2210260f082bSDavid Howells acl->size = call->count2; 2211260f082bSDavid Howells afs_extract_begin(call, acl->data, size); 2212260f082bSDavid Howells call->unmarshall++; 2213260f082bSDavid Howells 2214260f082bSDavid Howells /* extract the returned data */ 2215260f082bSDavid Howells case 2: 2216260f082bSDavid Howells ret = afs_extract_data(call, true); 2217260f082bSDavid Howells if (ret < 0) 2218260f082bSDavid Howells return ret; 2219260f082bSDavid Howells 2220260f082bSDavid Howells afs_extract_to_buf(call, (21 + 6) * 4); 2221260f082bSDavid Howells call->unmarshall++; 2222260f082bSDavid Howells 2223260f082bSDavid Howells /* extract the metadata */ 2224260f082bSDavid Howells case 3: 2225260f082bSDavid Howells ret = afs_extract_data(call, false); 2226260f082bSDavid Howells if (ret < 0) 2227260f082bSDavid Howells return ret; 2228260f082bSDavid Howells 2229260f082bSDavid Howells bp = call->buffer; 2230a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2231260f082bSDavid Howells if (ret < 0) 2232260f082bSDavid Howells return ret; 2233ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2234260f082bSDavid Howells 2235260f082bSDavid Howells call->unmarshall++; 2236260f082bSDavid Howells 2237260f082bSDavid Howells case 4: 2238260f082bSDavid Howells break; 2239260f082bSDavid Howells } 2240260f082bSDavid Howells 2241260f082bSDavid Howells _leave(" = 0 [done]"); 2242260f082bSDavid Howells return 0; 2243260f082bSDavid Howells } 2244260f082bSDavid Howells 2245260f082bSDavid Howells static void afs_destroy_fs_fetch_acl(struct afs_call *call) 2246260f082bSDavid Howells { 2247ffba718eSDavid Howells kfree(call->ret_acl); 2248260f082bSDavid Howells afs_flat_call_destructor(call); 2249260f082bSDavid Howells } 2250260f082bSDavid Howells 2251260f082bSDavid Howells /* 2252260f082bSDavid Howells * FS.FetchACL operation type 2253260f082bSDavid Howells */ 2254260f082bSDavid Howells static const struct afs_call_type afs_RXFSFetchACL = { 2255260f082bSDavid Howells .name = "FS.FetchACL", 2256260f082bSDavid Howells .op = afs_FS_FetchACL, 2257260f082bSDavid Howells .deliver = afs_deliver_fs_fetch_acl, 2258260f082bSDavid Howells .destructor = afs_destroy_fs_fetch_acl, 2259260f082bSDavid Howells }; 2260260f082bSDavid Howells 2261260f082bSDavid Howells /* 2262260f082bSDavid Howells * Fetch the ACL for a file. 2263260f082bSDavid Howells */ 2264a58823acSDavid Howells struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc, 2265a58823acSDavid Howells struct afs_status_cb *scb) 2266260f082bSDavid Howells { 2267260f082bSDavid Howells struct afs_vnode *vnode = fc->vnode; 2268260f082bSDavid Howells struct afs_call *call; 2269260f082bSDavid Howells struct afs_net *net = afs_v2net(vnode); 2270260f082bSDavid Howells __be32 *bp; 2271260f082bSDavid Howells 2272260f082bSDavid Howells _enter(",%x,{%llx:%llu},,", 2273260f082bSDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2274260f082bSDavid Howells 2275260f082bSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4); 2276260f082bSDavid Howells if (!call) { 2277260f082bSDavid Howells fc->ac.error = -ENOMEM; 2278260f082bSDavid Howells return ERR_PTR(-ENOMEM); 2279260f082bSDavid Howells } 2280260f082bSDavid Howells 2281260f082bSDavid Howells call->key = fc->key; 2282ffba718eSDavid Howells call->ret_acl = NULL; 2283a58823acSDavid Howells call->out_scb = scb; 2284ffba718eSDavid Howells call->out_volsync = NULL; 2285260f082bSDavid Howells 2286260f082bSDavid Howells /* marshall the parameters */ 2287260f082bSDavid Howells bp = call->request; 2288260f082bSDavid Howells bp[0] = htonl(FSFETCHACL); 2289260f082bSDavid Howells bp[1] = htonl(vnode->fid.vid); 2290260f082bSDavid Howells bp[2] = htonl(vnode->fid.vnode); 2291260f082bSDavid Howells bp[3] = htonl(vnode->fid.unique); 2292260f082bSDavid Howells 2293260f082bSDavid Howells afs_use_fs_server(call, fc->cbi); 2294260f082bSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 2295260f082bSDavid Howells afs_make_call(&fc->ac, call, GFP_KERNEL); 2296260f082bSDavid Howells return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac); 2297260f082bSDavid Howells } 2298b10494afSJoe Gorse 2299b10494afSJoe Gorse /* 2300ffba718eSDavid Howells * Deliver reply data to any operation that returns file status and volume 2301ffba718eSDavid Howells * sync. 2302ffba718eSDavid Howells */ 2303ffba718eSDavid Howells static int afs_deliver_fs_file_status_and_vol(struct afs_call *call) 2304ffba718eSDavid Howells { 2305ffba718eSDavid Howells const __be32 *bp; 2306ffba718eSDavid Howells int ret; 2307ffba718eSDavid Howells 2308ffba718eSDavid Howells ret = afs_transfer_reply(call); 2309ffba718eSDavid Howells if (ret < 0) 2310ffba718eSDavid Howells return ret; 2311ffba718eSDavid Howells 2312ffba718eSDavid Howells bp = call->buffer; 2313a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2314ffba718eSDavid Howells if (ret < 0) 2315ffba718eSDavid Howells return ret; 2316ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2317ffba718eSDavid Howells 2318ffba718eSDavid Howells _leave(" = 0 [done]"); 2319ffba718eSDavid Howells return 0; 2320ffba718eSDavid Howells } 2321ffba718eSDavid Howells 2322ffba718eSDavid Howells /* 2323b10494afSJoe Gorse * FS.StoreACL operation type 2324b10494afSJoe Gorse */ 2325b10494afSJoe Gorse static const struct afs_call_type afs_RXFSStoreACL = { 2326b10494afSJoe Gorse .name = "FS.StoreACL", 2327b10494afSJoe Gorse .op = afs_FS_StoreACL, 2328ffba718eSDavid Howells .deliver = afs_deliver_fs_file_status_and_vol, 2329b10494afSJoe Gorse .destructor = afs_flat_call_destructor, 2330b10494afSJoe Gorse }; 2331b10494afSJoe Gorse 2332b10494afSJoe Gorse /* 2333b10494afSJoe Gorse * Fetch the ACL for a file. 2334b10494afSJoe Gorse */ 2335a58823acSDavid Howells int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl, 2336a58823acSDavid Howells struct afs_status_cb *scb) 2337b10494afSJoe Gorse { 2338b10494afSJoe Gorse struct afs_vnode *vnode = fc->vnode; 2339b10494afSJoe Gorse struct afs_call *call; 2340b10494afSJoe Gorse struct afs_net *net = afs_v2net(vnode); 2341b10494afSJoe Gorse size_t size; 2342b10494afSJoe Gorse __be32 *bp; 2343b10494afSJoe Gorse 2344b10494afSJoe Gorse _enter(",%x,{%llx:%llu},,", 2345b10494afSJoe Gorse key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2346b10494afSJoe Gorse 2347b10494afSJoe Gorse size = round_up(acl->size, 4); 2348b10494afSJoe Gorse call = afs_alloc_flat_call(net, &afs_RXFSStoreACL, 2349b10494afSJoe Gorse 5 * 4 + size, (21 + 6) * 4); 2350b10494afSJoe Gorse if (!call) { 2351b10494afSJoe Gorse fc->ac.error = -ENOMEM; 2352b10494afSJoe Gorse return -ENOMEM; 2353b10494afSJoe Gorse } 2354b10494afSJoe Gorse 2355b10494afSJoe Gorse call->key = fc->key; 2356a58823acSDavid Howells call->out_scb = scb; 2357ffba718eSDavid Howells call->out_volsync = NULL; 2358b10494afSJoe Gorse 2359b10494afSJoe Gorse /* marshall the parameters */ 2360b10494afSJoe Gorse bp = call->request; 2361b10494afSJoe Gorse bp[0] = htonl(FSSTOREACL); 2362b10494afSJoe Gorse bp[1] = htonl(vnode->fid.vid); 2363b10494afSJoe Gorse bp[2] = htonl(vnode->fid.vnode); 2364b10494afSJoe Gorse bp[3] = htonl(vnode->fid.unique); 2365b10494afSJoe Gorse bp[4] = htonl(acl->size); 2366b10494afSJoe Gorse memcpy(&bp[5], acl->data, acl->size); 2367b10494afSJoe Gorse if (acl->size != size) 2368b10494afSJoe Gorse memset((void *)&bp[5] + acl->size, 0, size - acl->size); 2369b10494afSJoe Gorse 2370b10494afSJoe Gorse trace_afs_make_fs_call(call, &vnode->fid); 2371b10494afSJoe Gorse afs_make_call(&fc->ac, call, GFP_KERNEL); 2372b10494afSJoe Gorse return afs_wait_for_call_to_complete(call, &fc->ac); 23731da177e4SLinus Torvalds } 2374