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 18d2ddc776SDavid Howells static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi) 19c435ee34SDavid Howells { 20d2ddc776SDavid Howells call->cbi = afs_get_cb_interest(cbi); 21c435ee34SDavid Howells } 22c435ee34SDavid Howells 236db3ac3cSDavid Howells /* 24260a9803SDavid Howells * decode an AFSFid block 25260a9803SDavid Howells */ 26260a9803SDavid Howells static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid) 27260a9803SDavid Howells { 28260a9803SDavid Howells const __be32 *bp = *_bp; 29260a9803SDavid Howells 30260a9803SDavid Howells fid->vid = ntohl(*bp++); 31260a9803SDavid Howells fid->vnode = ntohl(*bp++); 32260a9803SDavid Howells fid->unique = ntohl(*bp++); 33260a9803SDavid Howells *_bp = bp; 34260a9803SDavid Howells } 35260a9803SDavid Howells 36260a9803SDavid Howells /* 37888b3384SDavid Howells * Dump a bad file status record. 38888b3384SDavid Howells */ 39888b3384SDavid Howells static void xdr_dump_bad(const __be32 *bp) 40888b3384SDavid Howells { 41888b3384SDavid Howells __be32 x[4]; 42888b3384SDavid Howells int i; 43888b3384SDavid Howells 44888b3384SDavid Howells pr_notice("AFS XDR: Bad status record\n"); 45888b3384SDavid Howells for (i = 0; i < 5 * 4 * 4; i += 16) { 46888b3384SDavid Howells memcpy(x, bp, 16); 47888b3384SDavid Howells bp += 4; 48888b3384SDavid Howells pr_notice("%03x: %08x %08x %08x %08x\n", 49888b3384SDavid Howells i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3])); 50888b3384SDavid Howells } 51888b3384SDavid Howells 52888b3384SDavid Howells memcpy(x, bp, 4); 53888b3384SDavid Howells pr_notice("0x50: %08x\n", ntohl(x[0])); 54888b3384SDavid Howells } 55888b3384SDavid Howells 56888b3384SDavid Howells /* 57dd9fbcb8SDavid Howells * decode an AFSFetchStatus block 58dd9fbcb8SDavid Howells */ 59a58823acSDavid Howells static int xdr_decode_AFSFetchStatus(const __be32 **_bp, 60a58823acSDavid Howells struct afs_call *call, 61a58823acSDavid Howells struct afs_status_cb *scb) 62dd9fbcb8SDavid Howells { 63dd9fbcb8SDavid Howells const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp; 64a58823acSDavid Howells struct afs_file_status *status = &scb->status; 65684b0f68SDavid Howells bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus); 66dd9fbcb8SDavid Howells u64 data_version, size; 67dd9fbcb8SDavid Howells u32 type, abort_code; 68c72057b5SDavid Howells int ret; 69dd9fbcb8SDavid Howells 70684b0f68SDavid Howells abort_code = ntohl(xdr->abort_code); 71684b0f68SDavid Howells 72dd9fbcb8SDavid Howells if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { 73684b0f68SDavid Howells if (xdr->if_version == htonl(0) && 74684b0f68SDavid Howells abort_code != 0 && 75684b0f68SDavid Howells inline_error) { 76684b0f68SDavid Howells /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus 77684b0f68SDavid Howells * whereby it doesn't set the interface version in the error 78684b0f68SDavid Howells * case. 79684b0f68SDavid Howells */ 80684b0f68SDavid Howells status->abort_code = abort_code; 81a38a7558SDavid Howells scb->have_error = true; 82c72057b5SDavid Howells goto good; 83684b0f68SDavid Howells } 84684b0f68SDavid Howells 85dd9fbcb8SDavid Howells pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); 86dd9fbcb8SDavid Howells goto bad; 87dd9fbcb8SDavid Howells } 88dd9fbcb8SDavid Howells 89684b0f68SDavid Howells if (abort_code != 0 && inline_error) { 90684b0f68SDavid Howells status->abort_code = abort_code; 91c72057b5SDavid Howells goto good; 92684b0f68SDavid Howells } 93684b0f68SDavid Howells 94dd9fbcb8SDavid Howells type = ntohl(xdr->type); 95dd9fbcb8SDavid Howells switch (type) { 96dd9fbcb8SDavid Howells case AFS_FTYPE_FILE: 97dd9fbcb8SDavid Howells case AFS_FTYPE_DIR: 98dd9fbcb8SDavid Howells case AFS_FTYPE_SYMLINK: 99dd9fbcb8SDavid Howells status->type = type; 100dd9fbcb8SDavid Howells break; 101dd9fbcb8SDavid Howells default: 102dd9fbcb8SDavid Howells goto bad; 103dd9fbcb8SDavid Howells } 104dd9fbcb8SDavid Howells 105a58823acSDavid Howells status->nlink = ntohl(xdr->nlink); 106a58823acSDavid Howells status->author = ntohl(xdr->author); 107a58823acSDavid Howells status->owner = ntohl(xdr->owner); 108a58823acSDavid Howells status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */ 109a58823acSDavid Howells status->anon_access = ntohl(xdr->anon_access); 110a58823acSDavid Howells status->mode = ntohl(xdr->mode) & S_IALLUGO; 111a58823acSDavid Howells status->group = ntohl(xdr->group); 112a58823acSDavid Howells status->lock_count = ntohl(xdr->lock_count); 113dd9fbcb8SDavid Howells 114d4936803SDavid Howells status->mtime_client.tv_sec = ntohl(xdr->mtime_client); 115d4936803SDavid Howells status->mtime_client.tv_nsec = 0; 116d4936803SDavid Howells status->mtime_server.tv_sec = ntohl(xdr->mtime_server); 117d4936803SDavid Howells status->mtime_server.tv_nsec = 0; 118dd9fbcb8SDavid Howells 119dd9fbcb8SDavid Howells size = (u64)ntohl(xdr->size_lo); 120dd9fbcb8SDavid Howells size |= (u64)ntohl(xdr->size_hi) << 32; 121dd9fbcb8SDavid Howells status->size = size; 122dd9fbcb8SDavid Howells 123dd9fbcb8SDavid Howells data_version = (u64)ntohl(xdr->data_version_lo); 124dd9fbcb8SDavid Howells data_version |= (u64)ntohl(xdr->data_version_hi) << 32; 125dd9fbcb8SDavid Howells status->data_version = data_version; 126a38a7558SDavid Howells scb->have_status = true; 127c72057b5SDavid Howells good: 128c72057b5SDavid Howells ret = 0; 129c72057b5SDavid Howells advance: 130dd9fbcb8SDavid Howells *_bp = (const void *)*_bp + sizeof(*xdr); 131c72057b5SDavid Howells return ret; 132dd9fbcb8SDavid Howells 133dd9fbcb8SDavid Howells bad: 134dd9fbcb8SDavid Howells xdr_dump_bad(*_bp); 135c72057b5SDavid Howells ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); 136c72057b5SDavid Howells goto advance; 137c875c76aSDavid Howells } 138c875c76aSDavid Howells 13978107055SDavid Howells static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) 14078107055SDavid Howells { 14178107055SDavid Howells return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; 14278107055SDavid Howells } 14378107055SDavid Howells 144a58823acSDavid Howells static void xdr_decode_AFSCallBack(const __be32 **_bp, 145a58823acSDavid Howells struct afs_call *call, 146a58823acSDavid Howells struct afs_status_cb *scb) 14778107055SDavid Howells { 148a58823acSDavid Howells struct afs_callback *cb = &scb->callback; 14978107055SDavid Howells const __be32 *bp = *_bp; 15078107055SDavid Howells 1517c712458SDavid Howells bp++; /* version */ 15278107055SDavid Howells cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); 1537c712458SDavid Howells bp++; /* type */ 154a58823acSDavid Howells scb->have_cb = true; 15578107055SDavid Howells *_bp = bp; 15678107055SDavid Howells } 15778107055SDavid Howells 1581da177e4SLinus Torvalds /* 15908e0e7c8SDavid Howells * decode an AFSVolSync block 1601da177e4SLinus Torvalds */ 16108e0e7c8SDavid Howells static void xdr_decode_AFSVolSync(const __be32 **_bp, 16208e0e7c8SDavid Howells struct afs_volsync *volsync) 1631da177e4SLinus Torvalds { 16408e0e7c8SDavid Howells const __be32 *bp = *_bp; 16530062bd1SDavid Howells u32 creation; 1661da177e4SLinus Torvalds 16730062bd1SDavid Howells creation = ntohl(*bp++); 16808e0e7c8SDavid Howells bp++; /* spare2 */ 16908e0e7c8SDavid Howells bp++; /* spare3 */ 17008e0e7c8SDavid Howells bp++; /* spare4 */ 17108e0e7c8SDavid Howells bp++; /* spare5 */ 17208e0e7c8SDavid Howells bp++; /* spare6 */ 17308e0e7c8SDavid Howells *_bp = bp; 17430062bd1SDavid Howells 17530062bd1SDavid Howells if (volsync) 17630062bd1SDavid Howells volsync->creation = creation; 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 17908e0e7c8SDavid Howells /* 18031143d5dSDavid Howells * encode the requested attributes into an AFSStoreStatus block 18131143d5dSDavid Howells */ 18231143d5dSDavid Howells static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr) 18331143d5dSDavid Howells { 18431143d5dSDavid Howells __be32 *bp = *_bp; 18531143d5dSDavid Howells u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0; 18631143d5dSDavid Howells 18731143d5dSDavid Howells mask = 0; 18831143d5dSDavid Howells if (attr->ia_valid & ATTR_MTIME) { 18931143d5dSDavid Howells mask |= AFS_SET_MTIME; 19031143d5dSDavid Howells mtime = attr->ia_mtime.tv_sec; 19131143d5dSDavid Howells } 19231143d5dSDavid Howells 19331143d5dSDavid Howells if (attr->ia_valid & ATTR_UID) { 19431143d5dSDavid Howells mask |= AFS_SET_OWNER; 195a0a5386aSEric W. Biederman owner = from_kuid(&init_user_ns, attr->ia_uid); 19631143d5dSDavid Howells } 19731143d5dSDavid Howells 19831143d5dSDavid Howells if (attr->ia_valid & ATTR_GID) { 19931143d5dSDavid Howells mask |= AFS_SET_GROUP; 200a0a5386aSEric W. Biederman group = from_kgid(&init_user_ns, attr->ia_gid); 20131143d5dSDavid Howells } 20231143d5dSDavid Howells 20331143d5dSDavid Howells if (attr->ia_valid & ATTR_MODE) { 20431143d5dSDavid Howells mask |= AFS_SET_MODE; 20531143d5dSDavid Howells mode = attr->ia_mode & S_IALLUGO; 20631143d5dSDavid Howells } 20731143d5dSDavid Howells 20831143d5dSDavid Howells *bp++ = htonl(mask); 20931143d5dSDavid Howells *bp++ = htonl(mtime); 21031143d5dSDavid Howells *bp++ = htonl(owner); 21131143d5dSDavid Howells *bp++ = htonl(group); 21231143d5dSDavid Howells *bp++ = htonl(mode); 21331143d5dSDavid Howells *bp++ = 0; /* segment size */ 21431143d5dSDavid Howells *_bp = bp; 21531143d5dSDavid Howells } 21631143d5dSDavid Howells 21731143d5dSDavid Howells /* 21845222b9eSDavid Howells * decode an AFSFetchVolumeStatus block 21945222b9eSDavid Howells */ 22045222b9eSDavid Howells static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, 22145222b9eSDavid Howells struct afs_volume_status *vs) 22245222b9eSDavid Howells { 22345222b9eSDavid Howells const __be32 *bp = *_bp; 22445222b9eSDavid Howells 22545222b9eSDavid Howells vs->vid = ntohl(*bp++); 22645222b9eSDavid Howells vs->parent_id = ntohl(*bp++); 22745222b9eSDavid Howells vs->online = ntohl(*bp++); 22845222b9eSDavid Howells vs->in_service = ntohl(*bp++); 22945222b9eSDavid Howells vs->blessed = ntohl(*bp++); 23045222b9eSDavid Howells vs->needs_salvage = ntohl(*bp++); 23145222b9eSDavid Howells vs->type = ntohl(*bp++); 23245222b9eSDavid Howells vs->min_quota = ntohl(*bp++); 23345222b9eSDavid Howells vs->max_quota = ntohl(*bp++); 23445222b9eSDavid Howells vs->blocks_in_use = ntohl(*bp++); 23545222b9eSDavid Howells vs->part_blocks_avail = ntohl(*bp++); 23645222b9eSDavid Howells vs->part_max_blocks = ntohl(*bp++); 23730062bd1SDavid Howells vs->vol_copy_date = 0; 23830062bd1SDavid Howells vs->vol_backup_date = 0; 23945222b9eSDavid Howells *_bp = bp; 24045222b9eSDavid Howells } 24145222b9eSDavid Howells 24245222b9eSDavid Howells /* 24308e0e7c8SDavid Howells * deliver reply data to an FS.FetchStatus 24408e0e7c8SDavid Howells */ 2455cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) 24608e0e7c8SDavid Howells { 24708e0e7c8SDavid Howells const __be32 *bp; 248372ee163SDavid Howells int ret; 2491da177e4SLinus Torvalds 250d001648eSDavid Howells ret = afs_transfer_reply(call); 251372ee163SDavid Howells if (ret < 0) 252372ee163SDavid Howells return ret; 2531da177e4SLinus Torvalds 25408e0e7c8SDavid Howells /* unmarshall the reply once we've received all of it */ 25508e0e7c8SDavid Howells bp = call->buffer; 256a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 257160cb957SDavid Howells if (ret < 0) 258160cb957SDavid Howells return ret; 259a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 260ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2611da177e4SLinus Torvalds 26208e0e7c8SDavid Howells _leave(" = 0 [done]"); 26308e0e7c8SDavid Howells return 0; 264ec26815aSDavid Howells } 26508e0e7c8SDavid Howells 26608e0e7c8SDavid Howells /* 26708e0e7c8SDavid Howells * FS.FetchStatus operation type 26808e0e7c8SDavid Howells */ 2695cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus_vnode = { 2705cf9dd55SDavid Howells .name = "FS.FetchStatus(vnode)", 271025db80cSDavid Howells .op = afs_FS_FetchStatus, 2725cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status_vnode, 27308e0e7c8SDavid Howells .destructor = afs_flat_call_destructor, 27408e0e7c8SDavid Howells }; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds /* 2771da177e4SLinus Torvalds * fetch the status information for a file 2781da177e4SLinus Torvalds */ 279a58823acSDavid Howells int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb, 280a58823acSDavid Howells struct afs_volsync *volsync) 2811da177e4SLinus Torvalds { 282d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 28308e0e7c8SDavid Howells struct afs_call *call; 284f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 2851da177e4SLinus Torvalds __be32 *bp; 2861da177e4SLinus Torvalds 28730062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 288a58823acSDavid Howells return yfs_fs_fetch_file_status(fc, scb, volsync); 28930062bd1SDavid Howells 2903b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 291d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2921da177e4SLinus Torvalds 2935cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode, 2945cf9dd55SDavid Howells 16, (21 + 3 + 6) * 4); 295d2ddc776SDavid Howells if (!call) { 296d2ddc776SDavid Howells fc->ac.error = -ENOMEM; 29708e0e7c8SDavid Howells return -ENOMEM; 298d2ddc776SDavid Howells } 2991da177e4SLinus Torvalds 300d2ddc776SDavid Howells call->key = fc->key; 301a58823acSDavid Howells call->out_scb = scb; 302ffba718eSDavid Howells call->out_volsync = volsync; 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds /* marshall the parameters */ 30508e0e7c8SDavid Howells bp = call->request; 3061da177e4SLinus Torvalds bp[0] = htonl(FSFETCHSTATUS); 3071da177e4SLinus Torvalds bp[1] = htonl(vnode->fid.vid); 3081da177e4SLinus Torvalds bp[2] = htonl(vnode->fid.vnode); 3091da177e4SLinus Torvalds bp[3] = htonl(vnode->fid.unique); 3101da177e4SLinus Torvalds 311d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 312025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 3130b9bf381SDavid Howells 31420b8391fSDavid Howells afs_set_fc_call(call, fc); 3150b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 3160b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 317ec26815aSDavid Howells } 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds /* 32008e0e7c8SDavid Howells * deliver reply data to an FS.FetchData 3211da177e4SLinus Torvalds */ 322d001648eSDavid Howells static int afs_deliver_fs_fetch_data(struct afs_call *call) 3231da177e4SLinus Torvalds { 324ffba718eSDavid Howells struct afs_read *req = call->read_request; 32508e0e7c8SDavid Howells const __be32 *bp; 326196ee9cdSDavid Howells unsigned int size; 3271da177e4SLinus Torvalds int ret; 3281da177e4SLinus Torvalds 32912bdcf33SDavid Howells _enter("{%u,%zu/%llu}", 330fc276122SDavid Howells call->unmarshall, iov_iter_count(call->iter), req->actual_len); 3311da177e4SLinus Torvalds 33208e0e7c8SDavid Howells switch (call->unmarshall) { 33308e0e7c8SDavid Howells case 0: 334196ee9cdSDavid Howells req->actual_len = 0; 33512bdcf33SDavid Howells req->index = 0; 33612bdcf33SDavid Howells req->offset = req->pos & (PAGE_SIZE - 1); 33708e0e7c8SDavid Howells call->unmarshall++; 33812bdcf33SDavid Howells if (call->operation_ID == FSFETCHDATA64) { 33912bdcf33SDavid Howells afs_extract_to_tmp64(call); 34012bdcf33SDavid Howells } else { 34112bdcf33SDavid Howells call->tmp_u = htonl(0); 34212bdcf33SDavid Howells afs_extract_to_tmp(call); 343b9b1f8d5SDavid Howells } 34429881608SGustavo A. R. Silva /* Fall through */ 3451da177e4SLinus Torvalds 34629881608SGustavo A. R. Silva /* extract the returned data length */ 34712bdcf33SDavid Howells case 1: 34808e0e7c8SDavid Howells _debug("extract data length"); 34912bdcf33SDavid Howells ret = afs_extract_data(call, true); 350372ee163SDavid Howells if (ret < 0) 351372ee163SDavid Howells return ret; 3521da177e4SLinus Torvalds 35312bdcf33SDavid Howells req->actual_len = be64_to_cpu(call->tmp64); 354196ee9cdSDavid Howells _debug("DATA length: %llu", req->actual_len); 35512bdcf33SDavid Howells req->remain = min(req->len, req->actual_len); 35612bdcf33SDavid Howells if (req->remain == 0) 357196ee9cdSDavid Howells goto no_more_data; 35812bdcf33SDavid Howells 35908e0e7c8SDavid Howells call->unmarshall++; 3601da177e4SLinus Torvalds 361196ee9cdSDavid Howells begin_page: 3626db3ac3cSDavid Howells ASSERTCMP(req->index, <, req->nr_pages); 36312bdcf33SDavid Howells if (req->remain > PAGE_SIZE - req->offset) 36412bdcf33SDavid Howells size = PAGE_SIZE - req->offset; 365196ee9cdSDavid Howells else 366196ee9cdSDavid Howells size = req->remain; 36712bdcf33SDavid Howells call->bvec[0].bv_len = size; 36812bdcf33SDavid Howells call->bvec[0].bv_offset = req->offset; 36912bdcf33SDavid Howells call->bvec[0].bv_page = req->pages[req->index]; 370fc276122SDavid Howells iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); 37112bdcf33SDavid Howells ASSERTCMP(size, <=, PAGE_SIZE); 37229881608SGustavo A. R. Silva /* Fall through */ 373196ee9cdSDavid Howells 37429881608SGustavo A. R. Silva /* extract the returned data */ 37512bdcf33SDavid Howells case 2: 37612bdcf33SDavid Howells _debug("extract data %zu/%llu", 377fc276122SDavid Howells iov_iter_count(call->iter), req->remain); 378196ee9cdSDavid Howells 37912bdcf33SDavid Howells ret = afs_extract_data(call, true); 380372ee163SDavid Howells if (ret < 0) 381372ee163SDavid Howells return ret; 38212bdcf33SDavid Howells req->remain -= call->bvec[0].bv_len; 38312bdcf33SDavid Howells req->offset += call->bvec[0].bv_len; 38412bdcf33SDavid Howells ASSERTCMP(req->offset, <=, PAGE_SIZE); 38512bdcf33SDavid Howells if (req->offset == PAGE_SIZE) { 38612bdcf33SDavid Howells req->offset = 0; 387196ee9cdSDavid Howells if (req->page_done) 388a58823acSDavid Howells req->page_done(req); 38929f06985SDavid Howells req->index++; 39012bdcf33SDavid Howells if (req->remain > 0) 391196ee9cdSDavid Howells goto begin_page; 392196ee9cdSDavid Howells } 39312bdcf33SDavid Howells 39412bdcf33SDavid Howells ASSERTCMP(req->remain, ==, 0); 39512bdcf33SDavid Howells if (req->actual_len <= req->len) 3966db3ac3cSDavid Howells goto no_more_data; 3976db3ac3cSDavid Howells 3986db3ac3cSDavid Howells /* Discard any excess data the server gave us */ 39923a28913SDavid Howells afs_extract_discard(call, req->actual_len - req->len); 40012bdcf33SDavid Howells call->unmarshall = 3; 401e690c9e3SGustavo A. R. Silva /* Fall through */ 40229881608SGustavo A. R. Silva 40312bdcf33SDavid Howells case 3: 40412bdcf33SDavid Howells _debug("extract discard %zu/%llu", 405fc276122SDavid Howells iov_iter_count(call->iter), req->actual_len - req->len); 4066db3ac3cSDavid Howells 40712bdcf33SDavid Howells ret = afs_extract_data(call, true); 4086db3ac3cSDavid Howells if (ret < 0) 4096db3ac3cSDavid Howells return ret; 4101da177e4SLinus Torvalds 411196ee9cdSDavid Howells no_more_data: 41212bdcf33SDavid Howells call->unmarshall = 4; 41312bdcf33SDavid Howells afs_extract_to_buf(call, (21 + 3 + 6) * 4); 41429881608SGustavo A. R. Silva /* Fall through */ 41508e0e7c8SDavid Howells 41629881608SGustavo A. R. Silva /* extract the metadata */ 41712bdcf33SDavid Howells case 4: 41812bdcf33SDavid Howells ret = afs_extract_data(call, false); 419372ee163SDavid Howells if (ret < 0) 420372ee163SDavid Howells return ret; 4211da177e4SLinus Torvalds 42208e0e7c8SDavid Howells bp = call->buffer; 423a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 424160cb957SDavid Howells if (ret < 0) 425160cb957SDavid Howells return ret; 426a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 427ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 4281da177e4SLinus Torvalds 429a58823acSDavid Howells req->data_version = call->out_scb->status.data_version; 430a58823acSDavid Howells req->file_size = call->out_scb->status.size; 431a58823acSDavid Howells 43208e0e7c8SDavid Howells call->unmarshall++; 4331da177e4SLinus Torvalds 43412bdcf33SDavid Howells case 5: 4351da177e4SLinus Torvalds break; 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds 4386db3ac3cSDavid Howells for (; req->index < req->nr_pages; req->index++) { 43912bdcf33SDavid Howells if (req->offset < PAGE_SIZE) 4406db3ac3cSDavid Howells zero_user_segment(req->pages[req->index], 44112bdcf33SDavid Howells req->offset, PAGE_SIZE); 442196ee9cdSDavid Howells if (req->page_done) 443a58823acSDavid Howells req->page_done(req); 44412bdcf33SDavid Howells req->offset = 0; 445416351f2SDavid Howells } 446416351f2SDavid Howells 44708e0e7c8SDavid Howells _leave(" = 0 [done]"); 44808e0e7c8SDavid Howells return 0; 449ec26815aSDavid Howells } 4501da177e4SLinus Torvalds 451196ee9cdSDavid Howells static void afs_fetch_data_destructor(struct afs_call *call) 452196ee9cdSDavid Howells { 453ffba718eSDavid Howells struct afs_read *req = call->read_request; 454196ee9cdSDavid Howells 455196ee9cdSDavid Howells afs_put_read(req); 456196ee9cdSDavid Howells afs_flat_call_destructor(call); 457196ee9cdSDavid Howells } 458196ee9cdSDavid Howells 4591da177e4SLinus Torvalds /* 46008e0e7c8SDavid Howells * FS.FetchData operation type 4611da177e4SLinus Torvalds */ 46208e0e7c8SDavid Howells static const struct afs_call_type afs_RXFSFetchData = { 46300d3b7a4SDavid Howells .name = "FS.FetchData", 464025db80cSDavid Howells .op = afs_FS_FetchData, 46508e0e7c8SDavid Howells .deliver = afs_deliver_fs_fetch_data, 466196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 46708e0e7c8SDavid Howells }; 46808e0e7c8SDavid Howells 469b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSFetchData64 = { 470b9b1f8d5SDavid Howells .name = "FS.FetchData64", 471025db80cSDavid Howells .op = afs_FS_FetchData64, 472b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_fetch_data, 473196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 474b9b1f8d5SDavid Howells }; 475b9b1f8d5SDavid Howells 476b9b1f8d5SDavid Howells /* 477b9b1f8d5SDavid Howells * fetch data from a very large file 478b9b1f8d5SDavid Howells */ 479a58823acSDavid Howells static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, 480a58823acSDavid Howells struct afs_status_cb *scb, 481a58823acSDavid Howells struct afs_read *req) 482b9b1f8d5SDavid Howells { 483d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 484b9b1f8d5SDavid Howells struct afs_call *call; 485f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 486b9b1f8d5SDavid Howells __be32 *bp; 487b9b1f8d5SDavid Howells 488b9b1f8d5SDavid Howells _enter(""); 489b9b1f8d5SDavid Howells 490f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4); 491b9b1f8d5SDavid Howells if (!call) 492b9b1f8d5SDavid Howells return -ENOMEM; 493b9b1f8d5SDavid Howells 494d2ddc776SDavid Howells call->key = fc->key; 495a58823acSDavid Howells call->out_scb = scb; 496ffba718eSDavid Howells call->out_volsync = NULL; 497d4438a25SDavid Howells call->read_request = afs_get_read(req); 498b9b1f8d5SDavid Howells 499b9b1f8d5SDavid Howells /* marshall the parameters */ 500b9b1f8d5SDavid Howells bp = call->request; 501b9b1f8d5SDavid Howells bp[0] = htonl(FSFETCHDATA64); 502b9b1f8d5SDavid Howells bp[1] = htonl(vnode->fid.vid); 503b9b1f8d5SDavid Howells bp[2] = htonl(vnode->fid.vnode); 504b9b1f8d5SDavid Howells bp[3] = htonl(vnode->fid.unique); 505196ee9cdSDavid Howells bp[4] = htonl(upper_32_bits(req->pos)); 506196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->pos)); 507b9b1f8d5SDavid Howells bp[6] = 0; 508196ee9cdSDavid Howells bp[7] = htonl(lower_32_bits(req->len)); 509b9b1f8d5SDavid Howells 510d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 511025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 51220b8391fSDavid Howells afs_set_fc_call(call, fc); 5130b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5140b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 515b9b1f8d5SDavid Howells } 516b9b1f8d5SDavid Howells 51708e0e7c8SDavid Howells /* 51808e0e7c8SDavid Howells * fetch data from a file 51908e0e7c8SDavid Howells */ 520a58823acSDavid Howells int afs_fs_fetch_data(struct afs_fs_cursor *fc, 521a58823acSDavid Howells struct afs_status_cb *scb, 522a58823acSDavid Howells struct afs_read *req) 5231da177e4SLinus Torvalds { 524d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 52508e0e7c8SDavid Howells struct afs_call *call; 526f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 52708e0e7c8SDavid Howells __be32 *bp; 5281da177e4SLinus Torvalds 52930062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 530a58823acSDavid Howells return yfs_fs_fetch_data(fc, scb, req); 53130062bd1SDavid Howells 532196ee9cdSDavid Howells if (upper_32_bits(req->pos) || 533196ee9cdSDavid Howells upper_32_bits(req->len) || 534196ee9cdSDavid Howells upper_32_bits(req->pos + req->len)) 535a58823acSDavid Howells return afs_fs_fetch_data64(fc, scb, req); 536b9b1f8d5SDavid Howells 53708e0e7c8SDavid Howells _enter(""); 5381da177e4SLinus Torvalds 539f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4); 54008e0e7c8SDavid Howells if (!call) 54108e0e7c8SDavid Howells return -ENOMEM; 5421da177e4SLinus Torvalds 543d2ddc776SDavid Howells call->key = fc->key; 544a58823acSDavid Howells call->out_scb = scb; 545ffba718eSDavid Howells call->out_volsync = NULL; 546d4438a25SDavid Howells call->read_request = afs_get_read(req); 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds /* marshall the parameters */ 54908e0e7c8SDavid Howells bp = call->request; 55008e0e7c8SDavid Howells bp[0] = htonl(FSFETCHDATA); 55108e0e7c8SDavid Howells bp[1] = htonl(vnode->fid.vid); 55208e0e7c8SDavid Howells bp[2] = htonl(vnode->fid.vnode); 55308e0e7c8SDavid Howells bp[3] = htonl(vnode->fid.unique); 554196ee9cdSDavid Howells bp[4] = htonl(lower_32_bits(req->pos)); 555196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->len)); 5561da177e4SLinus Torvalds 557d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 558025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 55920b8391fSDavid Howells afs_set_fc_call(call, fc); 5600b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5610b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 56208e0e7c8SDavid Howells } 563260a9803SDavid Howells 564260a9803SDavid Howells /* 565260a9803SDavid Howells * deliver reply data to an FS.CreateFile or an FS.MakeDir 566260a9803SDavid Howells */ 567d001648eSDavid Howells static int afs_deliver_fs_create_vnode(struct afs_call *call) 568260a9803SDavid Howells { 569260a9803SDavid Howells const __be32 *bp; 570372ee163SDavid Howells int ret; 571260a9803SDavid Howells 572d001648eSDavid Howells ret = afs_transfer_reply(call); 573372ee163SDavid Howells if (ret < 0) 574372ee163SDavid Howells return ret; 575260a9803SDavid Howells 576260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 577260a9803SDavid Howells bp = call->buffer; 578ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 579a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 580160cb957SDavid Howells if (ret < 0) 581160cb957SDavid Howells return ret; 582a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 583160cb957SDavid Howells if (ret < 0) 584160cb957SDavid Howells return ret; 585a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 586ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 587260a9803SDavid Howells 588260a9803SDavid Howells _leave(" = 0 [done]"); 589260a9803SDavid Howells return 0; 590260a9803SDavid Howells } 591260a9803SDavid Howells 592260a9803SDavid Howells /* 593260a9803SDavid Howells * FS.CreateFile and FS.MakeDir operation type 594260a9803SDavid Howells */ 595025db80cSDavid Howells static const struct afs_call_type afs_RXFSCreateFile = { 596025db80cSDavid Howells .name = "FS.CreateFile", 597025db80cSDavid Howells .op = afs_FS_CreateFile, 598025db80cSDavid Howells .deliver = afs_deliver_fs_create_vnode, 599025db80cSDavid Howells .destructor = afs_flat_call_destructor, 600025db80cSDavid Howells }; 601025db80cSDavid Howells 602025db80cSDavid Howells static const struct afs_call_type afs_RXFSMakeDir = { 603025db80cSDavid Howells .name = "FS.MakeDir", 604025db80cSDavid Howells .op = afs_FS_MakeDir, 605260a9803SDavid Howells .deliver = afs_deliver_fs_create_vnode, 606260a9803SDavid Howells .destructor = afs_flat_call_destructor, 607260a9803SDavid Howells }; 608260a9803SDavid Howells 609260a9803SDavid Howells /* 610260a9803SDavid Howells * create a file or make a directory 611260a9803SDavid Howells */ 6128b2a464cSDavid Howells int afs_fs_create(struct afs_fs_cursor *fc, 613260a9803SDavid Howells const char *name, 614260a9803SDavid Howells umode_t mode, 615a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 616260a9803SDavid Howells struct afs_fid *newfid, 617a58823acSDavid Howells struct afs_status_cb *new_scb) 618260a9803SDavid Howells { 619ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 620260a9803SDavid Howells struct afs_call *call; 621ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 622260a9803SDavid Howells size_t namesz, reqsz, padsz; 623260a9803SDavid Howells __be32 *bp; 624260a9803SDavid Howells 62530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){ 62630062bd1SDavid Howells if (S_ISDIR(mode)) 627a58823acSDavid Howells return yfs_fs_make_dir(fc, name, mode, dvnode_scb, 628a58823acSDavid Howells newfid, new_scb); 62930062bd1SDavid Howells else 630a58823acSDavid Howells return yfs_fs_create_file(fc, name, mode, dvnode_scb, 631a58823acSDavid Howells newfid, new_scb); 63230062bd1SDavid Howells } 63330062bd1SDavid Howells 634260a9803SDavid Howells _enter(""); 635260a9803SDavid Howells 636260a9803SDavid Howells namesz = strlen(name); 637260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 638260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (6 * 4); 639260a9803SDavid Howells 640025db80cSDavid Howells call = afs_alloc_flat_call( 641025db80cSDavid Howells net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile, 642025db80cSDavid Howells reqsz, (3 + 21 + 21 + 3 + 6) * 4); 643260a9803SDavid Howells if (!call) 644260a9803SDavid Howells return -ENOMEM; 645260a9803SDavid Howells 646d2ddc776SDavid Howells call->key = fc->key; 647a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 648ffba718eSDavid Howells call->out_fid = newfid; 649a58823acSDavid Howells call->out_scb = new_scb; 650260a9803SDavid Howells 651260a9803SDavid Howells /* marshall the parameters */ 652260a9803SDavid Howells bp = call->request; 653260a9803SDavid Howells *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); 654ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 655ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 656ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 657260a9803SDavid Howells *bp++ = htonl(namesz); 658260a9803SDavid Howells memcpy(bp, name, namesz); 659260a9803SDavid Howells bp = (void *) bp + namesz; 660260a9803SDavid Howells if (padsz > 0) { 661260a9803SDavid Howells memset(bp, 0, padsz); 662260a9803SDavid Howells bp = (void *) bp + padsz; 663260a9803SDavid Howells } 664ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 665ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 666260a9803SDavid Howells *bp++ = 0; /* owner */ 667260a9803SDavid Howells *bp++ = 0; /* group */ 668260a9803SDavid Howells *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ 669260a9803SDavid Howells *bp++ = 0; /* segment size */ 670260a9803SDavid Howells 671d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 672ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 67320b8391fSDavid Howells afs_set_fc_call(call, fc); 6740b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 6750b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 676260a9803SDavid Howells } 677260a9803SDavid Howells 678260a9803SDavid Howells /* 679ffba718eSDavid Howells * Deliver reply data to any operation that returns directory status and volume 680b10494afSJoe Gorse * sync. 681260a9803SDavid Howells */ 682ffba718eSDavid Howells static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call) 683260a9803SDavid Howells { 684260a9803SDavid Howells const __be32 *bp; 685372ee163SDavid Howells int ret; 686260a9803SDavid Howells 687d001648eSDavid Howells ret = afs_transfer_reply(call); 688372ee163SDavid Howells if (ret < 0) 689372ee163SDavid Howells return ret; 690260a9803SDavid Howells 691260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 692260a9803SDavid Howells bp = call->buffer; 693a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 694160cb957SDavid Howells if (ret < 0) 695160cb957SDavid Howells return ret; 696ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 697260a9803SDavid Howells 698260a9803SDavid Howells _leave(" = 0 [done]"); 699260a9803SDavid Howells return 0; 700260a9803SDavid Howells } 701260a9803SDavid Howells 702260a9803SDavid Howells /* 703260a9803SDavid Howells * FS.RemoveDir/FS.RemoveFile operation type 704260a9803SDavid Howells */ 705025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveFile = { 706025db80cSDavid Howells .name = "FS.RemoveFile", 707025db80cSDavid Howells .op = afs_FS_RemoveFile, 708ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 709025db80cSDavid Howells .destructor = afs_flat_call_destructor, 710025db80cSDavid Howells }; 711025db80cSDavid Howells 712025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveDir = { 713025db80cSDavid Howells .name = "FS.RemoveDir", 714025db80cSDavid Howells .op = afs_FS_RemoveDir, 715ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 716260a9803SDavid Howells .destructor = afs_flat_call_destructor, 717260a9803SDavid Howells }; 718260a9803SDavid Howells 719260a9803SDavid Howells /* 720260a9803SDavid Howells * remove a file or directory 721260a9803SDavid Howells */ 72230062bd1SDavid Howells int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 723a58823acSDavid Howells const char *name, bool isdir, struct afs_status_cb *dvnode_scb) 724260a9803SDavid Howells { 72530062bd1SDavid Howells struct afs_vnode *dvnode = fc->vnode; 726260a9803SDavid Howells struct afs_call *call; 72730062bd1SDavid Howells struct afs_net *net = afs_v2net(dvnode); 728260a9803SDavid Howells size_t namesz, reqsz, padsz; 729260a9803SDavid Howells __be32 *bp; 730260a9803SDavid Howells 73130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 732a58823acSDavid Howells return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb); 73330062bd1SDavid Howells 734260a9803SDavid Howells _enter(""); 735260a9803SDavid Howells 736260a9803SDavid Howells namesz = strlen(name); 737260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 738260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz; 739260a9803SDavid Howells 740025db80cSDavid Howells call = afs_alloc_flat_call( 741025db80cSDavid Howells net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile, 742025db80cSDavid Howells reqsz, (21 + 6) * 4); 743260a9803SDavid Howells if (!call) 744260a9803SDavid Howells return -ENOMEM; 745260a9803SDavid Howells 746d2ddc776SDavid Howells call->key = fc->key; 747a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 748260a9803SDavid Howells 749260a9803SDavid Howells /* marshall the parameters */ 750260a9803SDavid Howells bp = call->request; 751260a9803SDavid Howells *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); 75230062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vid); 75330062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 75430062bd1SDavid Howells *bp++ = htonl(dvnode->fid.unique); 755260a9803SDavid Howells *bp++ = htonl(namesz); 756260a9803SDavid Howells memcpy(bp, name, namesz); 757260a9803SDavid Howells bp = (void *) bp + namesz; 758260a9803SDavid Howells if (padsz > 0) { 759260a9803SDavid Howells memset(bp, 0, padsz); 760260a9803SDavid Howells bp = (void *) bp + padsz; 761260a9803SDavid Howells } 762260a9803SDavid Howells 763d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 76480548b03SDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 76520b8391fSDavid Howells afs_set_fc_call(call, fc); 7660b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 7670b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 768260a9803SDavid Howells } 769260a9803SDavid Howells 770260a9803SDavid Howells /* 771260a9803SDavid Howells * deliver reply data to an FS.Link 772260a9803SDavid Howells */ 773d001648eSDavid Howells static int afs_deliver_fs_link(struct afs_call *call) 774260a9803SDavid Howells { 775260a9803SDavid Howells const __be32 *bp; 776372ee163SDavid Howells int ret; 777260a9803SDavid Howells 778d001648eSDavid Howells _enter("{%u}", call->unmarshall); 779260a9803SDavid Howells 780d001648eSDavid Howells ret = afs_transfer_reply(call); 781372ee163SDavid Howells if (ret < 0) 782372ee163SDavid Howells return ret; 783260a9803SDavid Howells 784260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 785260a9803SDavid Howells bp = call->buffer; 786a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 787160cb957SDavid Howells if (ret < 0) 788160cb957SDavid Howells return ret; 789a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 790160cb957SDavid Howells if (ret < 0) 791160cb957SDavid Howells return ret; 792ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 793260a9803SDavid Howells 794260a9803SDavid Howells _leave(" = 0 [done]"); 795260a9803SDavid Howells return 0; 796260a9803SDavid Howells } 797260a9803SDavid Howells 798260a9803SDavid Howells /* 799260a9803SDavid Howells * FS.Link operation type 800260a9803SDavid Howells */ 801260a9803SDavid Howells static const struct afs_call_type afs_RXFSLink = { 802260a9803SDavid Howells .name = "FS.Link", 803025db80cSDavid Howells .op = afs_FS_Link, 804260a9803SDavid Howells .deliver = afs_deliver_fs_link, 805260a9803SDavid Howells .destructor = afs_flat_call_destructor, 806260a9803SDavid Howells }; 807260a9803SDavid Howells 808260a9803SDavid Howells /* 809260a9803SDavid Howells * make a hard link 810260a9803SDavid Howells */ 811d2ddc776SDavid Howells int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 812a58823acSDavid Howells const char *name, 813a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 814a58823acSDavid Howells struct afs_status_cb *vnode_scb) 815260a9803SDavid Howells { 816d2ddc776SDavid Howells struct afs_vnode *dvnode = fc->vnode; 817260a9803SDavid Howells struct afs_call *call; 818f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 819260a9803SDavid Howells size_t namesz, reqsz, padsz; 820260a9803SDavid Howells __be32 *bp; 821260a9803SDavid Howells 82230062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 823a58823acSDavid Howells return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb); 82430062bd1SDavid Howells 825260a9803SDavid Howells _enter(""); 826260a9803SDavid Howells 827260a9803SDavid Howells namesz = strlen(name); 828260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 829260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (3 * 4); 830260a9803SDavid Howells 831f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4); 832260a9803SDavid Howells if (!call) 833260a9803SDavid Howells return -ENOMEM; 834260a9803SDavid Howells 835d2ddc776SDavid Howells call->key = fc->key; 836a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 837a58823acSDavid Howells call->out_scb = vnode_scb; 838260a9803SDavid Howells 839260a9803SDavid Howells /* marshall the parameters */ 840260a9803SDavid Howells bp = call->request; 841260a9803SDavid Howells *bp++ = htonl(FSLINK); 842260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vid); 843260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 844260a9803SDavid Howells *bp++ = htonl(dvnode->fid.unique); 845260a9803SDavid Howells *bp++ = htonl(namesz); 846260a9803SDavid Howells memcpy(bp, name, namesz); 847260a9803SDavid Howells bp = (void *) bp + namesz; 848260a9803SDavid Howells if (padsz > 0) { 849260a9803SDavid Howells memset(bp, 0, padsz); 850260a9803SDavid Howells bp = (void *) bp + padsz; 851260a9803SDavid Howells } 852260a9803SDavid Howells *bp++ = htonl(vnode->fid.vid); 853260a9803SDavid Howells *bp++ = htonl(vnode->fid.vnode); 854260a9803SDavid Howells *bp++ = htonl(vnode->fid.unique); 855260a9803SDavid Howells 856d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 85780548b03SDavid Howells trace_afs_make_fs_call1(call, &vnode->fid, name); 85820b8391fSDavid Howells afs_set_fc_call(call, fc); 8590b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 8600b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 861260a9803SDavid Howells } 862260a9803SDavid Howells 863260a9803SDavid Howells /* 864260a9803SDavid Howells * deliver reply data to an FS.Symlink 865260a9803SDavid Howells */ 866d001648eSDavid Howells static int afs_deliver_fs_symlink(struct afs_call *call) 867260a9803SDavid Howells { 868260a9803SDavid Howells const __be32 *bp; 869372ee163SDavid Howells int ret; 870260a9803SDavid Howells 871d001648eSDavid Howells _enter("{%u}", call->unmarshall); 872260a9803SDavid Howells 873d001648eSDavid Howells ret = afs_transfer_reply(call); 874372ee163SDavid Howells if (ret < 0) 875372ee163SDavid Howells return ret; 876260a9803SDavid Howells 877260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 878260a9803SDavid Howells bp = call->buffer; 879ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 880a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 881160cb957SDavid Howells if (ret < 0) 882160cb957SDavid Howells return ret; 883a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 884160cb957SDavid Howells if (ret < 0) 885160cb957SDavid Howells return ret; 886ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 887260a9803SDavid Howells 888260a9803SDavid Howells _leave(" = 0 [done]"); 889260a9803SDavid Howells return 0; 890260a9803SDavid Howells } 891260a9803SDavid Howells 892260a9803SDavid Howells /* 893260a9803SDavid Howells * FS.Symlink operation type 894260a9803SDavid Howells */ 895260a9803SDavid Howells static const struct afs_call_type afs_RXFSSymlink = { 896260a9803SDavid Howells .name = "FS.Symlink", 897025db80cSDavid Howells .op = afs_FS_Symlink, 898260a9803SDavid Howells .deliver = afs_deliver_fs_symlink, 899260a9803SDavid Howells .destructor = afs_flat_call_destructor, 900260a9803SDavid Howells }; 901260a9803SDavid Howells 902260a9803SDavid Howells /* 903260a9803SDavid Howells * create a symbolic link 904260a9803SDavid Howells */ 9058b2a464cSDavid Howells int afs_fs_symlink(struct afs_fs_cursor *fc, 906260a9803SDavid Howells const char *name, 907260a9803SDavid Howells const char *contents, 908a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 909260a9803SDavid Howells struct afs_fid *newfid, 910a58823acSDavid Howells struct afs_status_cb *new_scb) 911260a9803SDavid Howells { 912ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 913260a9803SDavid Howells struct afs_call *call; 914ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 915260a9803SDavid Howells size_t namesz, reqsz, padsz, c_namesz, c_padsz; 916260a9803SDavid Howells __be32 *bp; 917260a9803SDavid Howells 91830062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 919a58823acSDavid Howells return yfs_fs_symlink(fc, name, contents, dvnode_scb, 920a58823acSDavid Howells newfid, new_scb); 92130062bd1SDavid Howells 922260a9803SDavid Howells _enter(""); 923260a9803SDavid Howells 924260a9803SDavid Howells namesz = strlen(name); 925260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 926260a9803SDavid Howells 927260a9803SDavid Howells c_namesz = strlen(contents); 928260a9803SDavid Howells c_padsz = (4 - (c_namesz & 3)) & 3; 929260a9803SDavid Howells 930260a9803SDavid Howells reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4); 931260a9803SDavid Howells 932f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz, 933260a9803SDavid Howells (3 + 21 + 21 + 6) * 4); 934260a9803SDavid Howells if (!call) 935260a9803SDavid Howells return -ENOMEM; 936260a9803SDavid Howells 937d2ddc776SDavid Howells call->key = fc->key; 938a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 939ffba718eSDavid Howells call->out_fid = newfid; 940a58823acSDavid Howells call->out_scb = new_scb; 941260a9803SDavid Howells 942260a9803SDavid Howells /* marshall the parameters */ 943260a9803SDavid Howells bp = call->request; 944260a9803SDavid Howells *bp++ = htonl(FSSYMLINK); 945ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 946ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 947ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 948260a9803SDavid Howells *bp++ = htonl(namesz); 949260a9803SDavid Howells memcpy(bp, name, namesz); 950260a9803SDavid Howells bp = (void *) bp + namesz; 951260a9803SDavid Howells if (padsz > 0) { 952260a9803SDavid Howells memset(bp, 0, padsz); 953260a9803SDavid Howells bp = (void *) bp + padsz; 954260a9803SDavid Howells } 955260a9803SDavid Howells *bp++ = htonl(c_namesz); 956260a9803SDavid Howells memcpy(bp, contents, c_namesz); 957260a9803SDavid Howells bp = (void *) bp + c_namesz; 958260a9803SDavid Howells if (c_padsz > 0) { 959260a9803SDavid Howells memset(bp, 0, c_padsz); 960260a9803SDavid Howells bp = (void *) bp + c_padsz; 961260a9803SDavid Howells } 962ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 963ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 964260a9803SDavid Howells *bp++ = 0; /* owner */ 965260a9803SDavid Howells *bp++ = 0; /* group */ 966260a9803SDavid Howells *bp++ = htonl(S_IRWXUGO); /* unix mode */ 967260a9803SDavid Howells *bp++ = 0; /* segment size */ 968260a9803SDavid Howells 969d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 970ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 97120b8391fSDavid Howells afs_set_fc_call(call, fc); 9720b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 9730b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 974260a9803SDavid Howells } 975260a9803SDavid Howells 976260a9803SDavid Howells /* 977260a9803SDavid Howells * deliver reply data to an FS.Rename 978260a9803SDavid Howells */ 979d001648eSDavid Howells static int afs_deliver_fs_rename(struct afs_call *call) 980260a9803SDavid Howells { 981260a9803SDavid Howells const __be32 *bp; 982372ee163SDavid Howells int ret; 983260a9803SDavid Howells 984d001648eSDavid Howells ret = afs_transfer_reply(call); 985372ee163SDavid Howells if (ret < 0) 986372ee163SDavid Howells return ret; 987260a9803SDavid Howells 988260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 989260a9803SDavid Howells bp = call->buffer; 990a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 991160cb957SDavid Howells if (ret < 0) 992160cb957SDavid Howells return ret; 993a58823acSDavid Howells if (call->out_dir_scb != call->out_scb) { 994a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 995160cb957SDavid Howells if (ret < 0) 996160cb957SDavid Howells return ret; 997160cb957SDavid Howells } 998ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 999260a9803SDavid Howells 1000260a9803SDavid Howells _leave(" = 0 [done]"); 1001260a9803SDavid Howells return 0; 1002260a9803SDavid Howells } 1003260a9803SDavid Howells 1004260a9803SDavid Howells /* 1005260a9803SDavid Howells * FS.Rename operation type 1006260a9803SDavid Howells */ 1007260a9803SDavid Howells static const struct afs_call_type afs_RXFSRename = { 1008260a9803SDavid Howells .name = "FS.Rename", 1009025db80cSDavid Howells .op = afs_FS_Rename, 1010260a9803SDavid Howells .deliver = afs_deliver_fs_rename, 1011260a9803SDavid Howells .destructor = afs_flat_call_destructor, 1012260a9803SDavid Howells }; 1013260a9803SDavid Howells 1014260a9803SDavid Howells /* 1015a58823acSDavid Howells * Rename/move a file or directory. 1016260a9803SDavid Howells */ 10178b2a464cSDavid Howells int afs_fs_rename(struct afs_fs_cursor *fc, 1018260a9803SDavid Howells const char *orig_name, 1019260a9803SDavid Howells struct afs_vnode *new_dvnode, 102063a4681fSDavid Howells const char *new_name, 1021a58823acSDavid Howells struct afs_status_cb *orig_dvnode_scb, 1022a58823acSDavid Howells struct afs_status_cb *new_dvnode_scb) 1023260a9803SDavid Howells { 1024d2ddc776SDavid Howells struct afs_vnode *orig_dvnode = fc->vnode; 1025260a9803SDavid Howells struct afs_call *call; 1026f044c884SDavid Howells struct afs_net *net = afs_v2net(orig_dvnode); 1027260a9803SDavid Howells size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; 1028260a9803SDavid Howells __be32 *bp; 1029260a9803SDavid Howells 103030062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 103130062bd1SDavid Howells return yfs_fs_rename(fc, orig_name, 103230062bd1SDavid Howells new_dvnode, new_name, 1033a58823acSDavid Howells orig_dvnode_scb, 1034a58823acSDavid Howells new_dvnode_scb); 103530062bd1SDavid Howells 1036260a9803SDavid Howells _enter(""); 1037260a9803SDavid Howells 1038260a9803SDavid Howells o_namesz = strlen(orig_name); 1039260a9803SDavid Howells o_padsz = (4 - (o_namesz & 3)) & 3; 1040260a9803SDavid Howells 1041260a9803SDavid Howells n_namesz = strlen(new_name); 1042260a9803SDavid Howells n_padsz = (4 - (n_namesz & 3)) & 3; 1043260a9803SDavid Howells 1044260a9803SDavid Howells reqsz = (4 * 4) + 1045260a9803SDavid Howells 4 + o_namesz + o_padsz + 1046260a9803SDavid Howells (3 * 4) + 1047260a9803SDavid Howells 4 + n_namesz + n_padsz; 1048260a9803SDavid Howells 1049f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4); 1050260a9803SDavid Howells if (!call) 1051260a9803SDavid Howells return -ENOMEM; 1052260a9803SDavid Howells 1053d2ddc776SDavid Howells call->key = fc->key; 1054a58823acSDavid Howells call->out_dir_scb = orig_dvnode_scb; 1055a58823acSDavid Howells call->out_scb = new_dvnode_scb; 1056260a9803SDavid Howells 1057260a9803SDavid Howells /* marshall the parameters */ 1058260a9803SDavid Howells bp = call->request; 1059260a9803SDavid Howells *bp++ = htonl(FSRENAME); 1060260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vid); 1061260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vnode); 1062260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.unique); 1063260a9803SDavid Howells *bp++ = htonl(o_namesz); 1064260a9803SDavid Howells memcpy(bp, orig_name, o_namesz); 1065260a9803SDavid Howells bp = (void *) bp + o_namesz; 1066260a9803SDavid Howells if (o_padsz > 0) { 1067260a9803SDavid Howells memset(bp, 0, o_padsz); 1068260a9803SDavid Howells bp = (void *) bp + o_padsz; 1069260a9803SDavid Howells } 1070260a9803SDavid Howells 1071260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vid); 1072260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vnode); 1073260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.unique); 1074260a9803SDavid Howells *bp++ = htonl(n_namesz); 1075260a9803SDavid Howells memcpy(bp, new_name, n_namesz); 1076260a9803SDavid Howells bp = (void *) bp + n_namesz; 1077260a9803SDavid Howells if (n_padsz > 0) { 1078260a9803SDavid Howells memset(bp, 0, n_padsz); 1079260a9803SDavid Howells bp = (void *) bp + n_padsz; 1080260a9803SDavid Howells } 1081260a9803SDavid Howells 1082d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 108380548b03SDavid Howells trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name); 108420b8391fSDavid Howells afs_set_fc_call(call, fc); 10850b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 10860b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1087260a9803SDavid Howells } 108831143d5dSDavid Howells 108931143d5dSDavid Howells /* 109031143d5dSDavid Howells * deliver reply data to an FS.StoreData 109131143d5dSDavid Howells */ 1092d001648eSDavid Howells static int afs_deliver_fs_store_data(struct afs_call *call) 109331143d5dSDavid Howells { 109431143d5dSDavid Howells const __be32 *bp; 1095372ee163SDavid Howells int ret; 109631143d5dSDavid Howells 1097d001648eSDavid Howells _enter(""); 109831143d5dSDavid Howells 1099d001648eSDavid Howells ret = afs_transfer_reply(call); 1100372ee163SDavid Howells if (ret < 0) 1101372ee163SDavid Howells return ret; 110231143d5dSDavid Howells 110331143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 110431143d5dSDavid Howells bp = call->buffer; 1105a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1106160cb957SDavid Howells if (ret < 0) 1107160cb957SDavid Howells return ret; 1108ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 110931143d5dSDavid Howells 111031143d5dSDavid Howells _leave(" = 0 [done]"); 111131143d5dSDavid Howells return 0; 111231143d5dSDavid Howells } 111331143d5dSDavid Howells 111431143d5dSDavid Howells /* 111531143d5dSDavid Howells * FS.StoreData operation type 111631143d5dSDavid Howells */ 111731143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData = { 111831143d5dSDavid Howells .name = "FS.StoreData", 1119025db80cSDavid Howells .op = afs_FS_StoreData, 112031143d5dSDavid Howells .deliver = afs_deliver_fs_store_data, 112131143d5dSDavid Howells .destructor = afs_flat_call_destructor, 112231143d5dSDavid Howells }; 112331143d5dSDavid Howells 1124b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64 = { 1125b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1126025db80cSDavid Howells .op = afs_FS_StoreData64, 1127b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_data, 1128b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1129b9b1f8d5SDavid Howells }; 1130b9b1f8d5SDavid Howells 1131b9b1f8d5SDavid Howells /* 1132b9b1f8d5SDavid Howells * store a set of pages to a very large file 1133b9b1f8d5SDavid Howells */ 11348b2a464cSDavid Howells static int afs_fs_store_data64(struct afs_fs_cursor *fc, 11354343d008SDavid Howells struct address_space *mapping, 1136b9b1f8d5SDavid Howells pgoff_t first, pgoff_t last, 1137b9b1f8d5SDavid Howells unsigned offset, unsigned to, 1138a58823acSDavid Howells loff_t size, loff_t pos, loff_t i_size, 1139a58823acSDavid Howells struct afs_status_cb *scb) 1140b9b1f8d5SDavid Howells { 11414343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 1142b9b1f8d5SDavid Howells struct afs_call *call; 1143f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1144b9b1f8d5SDavid Howells __be32 *bp; 1145b9b1f8d5SDavid Howells 11463b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 11474343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1148b9b1f8d5SDavid Howells 1149f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64, 1150b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1151b9b1f8d5SDavid Howells (21 + 6) * 4); 1152b9b1f8d5SDavid Howells if (!call) 1153b9b1f8d5SDavid Howells return -ENOMEM; 1154b9b1f8d5SDavid Howells 11554343d008SDavid Howells call->key = fc->key; 11564343d008SDavid Howells call->mapping = mapping; 1157b9b1f8d5SDavid Howells call->first = first; 1158b9b1f8d5SDavid Howells call->last = last; 1159b9b1f8d5SDavid Howells call->first_offset = offset; 1160b9b1f8d5SDavid Howells call->last_to = to; 1161b9b1f8d5SDavid Howells call->send_pages = true; 1162a58823acSDavid Howells call->out_scb = scb; 1163b9b1f8d5SDavid Howells 1164b9b1f8d5SDavid Howells /* marshall the parameters */ 1165b9b1f8d5SDavid Howells bp = call->request; 1166b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1167b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1168b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1169b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1170b9b1f8d5SDavid Howells 1171ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1172ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 1173b9b1f8d5SDavid Howells *bp++ = 0; /* owner */ 1174b9b1f8d5SDavid Howells *bp++ = 0; /* group */ 1175b9b1f8d5SDavid Howells *bp++ = 0; /* unix mode */ 1176b9b1f8d5SDavid Howells *bp++ = 0; /* segment size */ 1177b9b1f8d5SDavid Howells 1178b9b1f8d5SDavid Howells *bp++ = htonl(pos >> 32); 1179b9b1f8d5SDavid Howells *bp++ = htonl((u32) pos); 1180b9b1f8d5SDavid Howells *bp++ = htonl(size >> 32); 1181b9b1f8d5SDavid Howells *bp++ = htonl((u32) size); 1182b9b1f8d5SDavid Howells *bp++ = htonl(i_size >> 32); 1183b9b1f8d5SDavid Howells *bp++ = htonl((u32) i_size); 1184b9b1f8d5SDavid Howells 1185025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 118620b8391fSDavid Howells afs_set_fc_call(call, fc); 11870b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 11880b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1189b9b1f8d5SDavid Howells } 1190b9b1f8d5SDavid Howells 119131143d5dSDavid Howells /* 119231143d5dSDavid Howells * store a set of pages 119331143d5dSDavid Howells */ 11944343d008SDavid Howells int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, 119531143d5dSDavid Howells pgoff_t first, pgoff_t last, 1196a58823acSDavid Howells unsigned offset, unsigned to, 1197a58823acSDavid Howells struct afs_status_cb *scb) 119831143d5dSDavid Howells { 11994343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 120031143d5dSDavid Howells struct afs_call *call; 1201f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 120231143d5dSDavid Howells loff_t size, pos, i_size; 120331143d5dSDavid Howells __be32 *bp; 120431143d5dSDavid Howells 120530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1206a58823acSDavid Howells return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb); 120730062bd1SDavid Howells 12083b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 12094343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 121031143d5dSDavid Howells 1211146a1192SDavid Howells size = (loff_t)to - (loff_t)offset; 121231143d5dSDavid Howells if (first != last) 121331143d5dSDavid Howells size += (loff_t)(last - first) << PAGE_SHIFT; 121431143d5dSDavid Howells pos = (loff_t)first << PAGE_SHIFT; 121531143d5dSDavid Howells pos += offset; 121631143d5dSDavid Howells 121731143d5dSDavid Howells i_size = i_size_read(&vnode->vfs_inode); 121831143d5dSDavid Howells if (pos + size > i_size) 121931143d5dSDavid Howells i_size = size + pos; 122031143d5dSDavid Howells 122131143d5dSDavid Howells _debug("size %llx, at %llx, i_size %llx", 122231143d5dSDavid Howells (unsigned long long) size, (unsigned long long) pos, 122331143d5dSDavid Howells (unsigned long long) i_size); 122431143d5dSDavid Howells 1225b9b1f8d5SDavid Howells if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32) 12264343d008SDavid Howells return afs_fs_store_data64(fc, mapping, first, last, offset, to, 1227a58823acSDavid Howells size, pos, i_size, scb); 122831143d5dSDavid Howells 1229f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData, 123031143d5dSDavid Howells (4 + 6 + 3) * 4, 123131143d5dSDavid Howells (21 + 6) * 4); 123231143d5dSDavid Howells if (!call) 123331143d5dSDavid Howells return -ENOMEM; 123431143d5dSDavid Howells 12354343d008SDavid Howells call->key = fc->key; 12364343d008SDavid Howells call->mapping = mapping; 123731143d5dSDavid Howells call->first = first; 123831143d5dSDavid Howells call->last = last; 123931143d5dSDavid Howells call->first_offset = offset; 124031143d5dSDavid Howells call->last_to = to; 124131143d5dSDavid Howells call->send_pages = true; 1242a58823acSDavid Howells call->out_scb = scb; 124331143d5dSDavid Howells 124431143d5dSDavid Howells /* marshall the parameters */ 124531143d5dSDavid Howells bp = call->request; 124631143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 124731143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 124831143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 124931143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 125031143d5dSDavid Howells 1251ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1252ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 125331143d5dSDavid Howells *bp++ = 0; /* owner */ 125431143d5dSDavid Howells *bp++ = 0; /* group */ 125531143d5dSDavid Howells *bp++ = 0; /* unix mode */ 125631143d5dSDavid Howells *bp++ = 0; /* segment size */ 125731143d5dSDavid Howells 125831143d5dSDavid Howells *bp++ = htonl(pos); 125931143d5dSDavid Howells *bp++ = htonl(size); 126031143d5dSDavid Howells *bp++ = htonl(i_size); 126131143d5dSDavid Howells 1262d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1263025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 126420b8391fSDavid Howells afs_set_fc_call(call, fc); 12650b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 12660b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 126731143d5dSDavid Howells } 126831143d5dSDavid Howells 126931143d5dSDavid Howells /* 127031143d5dSDavid Howells * deliver reply data to an FS.StoreStatus 127131143d5dSDavid Howells */ 1272d001648eSDavid Howells static int afs_deliver_fs_store_status(struct afs_call *call) 127331143d5dSDavid Howells { 127431143d5dSDavid Howells const __be32 *bp; 1275372ee163SDavid Howells int ret; 127631143d5dSDavid Howells 1277d001648eSDavid Howells _enter(""); 127831143d5dSDavid Howells 1279d001648eSDavid Howells ret = afs_transfer_reply(call); 1280372ee163SDavid Howells if (ret < 0) 1281372ee163SDavid Howells return ret; 128231143d5dSDavid Howells 128331143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 128431143d5dSDavid Howells bp = call->buffer; 1285a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1286160cb957SDavid Howells if (ret < 0) 1287160cb957SDavid Howells return ret; 1288ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 128931143d5dSDavid Howells 129031143d5dSDavid Howells _leave(" = 0 [done]"); 129131143d5dSDavid Howells return 0; 129231143d5dSDavid Howells } 129331143d5dSDavid Howells 129431143d5dSDavid Howells /* 129531143d5dSDavid Howells * FS.StoreStatus operation type 129631143d5dSDavid Howells */ 129731143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreStatus = { 129831143d5dSDavid Howells .name = "FS.StoreStatus", 1299025db80cSDavid Howells .op = afs_FS_StoreStatus, 130031143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 130131143d5dSDavid Howells .destructor = afs_flat_call_destructor, 130231143d5dSDavid Howells }; 130331143d5dSDavid Howells 130431143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData_as_Status = { 130531143d5dSDavid Howells .name = "FS.StoreData", 1306025db80cSDavid Howells .op = afs_FS_StoreData, 130731143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 130831143d5dSDavid Howells .destructor = afs_flat_call_destructor, 130931143d5dSDavid Howells }; 131031143d5dSDavid Howells 1311b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64_as_Status = { 1312b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1313025db80cSDavid Howells .op = afs_FS_StoreData64, 1314b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_status, 1315b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1316b9b1f8d5SDavid Howells }; 1317b9b1f8d5SDavid Howells 1318b9b1f8d5SDavid Howells /* 1319b9b1f8d5SDavid Howells * set the attributes on a very large file, using FS.StoreData rather than 1320b9b1f8d5SDavid Howells * FS.StoreStatus so as to alter the file size also 1321b9b1f8d5SDavid Howells */ 1322a58823acSDavid Howells static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr, 1323a58823acSDavid Howells struct afs_status_cb *scb) 1324b9b1f8d5SDavid Howells { 1325d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1326b9b1f8d5SDavid Howells struct afs_call *call; 1327f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1328b9b1f8d5SDavid Howells __be32 *bp; 1329b9b1f8d5SDavid Howells 13303b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1331d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1332b9b1f8d5SDavid Howells 1333b9b1f8d5SDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1334b9b1f8d5SDavid Howells 1335f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status, 1336b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1337b9b1f8d5SDavid Howells (21 + 6) * 4); 1338b9b1f8d5SDavid Howells if (!call) 1339b9b1f8d5SDavid Howells return -ENOMEM; 1340b9b1f8d5SDavid Howells 1341d2ddc776SDavid Howells call->key = fc->key; 1342a58823acSDavid Howells call->out_scb = scb; 1343b9b1f8d5SDavid Howells 1344b9b1f8d5SDavid Howells /* marshall the parameters */ 1345b9b1f8d5SDavid Howells bp = call->request; 1346b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1347b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1348b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1349b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1350b9b1f8d5SDavid Howells 1351b9b1f8d5SDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 1352b9b1f8d5SDavid Howells 13538c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* position of start of write */ 13548c7ae38dSDavid Howells *bp++ = htonl((u32) attr->ia_size); 1355b9b1f8d5SDavid Howells *bp++ = 0; /* size of write */ 1356b9b1f8d5SDavid Howells *bp++ = 0; 1357b9b1f8d5SDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* new file length */ 1358b9b1f8d5SDavid Howells *bp++ = htonl((u32) attr->ia_size); 1359b9b1f8d5SDavid Howells 1360d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1361025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 136220b8391fSDavid Howells afs_set_fc_call(call, fc); 13630b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 13640b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1365b9b1f8d5SDavid Howells } 1366b9b1f8d5SDavid Howells 136731143d5dSDavid Howells /* 136831143d5dSDavid Howells * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus 136931143d5dSDavid Howells * so as to alter the file size also 137031143d5dSDavid Howells */ 1371a58823acSDavid Howells static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr, 1372a58823acSDavid Howells struct afs_status_cb *scb) 137331143d5dSDavid Howells { 1374d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 137531143d5dSDavid Howells struct afs_call *call; 1376f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 137731143d5dSDavid Howells __be32 *bp; 137831143d5dSDavid Howells 13793b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1380d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 138131143d5dSDavid Howells 138231143d5dSDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1383b9b1f8d5SDavid Howells if (attr->ia_size >> 32) 1384a58823acSDavid Howells return afs_fs_setattr_size64(fc, attr, scb); 138531143d5dSDavid Howells 1386f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status, 138731143d5dSDavid Howells (4 + 6 + 3) * 4, 138831143d5dSDavid Howells (21 + 6) * 4); 138931143d5dSDavid Howells if (!call) 139031143d5dSDavid Howells return -ENOMEM; 139131143d5dSDavid Howells 1392d2ddc776SDavid Howells call->key = fc->key; 1393a58823acSDavid Howells call->out_scb = scb; 139431143d5dSDavid Howells 139531143d5dSDavid Howells /* marshall the parameters */ 139631143d5dSDavid Howells bp = call->request; 139731143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 139831143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 139931143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 140031143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 140131143d5dSDavid Howells 140231143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 140331143d5dSDavid Howells 14048c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size); /* position of start of write */ 140531143d5dSDavid Howells *bp++ = 0; /* size of write */ 140631143d5dSDavid Howells *bp++ = htonl(attr->ia_size); /* new file length */ 140731143d5dSDavid Howells 1408d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1409025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 141020b8391fSDavid Howells afs_set_fc_call(call, fc); 14110b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14120b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 141331143d5dSDavid Howells } 141431143d5dSDavid Howells 141531143d5dSDavid Howells /* 141631143d5dSDavid Howells * set the attributes on a file, using FS.StoreData if there's a change in file 141731143d5dSDavid Howells * size, and FS.StoreStatus otherwise 141831143d5dSDavid Howells */ 1419a58823acSDavid Howells int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr, 1420a58823acSDavid Howells struct afs_status_cb *scb) 142131143d5dSDavid Howells { 1422d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 142331143d5dSDavid Howells struct afs_call *call; 1424f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 142531143d5dSDavid Howells __be32 *bp; 142631143d5dSDavid Howells 142730062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1428a58823acSDavid Howells return yfs_fs_setattr(fc, attr, scb); 142930062bd1SDavid Howells 143031143d5dSDavid Howells if (attr->ia_valid & ATTR_SIZE) 1431a58823acSDavid Howells return afs_fs_setattr_size(fc, attr, scb); 143231143d5dSDavid Howells 14333b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1434d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 143531143d5dSDavid Howells 1436f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus, 143731143d5dSDavid Howells (4 + 6) * 4, 143831143d5dSDavid Howells (21 + 6) * 4); 143931143d5dSDavid Howells if (!call) 144031143d5dSDavid Howells return -ENOMEM; 144131143d5dSDavid Howells 1442d2ddc776SDavid Howells call->key = fc->key; 1443a58823acSDavid Howells call->out_scb = scb; 144431143d5dSDavid Howells 144531143d5dSDavid Howells /* marshall the parameters */ 144631143d5dSDavid Howells bp = call->request; 144731143d5dSDavid Howells *bp++ = htonl(FSSTORESTATUS); 144831143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 144931143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 145031143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 145131143d5dSDavid Howells 145231143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 145331143d5dSDavid Howells 1454d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1455025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 145620b8391fSDavid Howells afs_set_fc_call(call, fc); 14570b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14580b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 145931143d5dSDavid Howells } 146045222b9eSDavid Howells 146145222b9eSDavid Howells /* 146245222b9eSDavid Howells * deliver reply data to an FS.GetVolumeStatus 146345222b9eSDavid Howells */ 1464d001648eSDavid Howells static int afs_deliver_fs_get_volume_status(struct afs_call *call) 146545222b9eSDavid Howells { 146645222b9eSDavid Howells const __be32 *bp; 146745222b9eSDavid Howells char *p; 146812bdcf33SDavid Howells u32 size; 146945222b9eSDavid Howells int ret; 147045222b9eSDavid Howells 1471d001648eSDavid Howells _enter("{%u}", call->unmarshall); 147245222b9eSDavid Howells 147345222b9eSDavid Howells switch (call->unmarshall) { 147445222b9eSDavid Howells case 0: 147545222b9eSDavid Howells call->unmarshall++; 147612bdcf33SDavid Howells afs_extract_to_buf(call, 12 * 4); 147729881608SGustavo A. R. Silva /* Fall through */ 147845222b9eSDavid Howells 147929881608SGustavo A. R. Silva /* extract the returned status record */ 148045222b9eSDavid Howells case 1: 148145222b9eSDavid Howells _debug("extract status"); 148212bdcf33SDavid Howells ret = afs_extract_data(call, true); 1483372ee163SDavid Howells if (ret < 0) 1484372ee163SDavid Howells return ret; 148545222b9eSDavid Howells 148645222b9eSDavid Howells bp = call->buffer; 1487ffba718eSDavid Howells xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus); 148845222b9eSDavid Howells call->unmarshall++; 148912bdcf33SDavid Howells afs_extract_to_tmp(call); 149029881608SGustavo A. R. Silva /* Fall through */ 149145222b9eSDavid Howells 149229881608SGustavo A. R. Silva /* extract the volume name length */ 149345222b9eSDavid Howells case 2: 149412bdcf33SDavid Howells ret = afs_extract_data(call, true); 1495372ee163SDavid Howells if (ret < 0) 1496372ee163SDavid Howells return ret; 149745222b9eSDavid Howells 149845222b9eSDavid Howells call->count = ntohl(call->tmp); 149945222b9eSDavid Howells _debug("volname length: %u", call->count); 150045222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1501160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1502160cb957SDavid Howells afs_eproto_volname_len); 150312bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1504ffba718eSDavid Howells afs_extract_to_buf(call, size); 150545222b9eSDavid Howells call->unmarshall++; 150629881608SGustavo A. R. Silva /* Fall through */ 150745222b9eSDavid Howells 150829881608SGustavo A. R. Silva /* extract the volume name */ 150945222b9eSDavid Howells case 3: 151045222b9eSDavid Howells _debug("extract volname"); 151112bdcf33SDavid Howells ret = afs_extract_data(call, true); 1512372ee163SDavid Howells if (ret < 0) 1513372ee163SDavid Howells return ret; 151445222b9eSDavid Howells 1515ffba718eSDavid Howells p = call->buffer; 151645222b9eSDavid Howells p[call->count] = 0; 151745222b9eSDavid Howells _debug("volname '%s'", p); 151812bdcf33SDavid Howells afs_extract_to_tmp(call); 151945222b9eSDavid Howells call->unmarshall++; 152029881608SGustavo A. R. Silva /* Fall through */ 152145222b9eSDavid Howells 152229881608SGustavo A. R. Silva /* extract the offline message length */ 152312bdcf33SDavid Howells case 4: 152412bdcf33SDavid Howells ret = afs_extract_data(call, true); 1525372ee163SDavid Howells if (ret < 0) 1526372ee163SDavid Howells return ret; 152745222b9eSDavid Howells 152845222b9eSDavid Howells call->count = ntohl(call->tmp); 152945222b9eSDavid Howells _debug("offline msg length: %u", call->count); 153045222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1531160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1532160cb957SDavid Howells afs_eproto_offline_msg_len); 153312bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1534ffba718eSDavid Howells afs_extract_to_buf(call, size); 153545222b9eSDavid Howells call->unmarshall++; 153629881608SGustavo A. R. Silva /* Fall through */ 153745222b9eSDavid Howells 153829881608SGustavo A. R. Silva /* extract the offline message */ 153912bdcf33SDavid Howells case 5: 154045222b9eSDavid Howells _debug("extract offline"); 154112bdcf33SDavid Howells ret = afs_extract_data(call, true); 1542372ee163SDavid Howells if (ret < 0) 1543372ee163SDavid Howells return ret; 154445222b9eSDavid Howells 1545ffba718eSDavid Howells p = call->buffer; 154645222b9eSDavid Howells p[call->count] = 0; 154745222b9eSDavid Howells _debug("offline '%s'", p); 154845222b9eSDavid Howells 154912bdcf33SDavid Howells afs_extract_to_tmp(call); 155045222b9eSDavid Howells call->unmarshall++; 155129881608SGustavo A. R. Silva /* Fall through */ 155245222b9eSDavid Howells 155329881608SGustavo A. R. Silva /* extract the message of the day length */ 155412bdcf33SDavid Howells case 6: 155512bdcf33SDavid Howells ret = afs_extract_data(call, true); 1556372ee163SDavid Howells if (ret < 0) 1557372ee163SDavid Howells return ret; 155845222b9eSDavid Howells 155945222b9eSDavid Howells call->count = ntohl(call->tmp); 156045222b9eSDavid Howells _debug("motd length: %u", call->count); 156145222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1562160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1563160cb957SDavid Howells afs_eproto_motd_len); 156412bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1565ffba718eSDavid Howells afs_extract_to_buf(call, size); 156645222b9eSDavid Howells call->unmarshall++; 156729881608SGustavo A. R. Silva /* Fall through */ 156845222b9eSDavid Howells 156929881608SGustavo A. R. Silva /* extract the message of the day */ 157012bdcf33SDavid Howells case 7: 157145222b9eSDavid Howells _debug("extract motd"); 157212bdcf33SDavid Howells ret = afs_extract_data(call, false); 1573372ee163SDavid Howells if (ret < 0) 1574372ee163SDavid Howells return ret; 157545222b9eSDavid Howells 1576ffba718eSDavid Howells p = call->buffer; 157745222b9eSDavid Howells p[call->count] = 0; 157845222b9eSDavid Howells _debug("motd '%s'", p); 157945222b9eSDavid Howells 158045222b9eSDavid Howells call->unmarshall++; 158145222b9eSDavid Howells 158212bdcf33SDavid Howells case 8: 158345222b9eSDavid Howells break; 158445222b9eSDavid Howells } 158545222b9eSDavid Howells 158645222b9eSDavid Howells _leave(" = 0 [done]"); 158745222b9eSDavid Howells return 0; 158845222b9eSDavid Howells } 158945222b9eSDavid Howells 159045222b9eSDavid Howells /* 159145222b9eSDavid Howells * FS.GetVolumeStatus operation type 159245222b9eSDavid Howells */ 159345222b9eSDavid Howells static const struct afs_call_type afs_RXFSGetVolumeStatus = { 159445222b9eSDavid Howells .name = "FS.GetVolumeStatus", 1595025db80cSDavid Howells .op = afs_FS_GetVolumeStatus, 159645222b9eSDavid Howells .deliver = afs_deliver_fs_get_volume_status, 1597ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 159845222b9eSDavid Howells }; 159945222b9eSDavid Howells 160045222b9eSDavid Howells /* 160145222b9eSDavid Howells * fetch the status of a volume 160245222b9eSDavid Howells */ 16038b2a464cSDavid Howells int afs_fs_get_volume_status(struct afs_fs_cursor *fc, 1604d2ddc776SDavid Howells struct afs_volume_status *vs) 160545222b9eSDavid Howells { 1606d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 160745222b9eSDavid Howells struct afs_call *call; 1608f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 160945222b9eSDavid Howells __be32 *bp; 161045222b9eSDavid Howells 161130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 161230062bd1SDavid Howells return yfs_fs_get_volume_status(fc, vs); 161330062bd1SDavid Howells 161445222b9eSDavid Howells _enter(""); 161545222b9eSDavid Howells 1616ffba718eSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 1617ffba718eSDavid Howells max(12 * 4, AFSOPAQUEMAX + 1)); 1618ffba718eSDavid Howells if (!call) 161945222b9eSDavid Howells return -ENOMEM; 162045222b9eSDavid Howells 1621d2ddc776SDavid Howells call->key = fc->key; 1622ffba718eSDavid Howells call->out_volstatus = vs; 162345222b9eSDavid Howells 162445222b9eSDavid Howells /* marshall the parameters */ 162545222b9eSDavid Howells bp = call->request; 162645222b9eSDavid Howells bp[0] = htonl(FSGETVOLUMESTATUS); 162745222b9eSDavid Howells bp[1] = htonl(vnode->fid.vid); 162845222b9eSDavid Howells 1629d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1630025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 163120b8391fSDavid Howells afs_set_fc_call(call, fc); 16320b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 16330b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 163445222b9eSDavid Howells } 1635e8d6c554SDavid Howells 1636e8d6c554SDavid Howells /* 1637e8d6c554SDavid Howells * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock 1638e8d6c554SDavid Howells */ 1639d001648eSDavid Howells static int afs_deliver_fs_xxxx_lock(struct afs_call *call) 1640e8d6c554SDavid Howells { 1641e8d6c554SDavid Howells const __be32 *bp; 1642372ee163SDavid Howells int ret; 1643e8d6c554SDavid Howells 1644d001648eSDavid Howells _enter("{%u}", call->unmarshall); 1645e8d6c554SDavid Howells 1646d001648eSDavid Howells ret = afs_transfer_reply(call); 1647372ee163SDavid Howells if (ret < 0) 1648372ee163SDavid Howells return ret; 1649e8d6c554SDavid Howells 1650e8d6c554SDavid Howells /* unmarshall the reply once we've received all of it */ 1651e8d6c554SDavid Howells bp = call->buffer; 1652ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 1653e8d6c554SDavid Howells 1654e8d6c554SDavid Howells _leave(" = 0 [done]"); 1655e8d6c554SDavid Howells return 0; 1656e8d6c554SDavid Howells } 1657e8d6c554SDavid Howells 1658e8d6c554SDavid Howells /* 1659e8d6c554SDavid Howells * FS.SetLock operation type 1660e8d6c554SDavid Howells */ 1661e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSSetLock = { 1662e8d6c554SDavid Howells .name = "FS.SetLock", 1663025db80cSDavid Howells .op = afs_FS_SetLock, 1664e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1665a690f60aSDavid Howells .done = afs_lock_op_done, 1666e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1667e8d6c554SDavid Howells }; 1668e8d6c554SDavid Howells 1669e8d6c554SDavid Howells /* 1670e8d6c554SDavid Howells * FS.ExtendLock operation type 1671e8d6c554SDavid Howells */ 1672e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSExtendLock = { 1673e8d6c554SDavid Howells .name = "FS.ExtendLock", 1674025db80cSDavid Howells .op = afs_FS_ExtendLock, 1675e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1676a690f60aSDavid Howells .done = afs_lock_op_done, 1677e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1678e8d6c554SDavid Howells }; 1679e8d6c554SDavid Howells 1680e8d6c554SDavid Howells /* 1681e8d6c554SDavid Howells * FS.ReleaseLock operation type 1682e8d6c554SDavid Howells */ 1683e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSReleaseLock = { 1684e8d6c554SDavid Howells .name = "FS.ReleaseLock", 1685025db80cSDavid Howells .op = afs_FS_ReleaseLock, 1686e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1687e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1688e8d6c554SDavid Howells }; 1689e8d6c554SDavid Howells 1690e8d6c554SDavid Howells /* 1691d2ddc776SDavid Howells * Set a lock on a file 1692e8d6c554SDavid Howells */ 1693a58823acSDavid Howells int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type, 1694a58823acSDavid Howells struct afs_status_cb *scb) 1695e8d6c554SDavid Howells { 1696d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1697e8d6c554SDavid Howells struct afs_call *call; 1698f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1699e8d6c554SDavid Howells __be32 *bp; 1700e8d6c554SDavid Howells 170130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1702a58823acSDavid Howells return yfs_fs_set_lock(fc, type, scb); 170330062bd1SDavid Howells 1704e8d6c554SDavid Howells _enter(""); 1705e8d6c554SDavid Howells 1706f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4); 1707e8d6c554SDavid Howells if (!call) 1708e8d6c554SDavid Howells return -ENOMEM; 1709e8d6c554SDavid Howells 1710d2ddc776SDavid Howells call->key = fc->key; 1711a58823acSDavid Howells call->lvnode = vnode; 1712a58823acSDavid Howells call->out_scb = scb; 1713e8d6c554SDavid Howells 1714e8d6c554SDavid Howells /* marshall the parameters */ 1715e8d6c554SDavid Howells bp = call->request; 1716e8d6c554SDavid Howells *bp++ = htonl(FSSETLOCK); 1717e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1718e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1719e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1720e8d6c554SDavid Howells *bp++ = htonl(type); 1721e8d6c554SDavid Howells 1722d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 17236c6c1d63SDavid Howells trace_afs_make_fs_calli(call, &vnode->fid, type); 172420b8391fSDavid Howells afs_set_fc_call(call, fc); 17250b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17260b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1727e8d6c554SDavid Howells } 1728e8d6c554SDavid Howells 1729e8d6c554SDavid Howells /* 1730e8d6c554SDavid Howells * extend a lock on a file 1731e8d6c554SDavid Howells */ 1732a58823acSDavid Howells int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1733e8d6c554SDavid Howells { 1734d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1735e8d6c554SDavid Howells struct afs_call *call; 1736f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1737e8d6c554SDavid Howells __be32 *bp; 1738e8d6c554SDavid Howells 173930062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1740a58823acSDavid Howells return yfs_fs_extend_lock(fc, scb); 174130062bd1SDavid Howells 1742e8d6c554SDavid Howells _enter(""); 1743e8d6c554SDavid Howells 1744f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4); 1745e8d6c554SDavid Howells if (!call) 1746e8d6c554SDavid Howells return -ENOMEM; 1747e8d6c554SDavid Howells 1748d2ddc776SDavid Howells call->key = fc->key; 1749a58823acSDavid Howells call->lvnode = vnode; 1750a58823acSDavid Howells call->out_scb = scb; 1751e8d6c554SDavid Howells 1752e8d6c554SDavid Howells /* marshall the parameters */ 1753e8d6c554SDavid Howells bp = call->request; 1754e8d6c554SDavid Howells *bp++ = htonl(FSEXTENDLOCK); 1755e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1756e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1757e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1758e8d6c554SDavid Howells 1759d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1760025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 176120b8391fSDavid Howells afs_set_fc_call(call, fc); 17620b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17630b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1764e8d6c554SDavid Howells } 1765e8d6c554SDavid Howells 1766e8d6c554SDavid Howells /* 1767e8d6c554SDavid Howells * release a lock on a file 1768e8d6c554SDavid Howells */ 1769a58823acSDavid Howells int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1770e8d6c554SDavid Howells { 1771d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1772e8d6c554SDavid Howells struct afs_call *call; 1773f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1774e8d6c554SDavid Howells __be32 *bp; 1775e8d6c554SDavid Howells 177630062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1777a58823acSDavid Howells return yfs_fs_release_lock(fc, scb); 177830062bd1SDavid Howells 1779e8d6c554SDavid Howells _enter(""); 1780e8d6c554SDavid Howells 1781f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4); 1782e8d6c554SDavid Howells if (!call) 1783e8d6c554SDavid Howells return -ENOMEM; 1784e8d6c554SDavid Howells 1785d2ddc776SDavid Howells call->key = fc->key; 1786a58823acSDavid Howells call->lvnode = vnode; 1787a58823acSDavid Howells call->out_scb = scb; 1788e8d6c554SDavid Howells 1789e8d6c554SDavid Howells /* marshall the parameters */ 1790e8d6c554SDavid Howells bp = call->request; 1791e8d6c554SDavid Howells *bp++ = htonl(FSRELEASELOCK); 1792e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1793e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1794e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1795e8d6c554SDavid Howells 1796d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1797025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 179820b8391fSDavid Howells afs_set_fc_call(call, fc); 17990b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 18000b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1801c435ee34SDavid Howells } 1802c435ee34SDavid Howells 1803c435ee34SDavid Howells /* 1804c435ee34SDavid Howells * Deliver reply data to an FS.GiveUpAllCallBacks operation. 1805c435ee34SDavid Howells */ 1806c435ee34SDavid Howells static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call) 1807c435ee34SDavid Howells { 1808c435ee34SDavid Howells return afs_transfer_reply(call); 1809c435ee34SDavid Howells } 1810c435ee34SDavid Howells 1811c435ee34SDavid Howells /* 1812c435ee34SDavid Howells * FS.GiveUpAllCallBacks operation type 1813c435ee34SDavid Howells */ 1814c435ee34SDavid Howells static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = { 1815c435ee34SDavid Howells .name = "FS.GiveUpAllCallBacks", 1816025db80cSDavid Howells .op = afs_FS_GiveUpAllCallBacks, 1817c435ee34SDavid Howells .deliver = afs_deliver_fs_give_up_all_callbacks, 1818c435ee34SDavid Howells .destructor = afs_flat_call_destructor, 1819c435ee34SDavid Howells }; 1820c435ee34SDavid Howells 1821c435ee34SDavid Howells /* 1822c435ee34SDavid Howells * Flush all the callbacks we have on a server. 1823c435ee34SDavid Howells */ 1824d2ddc776SDavid Howells int afs_fs_give_up_all_callbacks(struct afs_net *net, 1825d2ddc776SDavid Howells struct afs_server *server, 18268b2a464cSDavid Howells struct afs_addr_cursor *ac, 1827d2ddc776SDavid Howells struct key *key) 1828c435ee34SDavid Howells { 1829c435ee34SDavid Howells struct afs_call *call; 1830c435ee34SDavid Howells __be32 *bp; 1831c435ee34SDavid Howells 1832c435ee34SDavid Howells _enter(""); 1833c435ee34SDavid Howells 1834d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0); 1835c435ee34SDavid Howells if (!call) 1836c435ee34SDavid Howells return -ENOMEM; 1837c435ee34SDavid Howells 1838c435ee34SDavid Howells call->key = key; 1839c435ee34SDavid Howells 1840c435ee34SDavid Howells /* marshall the parameters */ 1841c435ee34SDavid Howells bp = call->request; 1842c435ee34SDavid Howells *bp++ = htonl(FSGIVEUPALLCALLBACKS); 1843c435ee34SDavid Howells 1844c435ee34SDavid Howells /* Can't take a ref on server */ 18450b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 18460b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, ac); 1847d2ddc776SDavid Howells } 1848d2ddc776SDavid Howells 1849d2ddc776SDavid Howells /* 1850d2ddc776SDavid Howells * Deliver reply data to an FS.GetCapabilities operation. 1851d2ddc776SDavid Howells */ 1852d2ddc776SDavid Howells static int afs_deliver_fs_get_capabilities(struct afs_call *call) 1853d2ddc776SDavid Howells { 1854d2ddc776SDavid Howells u32 count; 1855d2ddc776SDavid Howells int ret; 1856d2ddc776SDavid Howells 1857fc276122SDavid Howells _enter("{%u,%zu}", call->unmarshall, iov_iter_count(call->iter)); 1858d2ddc776SDavid Howells 1859d2ddc776SDavid Howells switch (call->unmarshall) { 1860d2ddc776SDavid Howells case 0: 186112bdcf33SDavid Howells afs_extract_to_tmp(call); 1862d2ddc776SDavid Howells call->unmarshall++; 186329881608SGustavo A. R. Silva /* Fall through */ 1864d2ddc776SDavid Howells 186529881608SGustavo A. R. Silva /* Extract the capabilities word count */ 1866d2ddc776SDavid Howells case 1: 186712bdcf33SDavid Howells ret = afs_extract_data(call, true); 1868d2ddc776SDavid Howells if (ret < 0) 1869d2ddc776SDavid Howells return ret; 1870d2ddc776SDavid Howells 1871d2ddc776SDavid Howells count = ntohl(call->tmp); 1872d2ddc776SDavid Howells 1873d2ddc776SDavid Howells call->count = count; 1874d2ddc776SDavid Howells call->count2 = count; 187523a28913SDavid Howells afs_extract_discard(call, count * sizeof(__be32)); 1876d2ddc776SDavid Howells call->unmarshall++; 187729881608SGustavo A. R. Silva /* Fall through */ 1878d2ddc776SDavid Howells 187929881608SGustavo A. R. Silva /* Extract capabilities words */ 1880d2ddc776SDavid Howells case 2: 188112bdcf33SDavid Howells ret = afs_extract_data(call, false); 1882d2ddc776SDavid Howells if (ret < 0) 1883d2ddc776SDavid Howells return ret; 1884d2ddc776SDavid Howells 1885d2ddc776SDavid Howells /* TODO: Examine capabilities */ 1886d2ddc776SDavid Howells 1887d2ddc776SDavid Howells call->unmarshall++; 1888d2ddc776SDavid Howells break; 1889d2ddc776SDavid Howells } 1890d2ddc776SDavid Howells 1891d2ddc776SDavid Howells _leave(" = 0 [done]"); 1892d2ddc776SDavid Howells return 0; 1893d2ddc776SDavid Howells } 1894d2ddc776SDavid Howells 1895d2ddc776SDavid Howells /* 1896d2ddc776SDavid Howells * FS.GetCapabilities operation type 1897d2ddc776SDavid Howells */ 1898d2ddc776SDavid Howells static const struct afs_call_type afs_RXFSGetCapabilities = { 1899d2ddc776SDavid Howells .name = "FS.GetCapabilities", 1900025db80cSDavid Howells .op = afs_FS_GetCapabilities, 1901d2ddc776SDavid Howells .deliver = afs_deliver_fs_get_capabilities, 19023bf0fb6fSDavid Howells .done = afs_fileserver_probe_result, 1903ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 1904d2ddc776SDavid Howells }; 1905d2ddc776SDavid Howells 1906d2ddc776SDavid Howells /* 1907d2ddc776SDavid Howells * Probe a fileserver for the capabilities that it supports. This can 1908d2ddc776SDavid Howells * return up to 196 words. 1909d2ddc776SDavid Howells */ 19100b9bf381SDavid Howells struct afs_call *afs_fs_get_capabilities(struct afs_net *net, 1911d2ddc776SDavid Howells struct afs_server *server, 1912d2ddc776SDavid Howells struct afs_addr_cursor *ac, 19133bf0fb6fSDavid Howells struct key *key, 19140b9bf381SDavid Howells unsigned int server_index) 1915d2ddc776SDavid Howells { 1916d2ddc776SDavid Howells struct afs_call *call; 1917d2ddc776SDavid Howells __be32 *bp; 1918d2ddc776SDavid Howells 1919d2ddc776SDavid Howells _enter(""); 1920d2ddc776SDavid Howells 1921d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4); 1922d2ddc776SDavid Howells if (!call) 19230b9bf381SDavid Howells return ERR_PTR(-ENOMEM); 1924d2ddc776SDavid Howells 1925d2ddc776SDavid Howells call->key = key; 192645218193SDavid Howells call->server = afs_get_server(server, afs_server_trace_get_caps); 1927ffba718eSDavid Howells call->server_index = server_index; 192830062bd1SDavid Howells call->upgrade = true; 19290b9bf381SDavid Howells call->async = true; 193094f699c9SDavid Howells call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; 1931d2ddc776SDavid Howells 1932d2ddc776SDavid Howells /* marshall the parameters */ 1933d2ddc776SDavid Howells bp = call->request; 1934d2ddc776SDavid Howells *bp++ = htonl(FSGETCAPABILITIES); 1935d2ddc776SDavid Howells 1936d2ddc776SDavid Howells /* Can't take a ref on server */ 1937025db80cSDavid Howells trace_afs_make_fs_call(call, NULL); 19380b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 19390b9bf381SDavid Howells return call; 1940e8d6c554SDavid Howells } 19415cf9dd55SDavid Howells 19425cf9dd55SDavid Howells /* 19435cf9dd55SDavid Howells * Deliver reply data to an FS.FetchStatus with no vnode. 19445cf9dd55SDavid Howells */ 19455cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status(struct afs_call *call) 19465cf9dd55SDavid Howells { 19475cf9dd55SDavid Howells const __be32 *bp; 19485cf9dd55SDavid Howells int ret; 19495cf9dd55SDavid Howells 19505cf9dd55SDavid Howells ret = afs_transfer_reply(call); 19515cf9dd55SDavid Howells if (ret < 0) 19525cf9dd55SDavid Howells return ret; 19535cf9dd55SDavid Howells 19545cf9dd55SDavid Howells /* unmarshall the reply once we've received all of it */ 19555cf9dd55SDavid Howells bp = call->buffer; 1956a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1957160cb957SDavid Howells if (ret < 0) 1958160cb957SDavid Howells return ret; 1959a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 1960a58823acSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 19615cf9dd55SDavid Howells 19625cf9dd55SDavid Howells _leave(" = 0 [done]"); 19635cf9dd55SDavid Howells return 0; 19645cf9dd55SDavid Howells } 19655cf9dd55SDavid Howells 19665cf9dd55SDavid Howells /* 19675cf9dd55SDavid Howells * FS.FetchStatus operation type 19685cf9dd55SDavid Howells */ 19695cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus = { 19705cf9dd55SDavid Howells .name = "FS.FetchStatus", 19715cf9dd55SDavid Howells .op = afs_FS_FetchStatus, 19725cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status, 19735cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 19745cf9dd55SDavid Howells }; 19755cf9dd55SDavid Howells 19765cf9dd55SDavid Howells /* 19775cf9dd55SDavid Howells * Fetch the status information for a fid without needing a vnode handle. 19785cf9dd55SDavid Howells */ 19795cf9dd55SDavid Howells int afs_fs_fetch_status(struct afs_fs_cursor *fc, 19805cf9dd55SDavid Howells struct afs_net *net, 19815cf9dd55SDavid Howells struct afs_fid *fid, 1982a58823acSDavid Howells struct afs_status_cb *scb, 19835cf9dd55SDavid Howells struct afs_volsync *volsync) 19845cf9dd55SDavid Howells { 19855cf9dd55SDavid Howells struct afs_call *call; 19865cf9dd55SDavid Howells __be32 *bp; 19875cf9dd55SDavid Howells 198830062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1989a58823acSDavid Howells return yfs_fs_fetch_status(fc, net, fid, scb, volsync); 199030062bd1SDavid Howells 19913b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 19925cf9dd55SDavid Howells key_serial(fc->key), fid->vid, fid->vnode); 19935cf9dd55SDavid Howells 19945cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); 19955cf9dd55SDavid Howells if (!call) { 19965cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 19975cf9dd55SDavid Howells return -ENOMEM; 19985cf9dd55SDavid Howells } 19995cf9dd55SDavid Howells 20005cf9dd55SDavid Howells call->key = fc->key; 2001ffba718eSDavid Howells call->out_fid = fid; 2002a58823acSDavid Howells call->out_scb = scb; 2003ffba718eSDavid Howells call->out_volsync = volsync; 20045cf9dd55SDavid Howells 20055cf9dd55SDavid Howells /* marshall the parameters */ 20065cf9dd55SDavid Howells bp = call->request; 20075cf9dd55SDavid Howells bp[0] = htonl(FSFETCHSTATUS); 20085cf9dd55SDavid Howells bp[1] = htonl(fid->vid); 20095cf9dd55SDavid Howells bp[2] = htonl(fid->vnode); 20105cf9dd55SDavid Howells bp[3] = htonl(fid->unique); 20115cf9dd55SDavid Howells 20125cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 20135cf9dd55SDavid Howells trace_afs_make_fs_call(call, fid); 201420b8391fSDavid Howells afs_set_fc_call(call, fc); 20150b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 20160b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 20175cf9dd55SDavid Howells } 20185cf9dd55SDavid Howells 20195cf9dd55SDavid Howells /* 20205cf9dd55SDavid Howells * Deliver reply data to an FS.InlineBulkStatus call 20215cf9dd55SDavid Howells */ 20225cf9dd55SDavid Howells static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) 20235cf9dd55SDavid Howells { 202487182759SDavid Howells struct afs_status_cb *scb; 20255cf9dd55SDavid Howells const __be32 *bp; 20265cf9dd55SDavid Howells u32 tmp; 20275cf9dd55SDavid Howells int ret; 20285cf9dd55SDavid Howells 20295cf9dd55SDavid Howells _enter("{%u}", call->unmarshall); 20305cf9dd55SDavid Howells 20315cf9dd55SDavid Howells switch (call->unmarshall) { 20325cf9dd55SDavid Howells case 0: 203312bdcf33SDavid Howells afs_extract_to_tmp(call); 20345cf9dd55SDavid Howells call->unmarshall++; 203529881608SGustavo A. R. Silva /* Fall through */ 20365cf9dd55SDavid Howells 20375cf9dd55SDavid Howells /* Extract the file status count and array in two steps */ 20385cf9dd55SDavid Howells case 1: 20395cf9dd55SDavid Howells _debug("extract status count"); 204012bdcf33SDavid Howells ret = afs_extract_data(call, true); 20415cf9dd55SDavid Howells if (ret < 0) 20425cf9dd55SDavid Howells return ret; 20435cf9dd55SDavid Howells 20445cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20455cf9dd55SDavid Howells _debug("status count: %u/%u", tmp, call->count2); 20465cf9dd55SDavid Howells if (tmp != call->count2) 2047160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2048160cb957SDavid Howells afs_eproto_ibulkst_count); 20495cf9dd55SDavid Howells 20505cf9dd55SDavid Howells call->count = 0; 20515cf9dd55SDavid Howells call->unmarshall++; 20525cf9dd55SDavid Howells more_counts: 205312bdcf33SDavid Howells afs_extract_to_buf(call, 21 * sizeof(__be32)); 2054e690c9e3SGustavo A. R. Silva /* Fall through */ 205529881608SGustavo A. R. Silva 20565cf9dd55SDavid Howells case 2: 20575cf9dd55SDavid Howells _debug("extract status array %u", call->count); 205812bdcf33SDavid Howells ret = afs_extract_data(call, true); 20595cf9dd55SDavid Howells if (ret < 0) 20605cf9dd55SDavid Howells return ret; 20615cf9dd55SDavid Howells 20625cf9dd55SDavid Howells bp = call->buffer; 206387182759SDavid Howells scb = &call->out_scb[call->count]; 2064a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, scb); 2065160cb957SDavid Howells if (ret < 0) 2066160cb957SDavid Howells return ret; 20675cf9dd55SDavid Howells 20685cf9dd55SDavid Howells call->count++; 20695cf9dd55SDavid Howells if (call->count < call->count2) 20705cf9dd55SDavid Howells goto more_counts; 20715cf9dd55SDavid Howells 20725cf9dd55SDavid Howells call->count = 0; 20735cf9dd55SDavid Howells call->unmarshall++; 207412bdcf33SDavid Howells afs_extract_to_tmp(call); 207529881608SGustavo A. R. Silva /* Fall through */ 20765cf9dd55SDavid Howells 20775cf9dd55SDavid Howells /* Extract the callback count and array in two steps */ 20785cf9dd55SDavid Howells case 3: 20795cf9dd55SDavid Howells _debug("extract CB count"); 208012bdcf33SDavid Howells ret = afs_extract_data(call, true); 20815cf9dd55SDavid Howells if (ret < 0) 20825cf9dd55SDavid Howells return ret; 20835cf9dd55SDavid Howells 20845cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20855cf9dd55SDavid Howells _debug("CB count: %u", tmp); 20865cf9dd55SDavid Howells if (tmp != call->count2) 2087160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2088160cb957SDavid Howells afs_eproto_ibulkst_cb_count); 20895cf9dd55SDavid Howells call->count = 0; 20905cf9dd55SDavid Howells call->unmarshall++; 20915cf9dd55SDavid Howells more_cbs: 209212bdcf33SDavid Howells afs_extract_to_buf(call, 3 * sizeof(__be32)); 2093e690c9e3SGustavo A. R. Silva /* Fall through */ 209429881608SGustavo A. R. Silva 20955cf9dd55SDavid Howells case 4: 20965cf9dd55SDavid Howells _debug("extract CB array"); 209712bdcf33SDavid Howells ret = afs_extract_data(call, true); 20985cf9dd55SDavid Howells if (ret < 0) 20995cf9dd55SDavid Howells return ret; 21005cf9dd55SDavid Howells 21015cf9dd55SDavid Howells _debug("unmarshall CB array"); 21025cf9dd55SDavid Howells bp = call->buffer; 210387182759SDavid Howells scb = &call->out_scb[call->count]; 2104a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, scb); 21055cf9dd55SDavid Howells call->count++; 21065cf9dd55SDavid Howells if (call->count < call->count2) 21075cf9dd55SDavid Howells goto more_cbs; 21085cf9dd55SDavid Howells 210912bdcf33SDavid Howells afs_extract_to_buf(call, 6 * sizeof(__be32)); 21105cf9dd55SDavid Howells call->unmarshall++; 2111e690c9e3SGustavo A. R. Silva /* Fall through */ 211229881608SGustavo A. R. Silva 21135cf9dd55SDavid Howells case 5: 211412bdcf33SDavid Howells ret = afs_extract_data(call, false); 21155cf9dd55SDavid Howells if (ret < 0) 21165cf9dd55SDavid Howells return ret; 21175cf9dd55SDavid Howells 21185cf9dd55SDavid Howells bp = call->buffer; 2119ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 21205cf9dd55SDavid Howells 21215cf9dd55SDavid Howells call->unmarshall++; 21225cf9dd55SDavid Howells 21235cf9dd55SDavid Howells case 6: 21245cf9dd55SDavid Howells break; 21255cf9dd55SDavid Howells } 21265cf9dd55SDavid Howells 21275cf9dd55SDavid Howells _leave(" = 0 [done]"); 21285cf9dd55SDavid Howells return 0; 21295cf9dd55SDavid Howells } 21305cf9dd55SDavid Howells 21315cf9dd55SDavid Howells /* 21325cf9dd55SDavid Howells * FS.InlineBulkStatus operation type 21335cf9dd55SDavid Howells */ 21345cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSInlineBulkStatus = { 21355cf9dd55SDavid Howells .name = "FS.InlineBulkStatus", 21365cf9dd55SDavid Howells .op = afs_FS_InlineBulkStatus, 21375cf9dd55SDavid Howells .deliver = afs_deliver_fs_inline_bulk_status, 21385cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 21395cf9dd55SDavid Howells }; 21405cf9dd55SDavid Howells 21415cf9dd55SDavid Howells /* 21425cf9dd55SDavid Howells * Fetch the status information for up to 50 files 21435cf9dd55SDavid Howells */ 21445cf9dd55SDavid Howells int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, 21455cf9dd55SDavid Howells struct afs_net *net, 21465cf9dd55SDavid Howells struct afs_fid *fids, 214787182759SDavid Howells struct afs_status_cb *statuses, 21485cf9dd55SDavid Howells unsigned int nr_fids, 21495cf9dd55SDavid Howells struct afs_volsync *volsync) 21505cf9dd55SDavid Howells { 21515cf9dd55SDavid Howells struct afs_call *call; 21525cf9dd55SDavid Howells __be32 *bp; 21535cf9dd55SDavid Howells int i; 21545cf9dd55SDavid Howells 215530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 215687182759SDavid Howells return yfs_fs_inline_bulk_status(fc, net, fids, statuses, 215730062bd1SDavid Howells nr_fids, volsync); 215830062bd1SDavid Howells 21593b6492dfSDavid Howells _enter(",%x,{%llx:%llu},%u", 21605cf9dd55SDavid Howells key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); 21615cf9dd55SDavid Howells 21625cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus, 21635cf9dd55SDavid Howells (2 + nr_fids * 3) * 4, 21645cf9dd55SDavid Howells 21 * 4); 21655cf9dd55SDavid Howells if (!call) { 21665cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 21675cf9dd55SDavid Howells return -ENOMEM; 21685cf9dd55SDavid Howells } 21695cf9dd55SDavid Howells 21705cf9dd55SDavid Howells call->key = fc->key; 217187182759SDavid Howells call->out_scb = statuses; 2172ffba718eSDavid Howells call->out_volsync = volsync; 21735cf9dd55SDavid Howells call->count2 = nr_fids; 21745cf9dd55SDavid Howells 21755cf9dd55SDavid Howells /* marshall the parameters */ 21765cf9dd55SDavid Howells bp = call->request; 21775cf9dd55SDavid Howells *bp++ = htonl(FSINLINEBULKSTATUS); 21785cf9dd55SDavid Howells *bp++ = htonl(nr_fids); 21795cf9dd55SDavid Howells for (i = 0; i < nr_fids; i++) { 21805cf9dd55SDavid Howells *bp++ = htonl(fids[i].vid); 21815cf9dd55SDavid Howells *bp++ = htonl(fids[i].vnode); 21825cf9dd55SDavid Howells *bp++ = htonl(fids[i].unique); 21835cf9dd55SDavid Howells } 21845cf9dd55SDavid Howells 21855cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 21865cf9dd55SDavid Howells trace_afs_make_fs_call(call, &fids[0]); 218720b8391fSDavid Howells afs_set_fc_call(call, fc); 21880b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 21890b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 21905cf9dd55SDavid Howells } 2191260f082bSDavid Howells 2192260f082bSDavid Howells /* 2193260f082bSDavid Howells * deliver reply data to an FS.FetchACL 2194260f082bSDavid Howells */ 2195260f082bSDavid Howells static int afs_deliver_fs_fetch_acl(struct afs_call *call) 2196260f082bSDavid Howells { 2197260f082bSDavid Howells struct afs_acl *acl; 2198260f082bSDavid Howells const __be32 *bp; 2199260f082bSDavid Howells unsigned int size; 2200260f082bSDavid Howells int ret; 2201260f082bSDavid Howells 2202260f082bSDavid Howells _enter("{%u}", call->unmarshall); 2203260f082bSDavid Howells 2204260f082bSDavid Howells switch (call->unmarshall) { 2205260f082bSDavid Howells case 0: 2206260f082bSDavid Howells afs_extract_to_tmp(call); 2207260f082bSDavid Howells call->unmarshall++; 220829881608SGustavo A. R. Silva /* Fall through */ 2209260f082bSDavid Howells 2210260f082bSDavid Howells /* extract the returned data length */ 2211260f082bSDavid Howells case 1: 2212260f082bSDavid Howells ret = afs_extract_data(call, true); 2213260f082bSDavid Howells if (ret < 0) 2214260f082bSDavid Howells return ret; 2215260f082bSDavid Howells 2216260f082bSDavid Howells size = call->count2 = ntohl(call->tmp); 2217260f082bSDavid Howells size = round_up(size, 4); 2218260f082bSDavid Howells 2219260f082bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); 2220260f082bSDavid Howells if (!acl) 2221260f082bSDavid Howells return -ENOMEM; 2222ffba718eSDavid Howells call->ret_acl = acl; 2223260f082bSDavid Howells acl->size = call->count2; 2224260f082bSDavid Howells afs_extract_begin(call, acl->data, size); 2225260f082bSDavid Howells call->unmarshall++; 222629881608SGustavo A. R. Silva /* Fall through */ 2227260f082bSDavid Howells 2228260f082bSDavid Howells /* extract the returned data */ 2229260f082bSDavid Howells case 2: 2230260f082bSDavid Howells ret = afs_extract_data(call, true); 2231260f082bSDavid Howells if (ret < 0) 2232260f082bSDavid Howells return ret; 2233260f082bSDavid Howells 2234260f082bSDavid Howells afs_extract_to_buf(call, (21 + 6) * 4); 2235260f082bSDavid Howells call->unmarshall++; 223629881608SGustavo A. R. Silva /* Fall through */ 2237260f082bSDavid Howells 2238260f082bSDavid Howells /* extract the metadata */ 2239260f082bSDavid Howells case 3: 2240260f082bSDavid Howells ret = afs_extract_data(call, false); 2241260f082bSDavid Howells if (ret < 0) 2242260f082bSDavid Howells return ret; 2243260f082bSDavid Howells 2244260f082bSDavid Howells bp = call->buffer; 2245a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2246260f082bSDavid Howells if (ret < 0) 2247260f082bSDavid Howells return ret; 2248ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2249260f082bSDavid Howells 2250260f082bSDavid Howells call->unmarshall++; 2251260f082bSDavid Howells 2252260f082bSDavid Howells case 4: 2253260f082bSDavid Howells break; 2254260f082bSDavid Howells } 2255260f082bSDavid Howells 2256260f082bSDavid Howells _leave(" = 0 [done]"); 2257260f082bSDavid Howells return 0; 2258260f082bSDavid Howells } 2259260f082bSDavid Howells 2260260f082bSDavid Howells static void afs_destroy_fs_fetch_acl(struct afs_call *call) 2261260f082bSDavid Howells { 2262ffba718eSDavid Howells kfree(call->ret_acl); 2263260f082bSDavid Howells afs_flat_call_destructor(call); 2264260f082bSDavid Howells } 2265260f082bSDavid Howells 2266260f082bSDavid Howells /* 2267260f082bSDavid Howells * FS.FetchACL operation type 2268260f082bSDavid Howells */ 2269260f082bSDavid Howells static const struct afs_call_type afs_RXFSFetchACL = { 2270260f082bSDavid Howells .name = "FS.FetchACL", 2271260f082bSDavid Howells .op = afs_FS_FetchACL, 2272260f082bSDavid Howells .deliver = afs_deliver_fs_fetch_acl, 2273260f082bSDavid Howells .destructor = afs_destroy_fs_fetch_acl, 2274260f082bSDavid Howells }; 2275260f082bSDavid Howells 2276260f082bSDavid Howells /* 2277260f082bSDavid Howells * Fetch the ACL for a file. 2278260f082bSDavid Howells */ 2279a58823acSDavid Howells struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc, 2280a58823acSDavid Howells struct afs_status_cb *scb) 2281260f082bSDavid Howells { 2282260f082bSDavid Howells struct afs_vnode *vnode = fc->vnode; 2283260f082bSDavid Howells struct afs_call *call; 2284260f082bSDavid Howells struct afs_net *net = afs_v2net(vnode); 2285260f082bSDavid Howells __be32 *bp; 2286260f082bSDavid Howells 2287260f082bSDavid Howells _enter(",%x,{%llx:%llu},,", 2288260f082bSDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2289260f082bSDavid Howells 2290260f082bSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4); 2291260f082bSDavid Howells if (!call) { 2292260f082bSDavid Howells fc->ac.error = -ENOMEM; 2293260f082bSDavid Howells return ERR_PTR(-ENOMEM); 2294260f082bSDavid Howells } 2295260f082bSDavid Howells 2296260f082bSDavid Howells call->key = fc->key; 2297ffba718eSDavid Howells call->ret_acl = NULL; 2298a58823acSDavid Howells call->out_scb = scb; 2299ffba718eSDavid Howells call->out_volsync = NULL; 2300260f082bSDavid Howells 2301260f082bSDavid Howells /* marshall the parameters */ 2302260f082bSDavid Howells bp = call->request; 2303260f082bSDavid Howells bp[0] = htonl(FSFETCHACL); 2304260f082bSDavid Howells bp[1] = htonl(vnode->fid.vid); 2305260f082bSDavid Howells bp[2] = htonl(vnode->fid.vnode); 2306260f082bSDavid Howells bp[3] = htonl(vnode->fid.unique); 2307260f082bSDavid Howells 2308260f082bSDavid Howells afs_use_fs_server(call, fc->cbi); 2309260f082bSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 2310260f082bSDavid Howells afs_make_call(&fc->ac, call, GFP_KERNEL); 2311260f082bSDavid Howells return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac); 2312260f082bSDavid Howells } 2313b10494afSJoe Gorse 2314b10494afSJoe Gorse /* 2315ffba718eSDavid Howells * Deliver reply data to any operation that returns file status and volume 2316ffba718eSDavid Howells * sync. 2317ffba718eSDavid Howells */ 2318ffba718eSDavid Howells static int afs_deliver_fs_file_status_and_vol(struct afs_call *call) 2319ffba718eSDavid Howells { 2320ffba718eSDavid Howells const __be32 *bp; 2321ffba718eSDavid Howells int ret; 2322ffba718eSDavid Howells 2323ffba718eSDavid Howells ret = afs_transfer_reply(call); 2324ffba718eSDavid Howells if (ret < 0) 2325ffba718eSDavid Howells return ret; 2326ffba718eSDavid Howells 2327ffba718eSDavid Howells bp = call->buffer; 2328a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2329ffba718eSDavid Howells if (ret < 0) 2330ffba718eSDavid Howells return ret; 2331ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2332ffba718eSDavid Howells 2333ffba718eSDavid Howells _leave(" = 0 [done]"); 2334ffba718eSDavid Howells return 0; 2335ffba718eSDavid Howells } 2336ffba718eSDavid Howells 2337ffba718eSDavid Howells /* 2338b10494afSJoe Gorse * FS.StoreACL operation type 2339b10494afSJoe Gorse */ 2340b10494afSJoe Gorse static const struct afs_call_type afs_RXFSStoreACL = { 2341b10494afSJoe Gorse .name = "FS.StoreACL", 2342b10494afSJoe Gorse .op = afs_FS_StoreACL, 2343ffba718eSDavid Howells .deliver = afs_deliver_fs_file_status_and_vol, 2344b10494afSJoe Gorse .destructor = afs_flat_call_destructor, 2345b10494afSJoe Gorse }; 2346b10494afSJoe Gorse 2347b10494afSJoe Gorse /* 2348b10494afSJoe Gorse * Fetch the ACL for a file. 2349b10494afSJoe Gorse */ 2350a58823acSDavid Howells int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl, 2351a58823acSDavid Howells struct afs_status_cb *scb) 2352b10494afSJoe Gorse { 2353b10494afSJoe Gorse struct afs_vnode *vnode = fc->vnode; 2354b10494afSJoe Gorse struct afs_call *call; 2355b10494afSJoe Gorse struct afs_net *net = afs_v2net(vnode); 2356b10494afSJoe Gorse size_t size; 2357b10494afSJoe Gorse __be32 *bp; 2358b10494afSJoe Gorse 2359b10494afSJoe Gorse _enter(",%x,{%llx:%llu},,", 2360b10494afSJoe Gorse key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2361b10494afSJoe Gorse 2362b10494afSJoe Gorse size = round_up(acl->size, 4); 2363b10494afSJoe Gorse call = afs_alloc_flat_call(net, &afs_RXFSStoreACL, 2364b10494afSJoe Gorse 5 * 4 + size, (21 + 6) * 4); 2365b10494afSJoe Gorse if (!call) { 2366b10494afSJoe Gorse fc->ac.error = -ENOMEM; 2367b10494afSJoe Gorse return -ENOMEM; 2368b10494afSJoe Gorse } 2369b10494afSJoe Gorse 2370b10494afSJoe Gorse call->key = fc->key; 2371a58823acSDavid Howells call->out_scb = scb; 2372ffba718eSDavid Howells call->out_volsync = NULL; 2373b10494afSJoe Gorse 2374b10494afSJoe Gorse /* marshall the parameters */ 2375b10494afSJoe Gorse bp = call->request; 2376b10494afSJoe Gorse bp[0] = htonl(FSSTOREACL); 2377b10494afSJoe Gorse bp[1] = htonl(vnode->fid.vid); 2378b10494afSJoe Gorse bp[2] = htonl(vnode->fid.vnode); 2379b10494afSJoe Gorse bp[3] = htonl(vnode->fid.unique); 2380b10494afSJoe Gorse bp[4] = htonl(acl->size); 2381b10494afSJoe Gorse memcpy(&bp[5], acl->data, acl->size); 2382b10494afSJoe Gorse if (acl->size != size) 2383b10494afSJoe Gorse memset((void *)&bp[5] + acl->size, 0, size - acl->size); 2384b10494afSJoe Gorse 2385b10494afSJoe Gorse trace_afs_make_fs_call(call, &vnode->fid); 2386b10494afSJoe Gorse afs_make_call(&fc->ac, call, GFP_KERNEL); 2387b10494afSJoe Gorse return afs_wait_for_call_to_complete(call, &fc->ac); 23881da177e4SLinus Torvalds } 2389