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; 68dd9fbcb8SDavid Howells 69684b0f68SDavid Howells abort_code = ntohl(xdr->abort_code); 70684b0f68SDavid Howells 71dd9fbcb8SDavid Howells if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { 72684b0f68SDavid Howells if (xdr->if_version == htonl(0) && 73684b0f68SDavid Howells abort_code != 0 && 74684b0f68SDavid Howells inline_error) { 75684b0f68SDavid Howells /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus 76684b0f68SDavid Howells * whereby it doesn't set the interface version in the error 77684b0f68SDavid Howells * case. 78684b0f68SDavid Howells */ 79684b0f68SDavid Howells status->abort_code = abort_code; 80a38a7558SDavid Howells scb->have_error = true; 81de52cf92SAl Viro return 0; 82684b0f68SDavid Howells } 83684b0f68SDavid Howells 84dd9fbcb8SDavid Howells pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); 85dd9fbcb8SDavid Howells goto bad; 86dd9fbcb8SDavid Howells } 87dd9fbcb8SDavid Howells 88684b0f68SDavid Howells if (abort_code != 0 && inline_error) { 89684b0f68SDavid Howells status->abort_code = abort_code; 90de52cf92SAl Viro return 0; 91684b0f68SDavid Howells } 92684b0f68SDavid Howells 93dd9fbcb8SDavid Howells type = ntohl(xdr->type); 94dd9fbcb8SDavid Howells switch (type) { 95dd9fbcb8SDavid Howells case AFS_FTYPE_FILE: 96dd9fbcb8SDavid Howells case AFS_FTYPE_DIR: 97dd9fbcb8SDavid Howells case AFS_FTYPE_SYMLINK: 98dd9fbcb8SDavid Howells status->type = type; 99dd9fbcb8SDavid Howells break; 100dd9fbcb8SDavid Howells default: 101dd9fbcb8SDavid Howells goto bad; 102dd9fbcb8SDavid Howells } 103dd9fbcb8SDavid Howells 104a58823acSDavid Howells status->nlink = ntohl(xdr->nlink); 105a58823acSDavid Howells status->author = ntohl(xdr->author); 106a58823acSDavid Howells status->owner = ntohl(xdr->owner); 107a58823acSDavid Howells status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */ 108a58823acSDavid Howells status->anon_access = ntohl(xdr->anon_access); 109a58823acSDavid Howells status->mode = ntohl(xdr->mode) & S_IALLUGO; 110a58823acSDavid Howells status->group = ntohl(xdr->group); 111a58823acSDavid Howells status->lock_count = ntohl(xdr->lock_count); 112dd9fbcb8SDavid Howells 113d4936803SDavid Howells status->mtime_client.tv_sec = ntohl(xdr->mtime_client); 114d4936803SDavid Howells status->mtime_client.tv_nsec = 0; 115d4936803SDavid Howells status->mtime_server.tv_sec = ntohl(xdr->mtime_server); 116d4936803SDavid Howells status->mtime_server.tv_nsec = 0; 117dd9fbcb8SDavid Howells 118dd9fbcb8SDavid Howells size = (u64)ntohl(xdr->size_lo); 119dd9fbcb8SDavid Howells size |= (u64)ntohl(xdr->size_hi) << 32; 120dd9fbcb8SDavid Howells status->size = size; 121dd9fbcb8SDavid Howells 122dd9fbcb8SDavid Howells data_version = (u64)ntohl(xdr->data_version_lo); 123dd9fbcb8SDavid Howells data_version |= (u64)ntohl(xdr->data_version_hi) << 32; 124dd9fbcb8SDavid Howells status->data_version = data_version; 125a38a7558SDavid Howells scb->have_status = true; 126dd9fbcb8SDavid Howells 127dd9fbcb8SDavid Howells *_bp = (const void *)*_bp + sizeof(*xdr); 128c875c76aSDavid Howells return 0; 129dd9fbcb8SDavid Howells 130dd9fbcb8SDavid Howells bad: 131dd9fbcb8SDavid Howells xdr_dump_bad(*_bp); 132160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); 133c875c76aSDavid Howells } 134c875c76aSDavid Howells 13578107055SDavid Howells static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) 13678107055SDavid Howells { 13778107055SDavid Howells return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; 13878107055SDavid Howells } 13978107055SDavid Howells 140a58823acSDavid Howells static void xdr_decode_AFSCallBack(const __be32 **_bp, 141a58823acSDavid Howells struct afs_call *call, 142a58823acSDavid Howells struct afs_status_cb *scb) 14378107055SDavid Howells { 144a58823acSDavid Howells struct afs_callback *cb = &scb->callback; 14578107055SDavid Howells const __be32 *bp = *_bp; 14678107055SDavid Howells 1477c712458SDavid Howells bp++; /* version */ 14878107055SDavid Howells cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); 1497c712458SDavid Howells bp++; /* type */ 150a58823acSDavid Howells scb->have_cb = true; 15178107055SDavid Howells *_bp = bp; 15278107055SDavid Howells } 15378107055SDavid Howells 1541da177e4SLinus Torvalds /* 15508e0e7c8SDavid Howells * decode an AFSVolSync block 1561da177e4SLinus Torvalds */ 15708e0e7c8SDavid Howells static void xdr_decode_AFSVolSync(const __be32 **_bp, 15808e0e7c8SDavid Howells struct afs_volsync *volsync) 1591da177e4SLinus Torvalds { 16008e0e7c8SDavid Howells const __be32 *bp = *_bp; 16130062bd1SDavid Howells u32 creation; 1621da177e4SLinus Torvalds 16330062bd1SDavid Howells creation = ntohl(*bp++); 16408e0e7c8SDavid Howells bp++; /* spare2 */ 16508e0e7c8SDavid Howells bp++; /* spare3 */ 16608e0e7c8SDavid Howells bp++; /* spare4 */ 16708e0e7c8SDavid Howells bp++; /* spare5 */ 16808e0e7c8SDavid Howells bp++; /* spare6 */ 16908e0e7c8SDavid Howells *_bp = bp; 17030062bd1SDavid Howells 17130062bd1SDavid Howells if (volsync) 17230062bd1SDavid Howells volsync->creation = creation; 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds 17508e0e7c8SDavid Howells /* 17631143d5dSDavid Howells * encode the requested attributes into an AFSStoreStatus block 17731143d5dSDavid Howells */ 17831143d5dSDavid Howells static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr) 17931143d5dSDavid Howells { 18031143d5dSDavid Howells __be32 *bp = *_bp; 18131143d5dSDavid Howells u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0; 18231143d5dSDavid Howells 18331143d5dSDavid Howells mask = 0; 18431143d5dSDavid Howells if (attr->ia_valid & ATTR_MTIME) { 18531143d5dSDavid Howells mask |= AFS_SET_MTIME; 18631143d5dSDavid Howells mtime = attr->ia_mtime.tv_sec; 18731143d5dSDavid Howells } 18831143d5dSDavid Howells 18931143d5dSDavid Howells if (attr->ia_valid & ATTR_UID) { 19031143d5dSDavid Howells mask |= AFS_SET_OWNER; 191a0a5386aSEric W. Biederman owner = from_kuid(&init_user_ns, attr->ia_uid); 19231143d5dSDavid Howells } 19331143d5dSDavid Howells 19431143d5dSDavid Howells if (attr->ia_valid & ATTR_GID) { 19531143d5dSDavid Howells mask |= AFS_SET_GROUP; 196a0a5386aSEric W. Biederman group = from_kgid(&init_user_ns, attr->ia_gid); 19731143d5dSDavid Howells } 19831143d5dSDavid Howells 19931143d5dSDavid Howells if (attr->ia_valid & ATTR_MODE) { 20031143d5dSDavid Howells mask |= AFS_SET_MODE; 20131143d5dSDavid Howells mode = attr->ia_mode & S_IALLUGO; 20231143d5dSDavid Howells } 20331143d5dSDavid Howells 20431143d5dSDavid Howells *bp++ = htonl(mask); 20531143d5dSDavid Howells *bp++ = htonl(mtime); 20631143d5dSDavid Howells *bp++ = htonl(owner); 20731143d5dSDavid Howells *bp++ = htonl(group); 20831143d5dSDavid Howells *bp++ = htonl(mode); 20931143d5dSDavid Howells *bp++ = 0; /* segment size */ 21031143d5dSDavid Howells *_bp = bp; 21131143d5dSDavid Howells } 21231143d5dSDavid Howells 21331143d5dSDavid Howells /* 21445222b9eSDavid Howells * decode an AFSFetchVolumeStatus block 21545222b9eSDavid Howells */ 21645222b9eSDavid Howells static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, 21745222b9eSDavid Howells struct afs_volume_status *vs) 21845222b9eSDavid Howells { 21945222b9eSDavid Howells const __be32 *bp = *_bp; 22045222b9eSDavid Howells 22145222b9eSDavid Howells vs->vid = ntohl(*bp++); 22245222b9eSDavid Howells vs->parent_id = ntohl(*bp++); 22345222b9eSDavid Howells vs->online = ntohl(*bp++); 22445222b9eSDavid Howells vs->in_service = ntohl(*bp++); 22545222b9eSDavid Howells vs->blessed = ntohl(*bp++); 22645222b9eSDavid Howells vs->needs_salvage = ntohl(*bp++); 22745222b9eSDavid Howells vs->type = ntohl(*bp++); 22845222b9eSDavid Howells vs->min_quota = ntohl(*bp++); 22945222b9eSDavid Howells vs->max_quota = ntohl(*bp++); 23045222b9eSDavid Howells vs->blocks_in_use = ntohl(*bp++); 23145222b9eSDavid Howells vs->part_blocks_avail = ntohl(*bp++); 23245222b9eSDavid Howells vs->part_max_blocks = ntohl(*bp++); 23330062bd1SDavid Howells vs->vol_copy_date = 0; 23430062bd1SDavid Howells vs->vol_backup_date = 0; 23545222b9eSDavid Howells *_bp = bp; 23645222b9eSDavid Howells } 23745222b9eSDavid Howells 23845222b9eSDavid Howells /* 23908e0e7c8SDavid Howells * deliver reply data to an FS.FetchStatus 24008e0e7c8SDavid Howells */ 2415cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) 24208e0e7c8SDavid Howells { 24308e0e7c8SDavid Howells const __be32 *bp; 244372ee163SDavid Howells int ret; 2451da177e4SLinus Torvalds 246d001648eSDavid Howells ret = afs_transfer_reply(call); 247372ee163SDavid Howells if (ret < 0) 248372ee163SDavid Howells return ret; 2491da177e4SLinus Torvalds 25008e0e7c8SDavid Howells /* unmarshall the reply once we've received all of it */ 25108e0e7c8SDavid Howells bp = call->buffer; 252a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 253160cb957SDavid Howells if (ret < 0) 254160cb957SDavid Howells return ret; 255a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 256ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2571da177e4SLinus Torvalds 25808e0e7c8SDavid Howells _leave(" = 0 [done]"); 25908e0e7c8SDavid Howells return 0; 260ec26815aSDavid Howells } 26108e0e7c8SDavid Howells 26208e0e7c8SDavid Howells /* 26308e0e7c8SDavid Howells * FS.FetchStatus operation type 26408e0e7c8SDavid Howells */ 2655cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus_vnode = { 2665cf9dd55SDavid Howells .name = "FS.FetchStatus(vnode)", 267025db80cSDavid Howells .op = afs_FS_FetchStatus, 2685cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status_vnode, 26908e0e7c8SDavid Howells .destructor = afs_flat_call_destructor, 27008e0e7c8SDavid Howells }; 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds /* 2731da177e4SLinus Torvalds * fetch the status information for a file 2741da177e4SLinus Torvalds */ 275a58823acSDavid Howells int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb, 276a58823acSDavid Howells struct afs_volsync *volsync) 2771da177e4SLinus Torvalds { 278d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 27908e0e7c8SDavid Howells struct afs_call *call; 280f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 2811da177e4SLinus Torvalds __be32 *bp; 2821da177e4SLinus Torvalds 28330062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 284a58823acSDavid Howells return yfs_fs_fetch_file_status(fc, scb, volsync); 28530062bd1SDavid Howells 2863b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 287d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2881da177e4SLinus Torvalds 2895cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode, 2905cf9dd55SDavid Howells 16, (21 + 3 + 6) * 4); 291d2ddc776SDavid Howells if (!call) { 292d2ddc776SDavid Howells fc->ac.error = -ENOMEM; 29308e0e7c8SDavid Howells return -ENOMEM; 294d2ddc776SDavid Howells } 2951da177e4SLinus Torvalds 296d2ddc776SDavid Howells call->key = fc->key; 297a58823acSDavid Howells call->out_scb = scb; 298ffba718eSDavid Howells call->out_volsync = volsync; 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds /* marshall the parameters */ 30108e0e7c8SDavid Howells bp = call->request; 3021da177e4SLinus Torvalds bp[0] = htonl(FSFETCHSTATUS); 3031da177e4SLinus Torvalds bp[1] = htonl(vnode->fid.vid); 3041da177e4SLinus Torvalds bp[2] = htonl(vnode->fid.vnode); 3051da177e4SLinus Torvalds bp[3] = htonl(vnode->fid.unique); 3061da177e4SLinus Torvalds 307d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 308025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 3090b9bf381SDavid Howells 31020b8391fSDavid Howells afs_set_fc_call(call, fc); 3110b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 3120b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 313ec26815aSDavid Howells } 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds /* 31608e0e7c8SDavid Howells * deliver reply data to an FS.FetchData 3171da177e4SLinus Torvalds */ 318d001648eSDavid Howells static int afs_deliver_fs_fetch_data(struct afs_call *call) 3191da177e4SLinus Torvalds { 320ffba718eSDavid Howells struct afs_read *req = call->read_request; 32108e0e7c8SDavid Howells const __be32 *bp; 322196ee9cdSDavid Howells unsigned int size; 3231da177e4SLinus Torvalds int ret; 3241da177e4SLinus Torvalds 32512bdcf33SDavid Howells _enter("{%u,%zu/%llu}", 326fc276122SDavid Howells call->unmarshall, iov_iter_count(call->iter), req->actual_len); 3271da177e4SLinus Torvalds 32808e0e7c8SDavid Howells switch (call->unmarshall) { 32908e0e7c8SDavid Howells case 0: 330196ee9cdSDavid Howells req->actual_len = 0; 33112bdcf33SDavid Howells req->index = 0; 33212bdcf33SDavid Howells req->offset = req->pos & (PAGE_SIZE - 1); 33308e0e7c8SDavid Howells call->unmarshall++; 33412bdcf33SDavid Howells if (call->operation_ID == FSFETCHDATA64) { 33512bdcf33SDavid Howells afs_extract_to_tmp64(call); 33612bdcf33SDavid Howells } else { 33712bdcf33SDavid Howells call->tmp_u = htonl(0); 33812bdcf33SDavid Howells afs_extract_to_tmp(call); 339b9b1f8d5SDavid Howells } 34029881608SGustavo A. R. Silva /* Fall through */ 3411da177e4SLinus Torvalds 34229881608SGustavo A. R. Silva /* extract the returned data length */ 34312bdcf33SDavid Howells case 1: 34408e0e7c8SDavid Howells _debug("extract data length"); 34512bdcf33SDavid Howells ret = afs_extract_data(call, true); 346372ee163SDavid Howells if (ret < 0) 347372ee163SDavid Howells return ret; 3481da177e4SLinus Torvalds 34912bdcf33SDavid Howells req->actual_len = be64_to_cpu(call->tmp64); 350196ee9cdSDavid Howells _debug("DATA length: %llu", req->actual_len); 35112bdcf33SDavid Howells req->remain = min(req->len, req->actual_len); 35212bdcf33SDavid Howells if (req->remain == 0) 353196ee9cdSDavid Howells goto no_more_data; 35412bdcf33SDavid Howells 35508e0e7c8SDavid Howells call->unmarshall++; 3561da177e4SLinus Torvalds 357196ee9cdSDavid Howells begin_page: 3586db3ac3cSDavid Howells ASSERTCMP(req->index, <, req->nr_pages); 35912bdcf33SDavid Howells if (req->remain > PAGE_SIZE - req->offset) 36012bdcf33SDavid Howells size = PAGE_SIZE - req->offset; 361196ee9cdSDavid Howells else 362196ee9cdSDavid Howells size = req->remain; 36312bdcf33SDavid Howells call->bvec[0].bv_len = size; 36412bdcf33SDavid Howells call->bvec[0].bv_offset = req->offset; 36512bdcf33SDavid Howells call->bvec[0].bv_page = req->pages[req->index]; 366fc276122SDavid Howells iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); 36712bdcf33SDavid Howells ASSERTCMP(size, <=, PAGE_SIZE); 36829881608SGustavo A. R. Silva /* Fall through */ 369196ee9cdSDavid Howells 37029881608SGustavo A. R. Silva /* extract the returned data */ 37112bdcf33SDavid Howells case 2: 37212bdcf33SDavid Howells _debug("extract data %zu/%llu", 373fc276122SDavid Howells iov_iter_count(call->iter), req->remain); 374196ee9cdSDavid Howells 37512bdcf33SDavid Howells ret = afs_extract_data(call, true); 376372ee163SDavid Howells if (ret < 0) 377372ee163SDavid Howells return ret; 37812bdcf33SDavid Howells req->remain -= call->bvec[0].bv_len; 37912bdcf33SDavid Howells req->offset += call->bvec[0].bv_len; 38012bdcf33SDavid Howells ASSERTCMP(req->offset, <=, PAGE_SIZE); 38112bdcf33SDavid Howells if (req->offset == PAGE_SIZE) { 38212bdcf33SDavid Howells req->offset = 0; 383196ee9cdSDavid Howells if (req->page_done) 384a58823acSDavid Howells req->page_done(req); 38529f06985SDavid Howells req->index++; 38612bdcf33SDavid Howells if (req->remain > 0) 387196ee9cdSDavid Howells goto begin_page; 388196ee9cdSDavid Howells } 38912bdcf33SDavid Howells 39012bdcf33SDavid Howells ASSERTCMP(req->remain, ==, 0); 39112bdcf33SDavid Howells if (req->actual_len <= req->len) 3926db3ac3cSDavid Howells goto no_more_data; 3936db3ac3cSDavid Howells 3946db3ac3cSDavid Howells /* Discard any excess data the server gave us */ 39523a28913SDavid Howells afs_extract_discard(call, req->actual_len - req->len); 39612bdcf33SDavid Howells call->unmarshall = 3; 397e690c9e3SGustavo A. R. Silva /* Fall through */ 39829881608SGustavo A. R. Silva 39912bdcf33SDavid Howells case 3: 40012bdcf33SDavid Howells _debug("extract discard %zu/%llu", 401fc276122SDavid Howells iov_iter_count(call->iter), req->actual_len - req->len); 4026db3ac3cSDavid Howells 40312bdcf33SDavid Howells ret = afs_extract_data(call, true); 4046db3ac3cSDavid Howells if (ret < 0) 4056db3ac3cSDavid Howells return ret; 4061da177e4SLinus Torvalds 407196ee9cdSDavid Howells no_more_data: 40812bdcf33SDavid Howells call->unmarshall = 4; 40912bdcf33SDavid Howells afs_extract_to_buf(call, (21 + 3 + 6) * 4); 41029881608SGustavo A. R. Silva /* Fall through */ 41108e0e7c8SDavid Howells 41229881608SGustavo A. R. Silva /* extract the metadata */ 41312bdcf33SDavid Howells case 4: 41412bdcf33SDavid Howells ret = afs_extract_data(call, false); 415372ee163SDavid Howells if (ret < 0) 416372ee163SDavid Howells return ret; 4171da177e4SLinus Torvalds 41808e0e7c8SDavid Howells bp = call->buffer; 419a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 420160cb957SDavid Howells if (ret < 0) 421160cb957SDavid Howells return ret; 422a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 423ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 4241da177e4SLinus Torvalds 425a58823acSDavid Howells req->data_version = call->out_scb->status.data_version; 426a58823acSDavid Howells req->file_size = call->out_scb->status.size; 427a58823acSDavid Howells 42808e0e7c8SDavid Howells call->unmarshall++; 4291da177e4SLinus Torvalds 43012bdcf33SDavid Howells case 5: 4311da177e4SLinus Torvalds break; 4321da177e4SLinus Torvalds } 4331da177e4SLinus Torvalds 4346db3ac3cSDavid Howells for (; req->index < req->nr_pages; req->index++) { 43512bdcf33SDavid Howells if (req->offset < PAGE_SIZE) 4366db3ac3cSDavid Howells zero_user_segment(req->pages[req->index], 43712bdcf33SDavid Howells req->offset, PAGE_SIZE); 438196ee9cdSDavid Howells if (req->page_done) 439a58823acSDavid Howells req->page_done(req); 44012bdcf33SDavid Howells req->offset = 0; 441416351f2SDavid Howells } 442416351f2SDavid Howells 44308e0e7c8SDavid Howells _leave(" = 0 [done]"); 44408e0e7c8SDavid Howells return 0; 445ec26815aSDavid Howells } 4461da177e4SLinus Torvalds 447196ee9cdSDavid Howells static void afs_fetch_data_destructor(struct afs_call *call) 448196ee9cdSDavid Howells { 449ffba718eSDavid Howells struct afs_read *req = call->read_request; 450196ee9cdSDavid Howells 451196ee9cdSDavid Howells afs_put_read(req); 452196ee9cdSDavid Howells afs_flat_call_destructor(call); 453196ee9cdSDavid Howells } 454196ee9cdSDavid Howells 4551da177e4SLinus Torvalds /* 45608e0e7c8SDavid Howells * FS.FetchData operation type 4571da177e4SLinus Torvalds */ 45808e0e7c8SDavid Howells static const struct afs_call_type afs_RXFSFetchData = { 45900d3b7a4SDavid Howells .name = "FS.FetchData", 460025db80cSDavid Howells .op = afs_FS_FetchData, 46108e0e7c8SDavid Howells .deliver = afs_deliver_fs_fetch_data, 462196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 46308e0e7c8SDavid Howells }; 46408e0e7c8SDavid Howells 465b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSFetchData64 = { 466b9b1f8d5SDavid Howells .name = "FS.FetchData64", 467025db80cSDavid Howells .op = afs_FS_FetchData64, 468b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_fetch_data, 469196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 470b9b1f8d5SDavid Howells }; 471b9b1f8d5SDavid Howells 472b9b1f8d5SDavid Howells /* 473b9b1f8d5SDavid Howells * fetch data from a very large file 474b9b1f8d5SDavid Howells */ 475a58823acSDavid Howells static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, 476a58823acSDavid Howells struct afs_status_cb *scb, 477a58823acSDavid Howells struct afs_read *req) 478b9b1f8d5SDavid Howells { 479d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 480b9b1f8d5SDavid Howells struct afs_call *call; 481f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 482b9b1f8d5SDavid Howells __be32 *bp; 483b9b1f8d5SDavid Howells 484b9b1f8d5SDavid Howells _enter(""); 485b9b1f8d5SDavid Howells 486f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4); 487b9b1f8d5SDavid Howells if (!call) 488b9b1f8d5SDavid Howells return -ENOMEM; 489b9b1f8d5SDavid Howells 490d2ddc776SDavid Howells call->key = fc->key; 491a58823acSDavid Howells call->out_scb = scb; 492ffba718eSDavid Howells call->out_volsync = NULL; 493d4438a25SDavid Howells call->read_request = afs_get_read(req); 494b9b1f8d5SDavid Howells 495b9b1f8d5SDavid Howells /* marshall the parameters */ 496b9b1f8d5SDavid Howells bp = call->request; 497b9b1f8d5SDavid Howells bp[0] = htonl(FSFETCHDATA64); 498b9b1f8d5SDavid Howells bp[1] = htonl(vnode->fid.vid); 499b9b1f8d5SDavid Howells bp[2] = htonl(vnode->fid.vnode); 500b9b1f8d5SDavid Howells bp[3] = htonl(vnode->fid.unique); 501196ee9cdSDavid Howells bp[4] = htonl(upper_32_bits(req->pos)); 502196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->pos)); 503b9b1f8d5SDavid Howells bp[6] = 0; 504196ee9cdSDavid Howells bp[7] = htonl(lower_32_bits(req->len)); 505b9b1f8d5SDavid Howells 506d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 507025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 50820b8391fSDavid Howells afs_set_fc_call(call, fc); 5090b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5100b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 511b9b1f8d5SDavid Howells } 512b9b1f8d5SDavid Howells 51308e0e7c8SDavid Howells /* 51408e0e7c8SDavid Howells * fetch data from a file 51508e0e7c8SDavid Howells */ 516a58823acSDavid Howells int afs_fs_fetch_data(struct afs_fs_cursor *fc, 517a58823acSDavid Howells struct afs_status_cb *scb, 518a58823acSDavid Howells struct afs_read *req) 5191da177e4SLinus Torvalds { 520d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 52108e0e7c8SDavid Howells struct afs_call *call; 522f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 52308e0e7c8SDavid Howells __be32 *bp; 5241da177e4SLinus Torvalds 52530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 526a58823acSDavid Howells return yfs_fs_fetch_data(fc, scb, req); 52730062bd1SDavid Howells 528196ee9cdSDavid Howells if (upper_32_bits(req->pos) || 529196ee9cdSDavid Howells upper_32_bits(req->len) || 530196ee9cdSDavid Howells upper_32_bits(req->pos + req->len)) 531a58823acSDavid Howells return afs_fs_fetch_data64(fc, scb, req); 532b9b1f8d5SDavid Howells 53308e0e7c8SDavid Howells _enter(""); 5341da177e4SLinus Torvalds 535f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4); 53608e0e7c8SDavid Howells if (!call) 53708e0e7c8SDavid Howells return -ENOMEM; 5381da177e4SLinus Torvalds 539d2ddc776SDavid Howells call->key = fc->key; 540a58823acSDavid Howells call->out_scb = scb; 541ffba718eSDavid Howells call->out_volsync = NULL; 542d4438a25SDavid Howells call->read_request = afs_get_read(req); 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds /* marshall the parameters */ 54508e0e7c8SDavid Howells bp = call->request; 54608e0e7c8SDavid Howells bp[0] = htonl(FSFETCHDATA); 54708e0e7c8SDavid Howells bp[1] = htonl(vnode->fid.vid); 54808e0e7c8SDavid Howells bp[2] = htonl(vnode->fid.vnode); 54908e0e7c8SDavid Howells bp[3] = htonl(vnode->fid.unique); 550196ee9cdSDavid Howells bp[4] = htonl(lower_32_bits(req->pos)); 551196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->len)); 5521da177e4SLinus Torvalds 553d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 554025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 55520b8391fSDavid Howells afs_set_fc_call(call, fc); 5560b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5570b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 55808e0e7c8SDavid Howells } 559260a9803SDavid Howells 560260a9803SDavid Howells /* 561260a9803SDavid Howells * deliver reply data to an FS.CreateFile or an FS.MakeDir 562260a9803SDavid Howells */ 563d001648eSDavid Howells static int afs_deliver_fs_create_vnode(struct afs_call *call) 564260a9803SDavid Howells { 565260a9803SDavid Howells const __be32 *bp; 566372ee163SDavid Howells int ret; 567260a9803SDavid Howells 568d001648eSDavid Howells ret = afs_transfer_reply(call); 569372ee163SDavid Howells if (ret < 0) 570372ee163SDavid Howells return ret; 571260a9803SDavid Howells 572260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 573260a9803SDavid Howells bp = call->buffer; 574ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 575a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 576160cb957SDavid Howells if (ret < 0) 577160cb957SDavid Howells return ret; 578a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 579160cb957SDavid Howells if (ret < 0) 580160cb957SDavid Howells return ret; 581a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 582ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 583260a9803SDavid Howells 584260a9803SDavid Howells _leave(" = 0 [done]"); 585260a9803SDavid Howells return 0; 586260a9803SDavid Howells } 587260a9803SDavid Howells 588260a9803SDavid Howells /* 589260a9803SDavid Howells * FS.CreateFile and FS.MakeDir operation type 590260a9803SDavid Howells */ 591025db80cSDavid Howells static const struct afs_call_type afs_RXFSCreateFile = { 592025db80cSDavid Howells .name = "FS.CreateFile", 593025db80cSDavid Howells .op = afs_FS_CreateFile, 594025db80cSDavid Howells .deliver = afs_deliver_fs_create_vnode, 595025db80cSDavid Howells .destructor = afs_flat_call_destructor, 596025db80cSDavid Howells }; 597025db80cSDavid Howells 598025db80cSDavid Howells static const struct afs_call_type afs_RXFSMakeDir = { 599025db80cSDavid Howells .name = "FS.MakeDir", 600025db80cSDavid Howells .op = afs_FS_MakeDir, 601260a9803SDavid Howells .deliver = afs_deliver_fs_create_vnode, 602260a9803SDavid Howells .destructor = afs_flat_call_destructor, 603260a9803SDavid Howells }; 604260a9803SDavid Howells 605260a9803SDavid Howells /* 606260a9803SDavid Howells * create a file or make a directory 607260a9803SDavid Howells */ 6088b2a464cSDavid Howells int afs_fs_create(struct afs_fs_cursor *fc, 609260a9803SDavid Howells const char *name, 610260a9803SDavid Howells umode_t mode, 611a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 612260a9803SDavid Howells struct afs_fid *newfid, 613a58823acSDavid Howells struct afs_status_cb *new_scb) 614260a9803SDavid Howells { 615ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 616260a9803SDavid Howells struct afs_call *call; 617ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 618260a9803SDavid Howells size_t namesz, reqsz, padsz; 619260a9803SDavid Howells __be32 *bp; 620260a9803SDavid Howells 62130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){ 62230062bd1SDavid Howells if (S_ISDIR(mode)) 623a58823acSDavid Howells return yfs_fs_make_dir(fc, name, mode, dvnode_scb, 624a58823acSDavid Howells newfid, new_scb); 62530062bd1SDavid Howells else 626a58823acSDavid Howells return yfs_fs_create_file(fc, name, mode, dvnode_scb, 627a58823acSDavid Howells newfid, new_scb); 62830062bd1SDavid Howells } 62930062bd1SDavid Howells 630260a9803SDavid Howells _enter(""); 631260a9803SDavid Howells 632260a9803SDavid Howells namesz = strlen(name); 633260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 634260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (6 * 4); 635260a9803SDavid Howells 636025db80cSDavid Howells call = afs_alloc_flat_call( 637025db80cSDavid Howells net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile, 638025db80cSDavid Howells reqsz, (3 + 21 + 21 + 3 + 6) * 4); 639260a9803SDavid Howells if (!call) 640260a9803SDavid Howells return -ENOMEM; 641260a9803SDavid Howells 642d2ddc776SDavid Howells call->key = fc->key; 643a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 644ffba718eSDavid Howells call->out_fid = newfid; 645a58823acSDavid Howells call->out_scb = new_scb; 646260a9803SDavid Howells 647260a9803SDavid Howells /* marshall the parameters */ 648260a9803SDavid Howells bp = call->request; 649260a9803SDavid Howells *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); 650ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 651ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 652ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 653260a9803SDavid Howells *bp++ = htonl(namesz); 654260a9803SDavid Howells memcpy(bp, name, namesz); 655260a9803SDavid Howells bp = (void *) bp + namesz; 656260a9803SDavid Howells if (padsz > 0) { 657260a9803SDavid Howells memset(bp, 0, padsz); 658260a9803SDavid Howells bp = (void *) bp + padsz; 659260a9803SDavid Howells } 660ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 661ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 662260a9803SDavid Howells *bp++ = 0; /* owner */ 663260a9803SDavid Howells *bp++ = 0; /* group */ 664260a9803SDavid Howells *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ 665260a9803SDavid Howells *bp++ = 0; /* segment size */ 666260a9803SDavid Howells 667d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 668ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 66920b8391fSDavid Howells afs_set_fc_call(call, fc); 6700b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 6710b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 672260a9803SDavid Howells } 673260a9803SDavid Howells 674260a9803SDavid Howells /* 675ffba718eSDavid Howells * Deliver reply data to any operation that returns directory status and volume 676b10494afSJoe Gorse * sync. 677260a9803SDavid Howells */ 678ffba718eSDavid Howells static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call) 679260a9803SDavid Howells { 680260a9803SDavid Howells const __be32 *bp; 681372ee163SDavid Howells int ret; 682260a9803SDavid Howells 683d001648eSDavid Howells ret = afs_transfer_reply(call); 684372ee163SDavid Howells if (ret < 0) 685372ee163SDavid Howells return ret; 686260a9803SDavid Howells 687260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 688260a9803SDavid Howells bp = call->buffer; 689a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 690160cb957SDavid Howells if (ret < 0) 691160cb957SDavid Howells return ret; 692ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 693260a9803SDavid Howells 694260a9803SDavid Howells _leave(" = 0 [done]"); 695260a9803SDavid Howells return 0; 696260a9803SDavid Howells } 697260a9803SDavid Howells 698260a9803SDavid Howells /* 699260a9803SDavid Howells * FS.RemoveDir/FS.RemoveFile operation type 700260a9803SDavid Howells */ 701025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveFile = { 702025db80cSDavid Howells .name = "FS.RemoveFile", 703025db80cSDavid Howells .op = afs_FS_RemoveFile, 704ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 705025db80cSDavid Howells .destructor = afs_flat_call_destructor, 706025db80cSDavid Howells }; 707025db80cSDavid Howells 708025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveDir = { 709025db80cSDavid Howells .name = "FS.RemoveDir", 710025db80cSDavid Howells .op = afs_FS_RemoveDir, 711ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 712260a9803SDavid Howells .destructor = afs_flat_call_destructor, 713260a9803SDavid Howells }; 714260a9803SDavid Howells 715260a9803SDavid Howells /* 716260a9803SDavid Howells * remove a file or directory 717260a9803SDavid Howells */ 71830062bd1SDavid Howells int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 719a58823acSDavid Howells const char *name, bool isdir, struct afs_status_cb *dvnode_scb) 720260a9803SDavid Howells { 72130062bd1SDavid Howells struct afs_vnode *dvnode = fc->vnode; 722260a9803SDavid Howells struct afs_call *call; 72330062bd1SDavid Howells struct afs_net *net = afs_v2net(dvnode); 724260a9803SDavid Howells size_t namesz, reqsz, padsz; 725260a9803SDavid Howells __be32 *bp; 726260a9803SDavid Howells 72730062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 728a58823acSDavid Howells return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb); 72930062bd1SDavid Howells 730260a9803SDavid Howells _enter(""); 731260a9803SDavid Howells 732260a9803SDavid Howells namesz = strlen(name); 733260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 734260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz; 735260a9803SDavid Howells 736025db80cSDavid Howells call = afs_alloc_flat_call( 737025db80cSDavid Howells net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile, 738025db80cSDavid Howells reqsz, (21 + 6) * 4); 739260a9803SDavid Howells if (!call) 740260a9803SDavid Howells return -ENOMEM; 741260a9803SDavid Howells 742d2ddc776SDavid Howells call->key = fc->key; 743a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 744260a9803SDavid Howells 745260a9803SDavid Howells /* marshall the parameters */ 746260a9803SDavid Howells bp = call->request; 747260a9803SDavid Howells *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); 74830062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vid); 74930062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 75030062bd1SDavid Howells *bp++ = htonl(dvnode->fid.unique); 751260a9803SDavid Howells *bp++ = htonl(namesz); 752260a9803SDavid Howells memcpy(bp, name, namesz); 753260a9803SDavid Howells bp = (void *) bp + namesz; 754260a9803SDavid Howells if (padsz > 0) { 755260a9803SDavid Howells memset(bp, 0, padsz); 756260a9803SDavid Howells bp = (void *) bp + padsz; 757260a9803SDavid Howells } 758260a9803SDavid Howells 759d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 76080548b03SDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 76120b8391fSDavid Howells afs_set_fc_call(call, fc); 7620b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 7630b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 764260a9803SDavid Howells } 765260a9803SDavid Howells 766260a9803SDavid Howells /* 767260a9803SDavid Howells * deliver reply data to an FS.Link 768260a9803SDavid Howells */ 769d001648eSDavid Howells static int afs_deliver_fs_link(struct afs_call *call) 770260a9803SDavid Howells { 771260a9803SDavid Howells const __be32 *bp; 772372ee163SDavid Howells int ret; 773260a9803SDavid Howells 774d001648eSDavid Howells _enter("{%u}", call->unmarshall); 775260a9803SDavid Howells 776d001648eSDavid Howells ret = afs_transfer_reply(call); 777372ee163SDavid Howells if (ret < 0) 778372ee163SDavid Howells return ret; 779260a9803SDavid Howells 780260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 781260a9803SDavid Howells bp = call->buffer; 782a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 783160cb957SDavid Howells if (ret < 0) 784160cb957SDavid Howells return ret; 785a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 786160cb957SDavid Howells if (ret < 0) 787160cb957SDavid Howells return ret; 788ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 789260a9803SDavid Howells 790260a9803SDavid Howells _leave(" = 0 [done]"); 791260a9803SDavid Howells return 0; 792260a9803SDavid Howells } 793260a9803SDavid Howells 794260a9803SDavid Howells /* 795260a9803SDavid Howells * FS.Link operation type 796260a9803SDavid Howells */ 797260a9803SDavid Howells static const struct afs_call_type afs_RXFSLink = { 798260a9803SDavid Howells .name = "FS.Link", 799025db80cSDavid Howells .op = afs_FS_Link, 800260a9803SDavid Howells .deliver = afs_deliver_fs_link, 801260a9803SDavid Howells .destructor = afs_flat_call_destructor, 802260a9803SDavid Howells }; 803260a9803SDavid Howells 804260a9803SDavid Howells /* 805260a9803SDavid Howells * make a hard link 806260a9803SDavid Howells */ 807d2ddc776SDavid Howells int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 808a58823acSDavid Howells const char *name, 809a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 810a58823acSDavid Howells struct afs_status_cb *vnode_scb) 811260a9803SDavid Howells { 812d2ddc776SDavid Howells struct afs_vnode *dvnode = fc->vnode; 813260a9803SDavid Howells struct afs_call *call; 814f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 815260a9803SDavid Howells size_t namesz, reqsz, padsz; 816260a9803SDavid Howells __be32 *bp; 817260a9803SDavid Howells 81830062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 819a58823acSDavid Howells return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb); 82030062bd1SDavid Howells 821260a9803SDavid Howells _enter(""); 822260a9803SDavid Howells 823260a9803SDavid Howells namesz = strlen(name); 824260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 825260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (3 * 4); 826260a9803SDavid Howells 827f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4); 828260a9803SDavid Howells if (!call) 829260a9803SDavid Howells return -ENOMEM; 830260a9803SDavid Howells 831d2ddc776SDavid Howells call->key = fc->key; 832a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 833a58823acSDavid Howells call->out_scb = vnode_scb; 834260a9803SDavid Howells 835260a9803SDavid Howells /* marshall the parameters */ 836260a9803SDavid Howells bp = call->request; 837260a9803SDavid Howells *bp++ = htonl(FSLINK); 838260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vid); 839260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 840260a9803SDavid Howells *bp++ = htonl(dvnode->fid.unique); 841260a9803SDavid Howells *bp++ = htonl(namesz); 842260a9803SDavid Howells memcpy(bp, name, namesz); 843260a9803SDavid Howells bp = (void *) bp + namesz; 844260a9803SDavid Howells if (padsz > 0) { 845260a9803SDavid Howells memset(bp, 0, padsz); 846260a9803SDavid Howells bp = (void *) bp + padsz; 847260a9803SDavid Howells } 848260a9803SDavid Howells *bp++ = htonl(vnode->fid.vid); 849260a9803SDavid Howells *bp++ = htonl(vnode->fid.vnode); 850260a9803SDavid Howells *bp++ = htonl(vnode->fid.unique); 851260a9803SDavid Howells 852d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 85380548b03SDavid Howells trace_afs_make_fs_call1(call, &vnode->fid, name); 85420b8391fSDavid Howells afs_set_fc_call(call, fc); 8550b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 8560b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 857260a9803SDavid Howells } 858260a9803SDavid Howells 859260a9803SDavid Howells /* 860260a9803SDavid Howells * deliver reply data to an FS.Symlink 861260a9803SDavid Howells */ 862d001648eSDavid Howells static int afs_deliver_fs_symlink(struct afs_call *call) 863260a9803SDavid Howells { 864260a9803SDavid Howells const __be32 *bp; 865372ee163SDavid Howells int ret; 866260a9803SDavid Howells 867d001648eSDavid Howells _enter("{%u}", call->unmarshall); 868260a9803SDavid Howells 869d001648eSDavid Howells ret = afs_transfer_reply(call); 870372ee163SDavid Howells if (ret < 0) 871372ee163SDavid Howells return ret; 872260a9803SDavid Howells 873260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 874260a9803SDavid Howells bp = call->buffer; 875ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 876a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 877160cb957SDavid Howells if (ret < 0) 878160cb957SDavid Howells return ret; 879a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 880160cb957SDavid Howells if (ret < 0) 881160cb957SDavid Howells return ret; 882ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 883260a9803SDavid Howells 884260a9803SDavid Howells _leave(" = 0 [done]"); 885260a9803SDavid Howells return 0; 886260a9803SDavid Howells } 887260a9803SDavid Howells 888260a9803SDavid Howells /* 889260a9803SDavid Howells * FS.Symlink operation type 890260a9803SDavid Howells */ 891260a9803SDavid Howells static const struct afs_call_type afs_RXFSSymlink = { 892260a9803SDavid Howells .name = "FS.Symlink", 893025db80cSDavid Howells .op = afs_FS_Symlink, 894260a9803SDavid Howells .deliver = afs_deliver_fs_symlink, 895260a9803SDavid Howells .destructor = afs_flat_call_destructor, 896260a9803SDavid Howells }; 897260a9803SDavid Howells 898260a9803SDavid Howells /* 899260a9803SDavid Howells * create a symbolic link 900260a9803SDavid Howells */ 9018b2a464cSDavid Howells int afs_fs_symlink(struct afs_fs_cursor *fc, 902260a9803SDavid Howells const char *name, 903260a9803SDavid Howells const char *contents, 904a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 905260a9803SDavid Howells struct afs_fid *newfid, 906a58823acSDavid Howells struct afs_status_cb *new_scb) 907260a9803SDavid Howells { 908ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 909260a9803SDavid Howells struct afs_call *call; 910ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 911260a9803SDavid Howells size_t namesz, reqsz, padsz, c_namesz, c_padsz; 912260a9803SDavid Howells __be32 *bp; 913260a9803SDavid Howells 91430062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 915a58823acSDavid Howells return yfs_fs_symlink(fc, name, contents, dvnode_scb, 916a58823acSDavid Howells newfid, new_scb); 91730062bd1SDavid Howells 918260a9803SDavid Howells _enter(""); 919260a9803SDavid Howells 920260a9803SDavid Howells namesz = strlen(name); 921260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 922260a9803SDavid Howells 923260a9803SDavid Howells c_namesz = strlen(contents); 924260a9803SDavid Howells c_padsz = (4 - (c_namesz & 3)) & 3; 925260a9803SDavid Howells 926260a9803SDavid Howells reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4); 927260a9803SDavid Howells 928f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz, 929260a9803SDavid Howells (3 + 21 + 21 + 6) * 4); 930260a9803SDavid Howells if (!call) 931260a9803SDavid Howells return -ENOMEM; 932260a9803SDavid Howells 933d2ddc776SDavid Howells call->key = fc->key; 934a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 935ffba718eSDavid Howells call->out_fid = newfid; 936a58823acSDavid Howells call->out_scb = new_scb; 937260a9803SDavid Howells 938260a9803SDavid Howells /* marshall the parameters */ 939260a9803SDavid Howells bp = call->request; 940260a9803SDavid Howells *bp++ = htonl(FSSYMLINK); 941ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 942ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 943ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 944260a9803SDavid Howells *bp++ = htonl(namesz); 945260a9803SDavid Howells memcpy(bp, name, namesz); 946260a9803SDavid Howells bp = (void *) bp + namesz; 947260a9803SDavid Howells if (padsz > 0) { 948260a9803SDavid Howells memset(bp, 0, padsz); 949260a9803SDavid Howells bp = (void *) bp + padsz; 950260a9803SDavid Howells } 951260a9803SDavid Howells *bp++ = htonl(c_namesz); 952260a9803SDavid Howells memcpy(bp, contents, c_namesz); 953260a9803SDavid Howells bp = (void *) bp + c_namesz; 954260a9803SDavid Howells if (c_padsz > 0) { 955260a9803SDavid Howells memset(bp, 0, c_padsz); 956260a9803SDavid Howells bp = (void *) bp + c_padsz; 957260a9803SDavid Howells } 958ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 959ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 960260a9803SDavid Howells *bp++ = 0; /* owner */ 961260a9803SDavid Howells *bp++ = 0; /* group */ 962260a9803SDavid Howells *bp++ = htonl(S_IRWXUGO); /* unix mode */ 963260a9803SDavid Howells *bp++ = 0; /* segment size */ 964260a9803SDavid Howells 965d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 966ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 96720b8391fSDavid Howells afs_set_fc_call(call, fc); 9680b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 9690b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 970260a9803SDavid Howells } 971260a9803SDavid Howells 972260a9803SDavid Howells /* 973260a9803SDavid Howells * deliver reply data to an FS.Rename 974260a9803SDavid Howells */ 975d001648eSDavid Howells static int afs_deliver_fs_rename(struct afs_call *call) 976260a9803SDavid Howells { 977260a9803SDavid Howells const __be32 *bp; 978372ee163SDavid Howells int ret; 979260a9803SDavid Howells 980d001648eSDavid Howells ret = afs_transfer_reply(call); 981372ee163SDavid Howells if (ret < 0) 982372ee163SDavid Howells return ret; 983260a9803SDavid Howells 984260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 985260a9803SDavid Howells bp = call->buffer; 986a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 987160cb957SDavid Howells if (ret < 0) 988160cb957SDavid Howells return ret; 989a58823acSDavid Howells if (call->out_dir_scb != call->out_scb) { 990a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 991160cb957SDavid Howells if (ret < 0) 992160cb957SDavid Howells return ret; 993160cb957SDavid Howells } 994ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 995260a9803SDavid Howells 996260a9803SDavid Howells _leave(" = 0 [done]"); 997260a9803SDavid Howells return 0; 998260a9803SDavid Howells } 999260a9803SDavid Howells 1000260a9803SDavid Howells /* 1001260a9803SDavid Howells * FS.Rename operation type 1002260a9803SDavid Howells */ 1003260a9803SDavid Howells static const struct afs_call_type afs_RXFSRename = { 1004260a9803SDavid Howells .name = "FS.Rename", 1005025db80cSDavid Howells .op = afs_FS_Rename, 1006260a9803SDavid Howells .deliver = afs_deliver_fs_rename, 1007260a9803SDavid Howells .destructor = afs_flat_call_destructor, 1008260a9803SDavid Howells }; 1009260a9803SDavid Howells 1010260a9803SDavid Howells /* 1011a58823acSDavid Howells * Rename/move a file or directory. 1012260a9803SDavid Howells */ 10138b2a464cSDavid Howells int afs_fs_rename(struct afs_fs_cursor *fc, 1014260a9803SDavid Howells const char *orig_name, 1015260a9803SDavid Howells struct afs_vnode *new_dvnode, 101663a4681fSDavid Howells const char *new_name, 1017a58823acSDavid Howells struct afs_status_cb *orig_dvnode_scb, 1018a58823acSDavid Howells struct afs_status_cb *new_dvnode_scb) 1019260a9803SDavid Howells { 1020d2ddc776SDavid Howells struct afs_vnode *orig_dvnode = fc->vnode; 1021260a9803SDavid Howells struct afs_call *call; 1022f044c884SDavid Howells struct afs_net *net = afs_v2net(orig_dvnode); 1023260a9803SDavid Howells size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; 1024260a9803SDavid Howells __be32 *bp; 1025260a9803SDavid Howells 102630062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 102730062bd1SDavid Howells return yfs_fs_rename(fc, orig_name, 102830062bd1SDavid Howells new_dvnode, new_name, 1029a58823acSDavid Howells orig_dvnode_scb, 1030a58823acSDavid Howells new_dvnode_scb); 103130062bd1SDavid Howells 1032260a9803SDavid Howells _enter(""); 1033260a9803SDavid Howells 1034260a9803SDavid Howells o_namesz = strlen(orig_name); 1035260a9803SDavid Howells o_padsz = (4 - (o_namesz & 3)) & 3; 1036260a9803SDavid Howells 1037260a9803SDavid Howells n_namesz = strlen(new_name); 1038260a9803SDavid Howells n_padsz = (4 - (n_namesz & 3)) & 3; 1039260a9803SDavid Howells 1040260a9803SDavid Howells reqsz = (4 * 4) + 1041260a9803SDavid Howells 4 + o_namesz + o_padsz + 1042260a9803SDavid Howells (3 * 4) + 1043260a9803SDavid Howells 4 + n_namesz + n_padsz; 1044260a9803SDavid Howells 1045f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4); 1046260a9803SDavid Howells if (!call) 1047260a9803SDavid Howells return -ENOMEM; 1048260a9803SDavid Howells 1049d2ddc776SDavid Howells call->key = fc->key; 1050a58823acSDavid Howells call->out_dir_scb = orig_dvnode_scb; 1051a58823acSDavid Howells call->out_scb = new_dvnode_scb; 1052260a9803SDavid Howells 1053260a9803SDavid Howells /* marshall the parameters */ 1054260a9803SDavid Howells bp = call->request; 1055260a9803SDavid Howells *bp++ = htonl(FSRENAME); 1056260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vid); 1057260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vnode); 1058260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.unique); 1059260a9803SDavid Howells *bp++ = htonl(o_namesz); 1060260a9803SDavid Howells memcpy(bp, orig_name, o_namesz); 1061260a9803SDavid Howells bp = (void *) bp + o_namesz; 1062260a9803SDavid Howells if (o_padsz > 0) { 1063260a9803SDavid Howells memset(bp, 0, o_padsz); 1064260a9803SDavid Howells bp = (void *) bp + o_padsz; 1065260a9803SDavid Howells } 1066260a9803SDavid Howells 1067260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vid); 1068260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vnode); 1069260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.unique); 1070260a9803SDavid Howells *bp++ = htonl(n_namesz); 1071260a9803SDavid Howells memcpy(bp, new_name, n_namesz); 1072260a9803SDavid Howells bp = (void *) bp + n_namesz; 1073260a9803SDavid Howells if (n_padsz > 0) { 1074260a9803SDavid Howells memset(bp, 0, n_padsz); 1075260a9803SDavid Howells bp = (void *) bp + n_padsz; 1076260a9803SDavid Howells } 1077260a9803SDavid Howells 1078d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 107980548b03SDavid Howells trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name); 108020b8391fSDavid Howells afs_set_fc_call(call, fc); 10810b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 10820b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1083260a9803SDavid Howells } 108431143d5dSDavid Howells 108531143d5dSDavid Howells /* 108631143d5dSDavid Howells * deliver reply data to an FS.StoreData 108731143d5dSDavid Howells */ 1088d001648eSDavid Howells static int afs_deliver_fs_store_data(struct afs_call *call) 108931143d5dSDavid Howells { 109031143d5dSDavid Howells const __be32 *bp; 1091372ee163SDavid Howells int ret; 109231143d5dSDavid Howells 1093d001648eSDavid Howells _enter(""); 109431143d5dSDavid Howells 1095d001648eSDavid Howells ret = afs_transfer_reply(call); 1096372ee163SDavid Howells if (ret < 0) 1097372ee163SDavid Howells return ret; 109831143d5dSDavid Howells 109931143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 110031143d5dSDavid Howells bp = call->buffer; 1101a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1102160cb957SDavid Howells if (ret < 0) 1103160cb957SDavid Howells return ret; 1104ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 110531143d5dSDavid Howells 110631143d5dSDavid Howells _leave(" = 0 [done]"); 110731143d5dSDavid Howells return 0; 110831143d5dSDavid Howells } 110931143d5dSDavid Howells 111031143d5dSDavid Howells /* 111131143d5dSDavid Howells * FS.StoreData operation type 111231143d5dSDavid Howells */ 111331143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData = { 111431143d5dSDavid Howells .name = "FS.StoreData", 1115025db80cSDavid Howells .op = afs_FS_StoreData, 111631143d5dSDavid Howells .deliver = afs_deliver_fs_store_data, 111731143d5dSDavid Howells .destructor = afs_flat_call_destructor, 111831143d5dSDavid Howells }; 111931143d5dSDavid Howells 1120b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64 = { 1121b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1122025db80cSDavid Howells .op = afs_FS_StoreData64, 1123b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_data, 1124b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1125b9b1f8d5SDavid Howells }; 1126b9b1f8d5SDavid Howells 1127b9b1f8d5SDavid Howells /* 1128b9b1f8d5SDavid Howells * store a set of pages to a very large file 1129b9b1f8d5SDavid Howells */ 11308b2a464cSDavid Howells static int afs_fs_store_data64(struct afs_fs_cursor *fc, 11314343d008SDavid Howells struct address_space *mapping, 1132b9b1f8d5SDavid Howells pgoff_t first, pgoff_t last, 1133b9b1f8d5SDavid Howells unsigned offset, unsigned to, 1134a58823acSDavid Howells loff_t size, loff_t pos, loff_t i_size, 1135a58823acSDavid Howells struct afs_status_cb *scb) 1136b9b1f8d5SDavid Howells { 11374343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 1138b9b1f8d5SDavid Howells struct afs_call *call; 1139f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1140b9b1f8d5SDavid Howells __be32 *bp; 1141b9b1f8d5SDavid Howells 11423b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 11434343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1144b9b1f8d5SDavid Howells 1145f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64, 1146b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1147b9b1f8d5SDavid Howells (21 + 6) * 4); 1148b9b1f8d5SDavid Howells if (!call) 1149b9b1f8d5SDavid Howells return -ENOMEM; 1150b9b1f8d5SDavid Howells 11514343d008SDavid Howells call->key = fc->key; 11524343d008SDavid Howells call->mapping = mapping; 1153b9b1f8d5SDavid Howells call->first = first; 1154b9b1f8d5SDavid Howells call->last = last; 1155b9b1f8d5SDavid Howells call->first_offset = offset; 1156b9b1f8d5SDavid Howells call->last_to = to; 1157b9b1f8d5SDavid Howells call->send_pages = true; 1158a58823acSDavid Howells call->out_scb = scb; 1159b9b1f8d5SDavid Howells 1160b9b1f8d5SDavid Howells /* marshall the parameters */ 1161b9b1f8d5SDavid Howells bp = call->request; 1162b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1163b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1164b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1165b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1166b9b1f8d5SDavid Howells 1167ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1168ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 1169b9b1f8d5SDavid Howells *bp++ = 0; /* owner */ 1170b9b1f8d5SDavid Howells *bp++ = 0; /* group */ 1171b9b1f8d5SDavid Howells *bp++ = 0; /* unix mode */ 1172b9b1f8d5SDavid Howells *bp++ = 0; /* segment size */ 1173b9b1f8d5SDavid Howells 1174b9b1f8d5SDavid Howells *bp++ = htonl(pos >> 32); 1175b9b1f8d5SDavid Howells *bp++ = htonl((u32) pos); 1176b9b1f8d5SDavid Howells *bp++ = htonl(size >> 32); 1177b9b1f8d5SDavid Howells *bp++ = htonl((u32) size); 1178b9b1f8d5SDavid Howells *bp++ = htonl(i_size >> 32); 1179b9b1f8d5SDavid Howells *bp++ = htonl((u32) i_size); 1180b9b1f8d5SDavid Howells 1181025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 118220b8391fSDavid Howells afs_set_fc_call(call, fc); 11830b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 11840b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1185b9b1f8d5SDavid Howells } 1186b9b1f8d5SDavid Howells 118731143d5dSDavid Howells /* 118831143d5dSDavid Howells * store a set of pages 118931143d5dSDavid Howells */ 11904343d008SDavid Howells int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, 119131143d5dSDavid Howells pgoff_t first, pgoff_t last, 1192a58823acSDavid Howells unsigned offset, unsigned to, 1193a58823acSDavid Howells struct afs_status_cb *scb) 119431143d5dSDavid Howells { 11954343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 119631143d5dSDavid Howells struct afs_call *call; 1197f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 119831143d5dSDavid Howells loff_t size, pos, i_size; 119931143d5dSDavid Howells __be32 *bp; 120031143d5dSDavid Howells 120130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1202a58823acSDavid Howells return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb); 120330062bd1SDavid Howells 12043b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 12054343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 120631143d5dSDavid Howells 1207146a1192SDavid Howells size = (loff_t)to - (loff_t)offset; 120831143d5dSDavid Howells if (first != last) 120931143d5dSDavid Howells size += (loff_t)(last - first) << PAGE_SHIFT; 121031143d5dSDavid Howells pos = (loff_t)first << PAGE_SHIFT; 121131143d5dSDavid Howells pos += offset; 121231143d5dSDavid Howells 121331143d5dSDavid Howells i_size = i_size_read(&vnode->vfs_inode); 121431143d5dSDavid Howells if (pos + size > i_size) 121531143d5dSDavid Howells i_size = size + pos; 121631143d5dSDavid Howells 121731143d5dSDavid Howells _debug("size %llx, at %llx, i_size %llx", 121831143d5dSDavid Howells (unsigned long long) size, (unsigned long long) pos, 121931143d5dSDavid Howells (unsigned long long) i_size); 122031143d5dSDavid Howells 1221b9b1f8d5SDavid Howells if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32) 12224343d008SDavid Howells return afs_fs_store_data64(fc, mapping, first, last, offset, to, 1223a58823acSDavid Howells size, pos, i_size, scb); 122431143d5dSDavid Howells 1225f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData, 122631143d5dSDavid Howells (4 + 6 + 3) * 4, 122731143d5dSDavid Howells (21 + 6) * 4); 122831143d5dSDavid Howells if (!call) 122931143d5dSDavid Howells return -ENOMEM; 123031143d5dSDavid Howells 12314343d008SDavid Howells call->key = fc->key; 12324343d008SDavid Howells call->mapping = mapping; 123331143d5dSDavid Howells call->first = first; 123431143d5dSDavid Howells call->last = last; 123531143d5dSDavid Howells call->first_offset = offset; 123631143d5dSDavid Howells call->last_to = to; 123731143d5dSDavid Howells call->send_pages = true; 1238a58823acSDavid Howells call->out_scb = scb; 123931143d5dSDavid Howells 124031143d5dSDavid Howells /* marshall the parameters */ 124131143d5dSDavid Howells bp = call->request; 124231143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 124331143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 124431143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 124531143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 124631143d5dSDavid Howells 1247ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1248ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 124931143d5dSDavid Howells *bp++ = 0; /* owner */ 125031143d5dSDavid Howells *bp++ = 0; /* group */ 125131143d5dSDavid Howells *bp++ = 0; /* unix mode */ 125231143d5dSDavid Howells *bp++ = 0; /* segment size */ 125331143d5dSDavid Howells 125431143d5dSDavid Howells *bp++ = htonl(pos); 125531143d5dSDavid Howells *bp++ = htonl(size); 125631143d5dSDavid Howells *bp++ = htonl(i_size); 125731143d5dSDavid Howells 1258d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1259025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 126020b8391fSDavid Howells afs_set_fc_call(call, fc); 12610b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 12620b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 126331143d5dSDavid Howells } 126431143d5dSDavid Howells 126531143d5dSDavid Howells /* 126631143d5dSDavid Howells * deliver reply data to an FS.StoreStatus 126731143d5dSDavid Howells */ 1268d001648eSDavid Howells static int afs_deliver_fs_store_status(struct afs_call *call) 126931143d5dSDavid Howells { 127031143d5dSDavid Howells const __be32 *bp; 1271372ee163SDavid Howells int ret; 127231143d5dSDavid Howells 1273d001648eSDavid Howells _enter(""); 127431143d5dSDavid Howells 1275d001648eSDavid Howells ret = afs_transfer_reply(call); 1276372ee163SDavid Howells if (ret < 0) 1277372ee163SDavid Howells return ret; 127831143d5dSDavid Howells 127931143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 128031143d5dSDavid Howells bp = call->buffer; 1281a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1282160cb957SDavid Howells if (ret < 0) 1283160cb957SDavid Howells return ret; 1284ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 128531143d5dSDavid Howells 128631143d5dSDavid Howells _leave(" = 0 [done]"); 128731143d5dSDavid Howells return 0; 128831143d5dSDavid Howells } 128931143d5dSDavid Howells 129031143d5dSDavid Howells /* 129131143d5dSDavid Howells * FS.StoreStatus operation type 129231143d5dSDavid Howells */ 129331143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreStatus = { 129431143d5dSDavid Howells .name = "FS.StoreStatus", 1295025db80cSDavid Howells .op = afs_FS_StoreStatus, 129631143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 129731143d5dSDavid Howells .destructor = afs_flat_call_destructor, 129831143d5dSDavid Howells }; 129931143d5dSDavid Howells 130031143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData_as_Status = { 130131143d5dSDavid Howells .name = "FS.StoreData", 1302025db80cSDavid Howells .op = afs_FS_StoreData, 130331143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 130431143d5dSDavid Howells .destructor = afs_flat_call_destructor, 130531143d5dSDavid Howells }; 130631143d5dSDavid Howells 1307b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64_as_Status = { 1308b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1309025db80cSDavid Howells .op = afs_FS_StoreData64, 1310b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_status, 1311b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1312b9b1f8d5SDavid Howells }; 1313b9b1f8d5SDavid Howells 1314b9b1f8d5SDavid Howells /* 1315b9b1f8d5SDavid Howells * set the attributes on a very large file, using FS.StoreData rather than 1316b9b1f8d5SDavid Howells * FS.StoreStatus so as to alter the file size also 1317b9b1f8d5SDavid Howells */ 1318a58823acSDavid Howells static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr, 1319a58823acSDavid Howells struct afs_status_cb *scb) 1320b9b1f8d5SDavid Howells { 1321d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1322b9b1f8d5SDavid Howells struct afs_call *call; 1323f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1324b9b1f8d5SDavid Howells __be32 *bp; 1325b9b1f8d5SDavid Howells 13263b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1327d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1328b9b1f8d5SDavid Howells 1329b9b1f8d5SDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1330b9b1f8d5SDavid Howells 1331f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status, 1332b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1333b9b1f8d5SDavid Howells (21 + 6) * 4); 1334b9b1f8d5SDavid Howells if (!call) 1335b9b1f8d5SDavid Howells return -ENOMEM; 1336b9b1f8d5SDavid Howells 1337d2ddc776SDavid Howells call->key = fc->key; 1338a58823acSDavid Howells call->out_scb = scb; 1339b9b1f8d5SDavid Howells 1340b9b1f8d5SDavid Howells /* marshall the parameters */ 1341b9b1f8d5SDavid Howells bp = call->request; 1342b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1343b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1344b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1345b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1346b9b1f8d5SDavid Howells 1347b9b1f8d5SDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 1348b9b1f8d5SDavid Howells 13498c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* position of start of write */ 13508c7ae38dSDavid Howells *bp++ = htonl((u32) attr->ia_size); 1351b9b1f8d5SDavid Howells *bp++ = 0; /* size of write */ 1352b9b1f8d5SDavid Howells *bp++ = 0; 1353b9b1f8d5SDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* new file length */ 1354b9b1f8d5SDavid Howells *bp++ = htonl((u32) attr->ia_size); 1355b9b1f8d5SDavid Howells 1356d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1357025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 135820b8391fSDavid Howells afs_set_fc_call(call, fc); 13590b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 13600b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1361b9b1f8d5SDavid Howells } 1362b9b1f8d5SDavid Howells 136331143d5dSDavid Howells /* 136431143d5dSDavid Howells * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus 136531143d5dSDavid Howells * so as to alter the file size also 136631143d5dSDavid Howells */ 1367a58823acSDavid Howells static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr, 1368a58823acSDavid Howells struct afs_status_cb *scb) 136931143d5dSDavid Howells { 1370d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 137131143d5dSDavid Howells struct afs_call *call; 1372f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 137331143d5dSDavid Howells __be32 *bp; 137431143d5dSDavid Howells 13753b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1376d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 137731143d5dSDavid Howells 137831143d5dSDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1379b9b1f8d5SDavid Howells if (attr->ia_size >> 32) 1380a58823acSDavid Howells return afs_fs_setattr_size64(fc, attr, scb); 138131143d5dSDavid Howells 1382f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status, 138331143d5dSDavid Howells (4 + 6 + 3) * 4, 138431143d5dSDavid Howells (21 + 6) * 4); 138531143d5dSDavid Howells if (!call) 138631143d5dSDavid Howells return -ENOMEM; 138731143d5dSDavid Howells 1388d2ddc776SDavid Howells call->key = fc->key; 1389a58823acSDavid Howells call->out_scb = scb; 139031143d5dSDavid Howells 139131143d5dSDavid Howells /* marshall the parameters */ 139231143d5dSDavid Howells bp = call->request; 139331143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 139431143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 139531143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 139631143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 139731143d5dSDavid Howells 139831143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 139931143d5dSDavid Howells 14008c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size); /* position of start of write */ 140131143d5dSDavid Howells *bp++ = 0; /* size of write */ 140231143d5dSDavid Howells *bp++ = htonl(attr->ia_size); /* new file length */ 140331143d5dSDavid Howells 1404d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1405025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 140620b8391fSDavid Howells afs_set_fc_call(call, fc); 14070b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14080b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 140931143d5dSDavid Howells } 141031143d5dSDavid Howells 141131143d5dSDavid Howells /* 141231143d5dSDavid Howells * set the attributes on a file, using FS.StoreData if there's a change in file 141331143d5dSDavid Howells * size, and FS.StoreStatus otherwise 141431143d5dSDavid Howells */ 1415a58823acSDavid Howells int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr, 1416a58823acSDavid Howells struct afs_status_cb *scb) 141731143d5dSDavid Howells { 1418d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 141931143d5dSDavid Howells struct afs_call *call; 1420f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 142131143d5dSDavid Howells __be32 *bp; 142231143d5dSDavid Howells 142330062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1424a58823acSDavid Howells return yfs_fs_setattr(fc, attr, scb); 142530062bd1SDavid Howells 142631143d5dSDavid Howells if (attr->ia_valid & ATTR_SIZE) 1427a58823acSDavid Howells return afs_fs_setattr_size(fc, attr, scb); 142831143d5dSDavid Howells 14293b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1430d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 143131143d5dSDavid Howells 1432f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus, 143331143d5dSDavid Howells (4 + 6) * 4, 143431143d5dSDavid Howells (21 + 6) * 4); 143531143d5dSDavid Howells if (!call) 143631143d5dSDavid Howells return -ENOMEM; 143731143d5dSDavid Howells 1438d2ddc776SDavid Howells call->key = fc->key; 1439a58823acSDavid Howells call->out_scb = scb; 144031143d5dSDavid Howells 144131143d5dSDavid Howells /* marshall the parameters */ 144231143d5dSDavid Howells bp = call->request; 144331143d5dSDavid Howells *bp++ = htonl(FSSTORESTATUS); 144431143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 144531143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 144631143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 144731143d5dSDavid Howells 144831143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 144931143d5dSDavid Howells 1450d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1451025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 145220b8391fSDavid Howells afs_set_fc_call(call, fc); 14530b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14540b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 145531143d5dSDavid Howells } 145645222b9eSDavid Howells 145745222b9eSDavid Howells /* 145845222b9eSDavid Howells * deliver reply data to an FS.GetVolumeStatus 145945222b9eSDavid Howells */ 1460d001648eSDavid Howells static int afs_deliver_fs_get_volume_status(struct afs_call *call) 146145222b9eSDavid Howells { 146245222b9eSDavid Howells const __be32 *bp; 146345222b9eSDavid Howells char *p; 146412bdcf33SDavid Howells u32 size; 146545222b9eSDavid Howells int ret; 146645222b9eSDavid Howells 1467d001648eSDavid Howells _enter("{%u}", call->unmarshall); 146845222b9eSDavid Howells 146945222b9eSDavid Howells switch (call->unmarshall) { 147045222b9eSDavid Howells case 0: 147145222b9eSDavid Howells call->unmarshall++; 147212bdcf33SDavid Howells afs_extract_to_buf(call, 12 * 4); 147329881608SGustavo A. R. Silva /* Fall through */ 147445222b9eSDavid Howells 147529881608SGustavo A. R. Silva /* extract the returned status record */ 147645222b9eSDavid Howells case 1: 147745222b9eSDavid Howells _debug("extract status"); 147812bdcf33SDavid Howells ret = afs_extract_data(call, true); 1479372ee163SDavid Howells if (ret < 0) 1480372ee163SDavid Howells return ret; 148145222b9eSDavid Howells 148245222b9eSDavid Howells bp = call->buffer; 1483ffba718eSDavid Howells xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus); 148445222b9eSDavid Howells call->unmarshall++; 148512bdcf33SDavid Howells afs_extract_to_tmp(call); 148629881608SGustavo A. R. Silva /* Fall through */ 148745222b9eSDavid Howells 148829881608SGustavo A. R. Silva /* extract the volume name length */ 148945222b9eSDavid Howells case 2: 149012bdcf33SDavid Howells ret = afs_extract_data(call, true); 1491372ee163SDavid Howells if (ret < 0) 1492372ee163SDavid Howells return ret; 149345222b9eSDavid Howells 149445222b9eSDavid Howells call->count = ntohl(call->tmp); 149545222b9eSDavid Howells _debug("volname length: %u", call->count); 149645222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1497160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1498160cb957SDavid Howells afs_eproto_volname_len); 149912bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1500ffba718eSDavid Howells afs_extract_to_buf(call, size); 150145222b9eSDavid Howells call->unmarshall++; 150229881608SGustavo A. R. Silva /* Fall through */ 150345222b9eSDavid Howells 150429881608SGustavo A. R. Silva /* extract the volume name */ 150545222b9eSDavid Howells case 3: 150645222b9eSDavid Howells _debug("extract volname"); 150712bdcf33SDavid Howells ret = afs_extract_data(call, true); 1508372ee163SDavid Howells if (ret < 0) 1509372ee163SDavid Howells return ret; 151045222b9eSDavid Howells 1511ffba718eSDavid Howells p = call->buffer; 151245222b9eSDavid Howells p[call->count] = 0; 151345222b9eSDavid Howells _debug("volname '%s'", p); 151412bdcf33SDavid Howells afs_extract_to_tmp(call); 151545222b9eSDavid Howells call->unmarshall++; 151629881608SGustavo A. R. Silva /* Fall through */ 151745222b9eSDavid Howells 151829881608SGustavo A. R. Silva /* extract the offline message length */ 151912bdcf33SDavid Howells case 4: 152012bdcf33SDavid Howells ret = afs_extract_data(call, true); 1521372ee163SDavid Howells if (ret < 0) 1522372ee163SDavid Howells return ret; 152345222b9eSDavid Howells 152445222b9eSDavid Howells call->count = ntohl(call->tmp); 152545222b9eSDavid Howells _debug("offline msg length: %u", call->count); 152645222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1527160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1528160cb957SDavid Howells afs_eproto_offline_msg_len); 152912bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1530ffba718eSDavid Howells afs_extract_to_buf(call, size); 153145222b9eSDavid Howells call->unmarshall++; 153229881608SGustavo A. R. Silva /* Fall through */ 153345222b9eSDavid Howells 153429881608SGustavo A. R. Silva /* extract the offline message */ 153512bdcf33SDavid Howells case 5: 153645222b9eSDavid Howells _debug("extract offline"); 153712bdcf33SDavid Howells ret = afs_extract_data(call, true); 1538372ee163SDavid Howells if (ret < 0) 1539372ee163SDavid Howells return ret; 154045222b9eSDavid Howells 1541ffba718eSDavid Howells p = call->buffer; 154245222b9eSDavid Howells p[call->count] = 0; 154345222b9eSDavid Howells _debug("offline '%s'", p); 154445222b9eSDavid Howells 154512bdcf33SDavid Howells afs_extract_to_tmp(call); 154645222b9eSDavid Howells call->unmarshall++; 154729881608SGustavo A. R. Silva /* Fall through */ 154845222b9eSDavid Howells 154929881608SGustavo A. R. Silva /* extract the message of the day length */ 155012bdcf33SDavid Howells case 6: 155112bdcf33SDavid Howells ret = afs_extract_data(call, true); 1552372ee163SDavid Howells if (ret < 0) 1553372ee163SDavid Howells return ret; 155445222b9eSDavid Howells 155545222b9eSDavid Howells call->count = ntohl(call->tmp); 155645222b9eSDavid Howells _debug("motd length: %u", call->count); 155745222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1558160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1559160cb957SDavid Howells afs_eproto_motd_len); 156012bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1561ffba718eSDavid Howells afs_extract_to_buf(call, size); 156245222b9eSDavid Howells call->unmarshall++; 156329881608SGustavo A. R. Silva /* Fall through */ 156445222b9eSDavid Howells 156529881608SGustavo A. R. Silva /* extract the message of the day */ 156612bdcf33SDavid Howells case 7: 156745222b9eSDavid Howells _debug("extract motd"); 156812bdcf33SDavid Howells ret = afs_extract_data(call, false); 1569372ee163SDavid Howells if (ret < 0) 1570372ee163SDavid Howells return ret; 157145222b9eSDavid Howells 1572ffba718eSDavid Howells p = call->buffer; 157345222b9eSDavid Howells p[call->count] = 0; 157445222b9eSDavid Howells _debug("motd '%s'", p); 157545222b9eSDavid Howells 157645222b9eSDavid Howells call->unmarshall++; 157745222b9eSDavid Howells 157812bdcf33SDavid Howells case 8: 157945222b9eSDavid Howells break; 158045222b9eSDavid Howells } 158145222b9eSDavid Howells 158245222b9eSDavid Howells _leave(" = 0 [done]"); 158345222b9eSDavid Howells return 0; 158445222b9eSDavid Howells } 158545222b9eSDavid Howells 158645222b9eSDavid Howells /* 158745222b9eSDavid Howells * FS.GetVolumeStatus operation type 158845222b9eSDavid Howells */ 158945222b9eSDavid Howells static const struct afs_call_type afs_RXFSGetVolumeStatus = { 159045222b9eSDavid Howells .name = "FS.GetVolumeStatus", 1591025db80cSDavid Howells .op = afs_FS_GetVolumeStatus, 159245222b9eSDavid Howells .deliver = afs_deliver_fs_get_volume_status, 1593ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 159445222b9eSDavid Howells }; 159545222b9eSDavid Howells 159645222b9eSDavid Howells /* 159745222b9eSDavid Howells * fetch the status of a volume 159845222b9eSDavid Howells */ 15998b2a464cSDavid Howells int afs_fs_get_volume_status(struct afs_fs_cursor *fc, 1600d2ddc776SDavid Howells struct afs_volume_status *vs) 160145222b9eSDavid Howells { 1602d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 160345222b9eSDavid Howells struct afs_call *call; 1604f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 160545222b9eSDavid Howells __be32 *bp; 160645222b9eSDavid Howells 160730062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 160830062bd1SDavid Howells return yfs_fs_get_volume_status(fc, vs); 160930062bd1SDavid Howells 161045222b9eSDavid Howells _enter(""); 161145222b9eSDavid Howells 1612ffba718eSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 1613ffba718eSDavid Howells max(12 * 4, AFSOPAQUEMAX + 1)); 1614ffba718eSDavid Howells if (!call) 161545222b9eSDavid Howells return -ENOMEM; 161645222b9eSDavid Howells 1617d2ddc776SDavid Howells call->key = fc->key; 1618ffba718eSDavid Howells call->out_volstatus = vs; 161945222b9eSDavid Howells 162045222b9eSDavid Howells /* marshall the parameters */ 162145222b9eSDavid Howells bp = call->request; 162245222b9eSDavid Howells bp[0] = htonl(FSGETVOLUMESTATUS); 162345222b9eSDavid Howells bp[1] = htonl(vnode->fid.vid); 162445222b9eSDavid Howells 1625d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1626025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 162720b8391fSDavid Howells afs_set_fc_call(call, fc); 16280b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 16290b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 163045222b9eSDavid Howells } 1631e8d6c554SDavid Howells 1632e8d6c554SDavid Howells /* 1633e8d6c554SDavid Howells * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock 1634e8d6c554SDavid Howells */ 1635d001648eSDavid Howells static int afs_deliver_fs_xxxx_lock(struct afs_call *call) 1636e8d6c554SDavid Howells { 1637e8d6c554SDavid Howells const __be32 *bp; 1638372ee163SDavid Howells int ret; 1639e8d6c554SDavid Howells 1640d001648eSDavid Howells _enter("{%u}", call->unmarshall); 1641e8d6c554SDavid Howells 1642d001648eSDavid Howells ret = afs_transfer_reply(call); 1643372ee163SDavid Howells if (ret < 0) 1644372ee163SDavid Howells return ret; 1645e8d6c554SDavid Howells 1646e8d6c554SDavid Howells /* unmarshall the reply once we've received all of it */ 1647e8d6c554SDavid Howells bp = call->buffer; 1648ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 1649e8d6c554SDavid Howells 1650e8d6c554SDavid Howells _leave(" = 0 [done]"); 1651e8d6c554SDavid Howells return 0; 1652e8d6c554SDavid Howells } 1653e8d6c554SDavid Howells 1654e8d6c554SDavid Howells /* 1655e8d6c554SDavid Howells * FS.SetLock operation type 1656e8d6c554SDavid Howells */ 1657e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSSetLock = { 1658e8d6c554SDavid Howells .name = "FS.SetLock", 1659025db80cSDavid Howells .op = afs_FS_SetLock, 1660e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1661a690f60aSDavid Howells .done = afs_lock_op_done, 1662e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1663e8d6c554SDavid Howells }; 1664e8d6c554SDavid Howells 1665e8d6c554SDavid Howells /* 1666e8d6c554SDavid Howells * FS.ExtendLock operation type 1667e8d6c554SDavid Howells */ 1668e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSExtendLock = { 1669e8d6c554SDavid Howells .name = "FS.ExtendLock", 1670025db80cSDavid Howells .op = afs_FS_ExtendLock, 1671e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1672a690f60aSDavid Howells .done = afs_lock_op_done, 1673e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1674e8d6c554SDavid Howells }; 1675e8d6c554SDavid Howells 1676e8d6c554SDavid Howells /* 1677e8d6c554SDavid Howells * FS.ReleaseLock operation type 1678e8d6c554SDavid Howells */ 1679e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSReleaseLock = { 1680e8d6c554SDavid Howells .name = "FS.ReleaseLock", 1681025db80cSDavid Howells .op = afs_FS_ReleaseLock, 1682e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1683e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1684e8d6c554SDavid Howells }; 1685e8d6c554SDavid Howells 1686e8d6c554SDavid Howells /* 1687d2ddc776SDavid Howells * Set a lock on a file 1688e8d6c554SDavid Howells */ 1689a58823acSDavid Howells int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type, 1690a58823acSDavid Howells struct afs_status_cb *scb) 1691e8d6c554SDavid Howells { 1692d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1693e8d6c554SDavid Howells struct afs_call *call; 1694f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1695e8d6c554SDavid Howells __be32 *bp; 1696e8d6c554SDavid Howells 169730062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1698a58823acSDavid Howells return yfs_fs_set_lock(fc, type, scb); 169930062bd1SDavid Howells 1700e8d6c554SDavid Howells _enter(""); 1701e8d6c554SDavid Howells 1702f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4); 1703e8d6c554SDavid Howells if (!call) 1704e8d6c554SDavid Howells return -ENOMEM; 1705e8d6c554SDavid Howells 1706d2ddc776SDavid Howells call->key = fc->key; 1707a58823acSDavid Howells call->lvnode = vnode; 1708a58823acSDavid Howells call->out_scb = scb; 1709e8d6c554SDavid Howells 1710e8d6c554SDavid Howells /* marshall the parameters */ 1711e8d6c554SDavid Howells bp = call->request; 1712e8d6c554SDavid Howells *bp++ = htonl(FSSETLOCK); 1713e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1714e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1715e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1716e8d6c554SDavid Howells *bp++ = htonl(type); 1717e8d6c554SDavid Howells 1718d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 17196c6c1d63SDavid Howells trace_afs_make_fs_calli(call, &vnode->fid, type); 172020b8391fSDavid Howells afs_set_fc_call(call, fc); 17210b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17220b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1723e8d6c554SDavid Howells } 1724e8d6c554SDavid Howells 1725e8d6c554SDavid Howells /* 1726e8d6c554SDavid Howells * extend a lock on a file 1727e8d6c554SDavid Howells */ 1728a58823acSDavid Howells int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1729e8d6c554SDavid Howells { 1730d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1731e8d6c554SDavid Howells struct afs_call *call; 1732f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1733e8d6c554SDavid Howells __be32 *bp; 1734e8d6c554SDavid Howells 173530062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1736a58823acSDavid Howells return yfs_fs_extend_lock(fc, scb); 173730062bd1SDavid Howells 1738e8d6c554SDavid Howells _enter(""); 1739e8d6c554SDavid Howells 1740f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4); 1741e8d6c554SDavid Howells if (!call) 1742e8d6c554SDavid Howells return -ENOMEM; 1743e8d6c554SDavid Howells 1744d2ddc776SDavid Howells call->key = fc->key; 1745a58823acSDavid Howells call->lvnode = vnode; 1746a58823acSDavid Howells call->out_scb = scb; 1747e8d6c554SDavid Howells 1748e8d6c554SDavid Howells /* marshall the parameters */ 1749e8d6c554SDavid Howells bp = call->request; 1750e8d6c554SDavid Howells *bp++ = htonl(FSEXTENDLOCK); 1751e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1752e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1753e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1754e8d6c554SDavid Howells 1755d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1756025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 175720b8391fSDavid Howells afs_set_fc_call(call, fc); 17580b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17590b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1760e8d6c554SDavid Howells } 1761e8d6c554SDavid Howells 1762e8d6c554SDavid Howells /* 1763e8d6c554SDavid Howells * release a lock on a file 1764e8d6c554SDavid Howells */ 1765a58823acSDavid Howells int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1766e8d6c554SDavid Howells { 1767d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1768e8d6c554SDavid Howells struct afs_call *call; 1769f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1770e8d6c554SDavid Howells __be32 *bp; 1771e8d6c554SDavid Howells 177230062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1773a58823acSDavid Howells return yfs_fs_release_lock(fc, scb); 177430062bd1SDavid Howells 1775e8d6c554SDavid Howells _enter(""); 1776e8d6c554SDavid Howells 1777f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4); 1778e8d6c554SDavid Howells if (!call) 1779e8d6c554SDavid Howells return -ENOMEM; 1780e8d6c554SDavid Howells 1781d2ddc776SDavid Howells call->key = fc->key; 1782a58823acSDavid Howells call->lvnode = vnode; 1783a58823acSDavid Howells call->out_scb = scb; 1784e8d6c554SDavid Howells 1785e8d6c554SDavid Howells /* marshall the parameters */ 1786e8d6c554SDavid Howells bp = call->request; 1787e8d6c554SDavid Howells *bp++ = htonl(FSRELEASELOCK); 1788e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1789e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1790e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1791e8d6c554SDavid Howells 1792d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1793025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 179420b8391fSDavid Howells afs_set_fc_call(call, fc); 17950b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17960b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1797c435ee34SDavid Howells } 1798c435ee34SDavid Howells 1799c435ee34SDavid Howells /* 1800c435ee34SDavid Howells * Deliver reply data to an FS.GiveUpAllCallBacks operation. 1801c435ee34SDavid Howells */ 1802c435ee34SDavid Howells static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call) 1803c435ee34SDavid Howells { 1804c435ee34SDavid Howells return afs_transfer_reply(call); 1805c435ee34SDavid Howells } 1806c435ee34SDavid Howells 1807c435ee34SDavid Howells /* 1808c435ee34SDavid Howells * FS.GiveUpAllCallBacks operation type 1809c435ee34SDavid Howells */ 1810c435ee34SDavid Howells static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = { 1811c435ee34SDavid Howells .name = "FS.GiveUpAllCallBacks", 1812025db80cSDavid Howells .op = afs_FS_GiveUpAllCallBacks, 1813c435ee34SDavid Howells .deliver = afs_deliver_fs_give_up_all_callbacks, 1814c435ee34SDavid Howells .destructor = afs_flat_call_destructor, 1815c435ee34SDavid Howells }; 1816c435ee34SDavid Howells 1817c435ee34SDavid Howells /* 1818c435ee34SDavid Howells * Flush all the callbacks we have on a server. 1819c435ee34SDavid Howells */ 1820d2ddc776SDavid Howells int afs_fs_give_up_all_callbacks(struct afs_net *net, 1821d2ddc776SDavid Howells struct afs_server *server, 18228b2a464cSDavid Howells struct afs_addr_cursor *ac, 1823d2ddc776SDavid Howells struct key *key) 1824c435ee34SDavid Howells { 1825c435ee34SDavid Howells struct afs_call *call; 1826c435ee34SDavid Howells __be32 *bp; 1827c435ee34SDavid Howells 1828c435ee34SDavid Howells _enter(""); 1829c435ee34SDavid Howells 1830d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0); 1831c435ee34SDavid Howells if (!call) 1832c435ee34SDavid Howells return -ENOMEM; 1833c435ee34SDavid Howells 1834c435ee34SDavid Howells call->key = key; 1835c435ee34SDavid Howells 1836c435ee34SDavid Howells /* marshall the parameters */ 1837c435ee34SDavid Howells bp = call->request; 1838c435ee34SDavid Howells *bp++ = htonl(FSGIVEUPALLCALLBACKS); 1839c435ee34SDavid Howells 1840c435ee34SDavid Howells /* Can't take a ref on server */ 18410b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 18420b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, ac); 1843d2ddc776SDavid Howells } 1844d2ddc776SDavid Howells 1845d2ddc776SDavid Howells /* 1846d2ddc776SDavid Howells * Deliver reply data to an FS.GetCapabilities operation. 1847d2ddc776SDavid Howells */ 1848d2ddc776SDavid Howells static int afs_deliver_fs_get_capabilities(struct afs_call *call) 1849d2ddc776SDavid Howells { 1850d2ddc776SDavid Howells u32 count; 1851d2ddc776SDavid Howells int ret; 1852d2ddc776SDavid Howells 1853fc276122SDavid Howells _enter("{%u,%zu}", call->unmarshall, iov_iter_count(call->iter)); 1854d2ddc776SDavid Howells 1855d2ddc776SDavid Howells switch (call->unmarshall) { 1856d2ddc776SDavid Howells case 0: 185712bdcf33SDavid Howells afs_extract_to_tmp(call); 1858d2ddc776SDavid Howells call->unmarshall++; 185929881608SGustavo A. R. Silva /* Fall through */ 1860d2ddc776SDavid Howells 186129881608SGustavo A. R. Silva /* Extract the capabilities word count */ 1862d2ddc776SDavid Howells case 1: 186312bdcf33SDavid Howells ret = afs_extract_data(call, true); 1864d2ddc776SDavid Howells if (ret < 0) 1865d2ddc776SDavid Howells return ret; 1866d2ddc776SDavid Howells 1867d2ddc776SDavid Howells count = ntohl(call->tmp); 1868d2ddc776SDavid Howells 1869d2ddc776SDavid Howells call->count = count; 1870d2ddc776SDavid Howells call->count2 = count; 187123a28913SDavid Howells afs_extract_discard(call, count * sizeof(__be32)); 1872d2ddc776SDavid Howells call->unmarshall++; 187329881608SGustavo A. R. Silva /* Fall through */ 1874d2ddc776SDavid Howells 187529881608SGustavo A. R. Silva /* Extract capabilities words */ 1876d2ddc776SDavid Howells case 2: 187712bdcf33SDavid Howells ret = afs_extract_data(call, false); 1878d2ddc776SDavid Howells if (ret < 0) 1879d2ddc776SDavid Howells return ret; 1880d2ddc776SDavid Howells 1881d2ddc776SDavid Howells /* TODO: Examine capabilities */ 1882d2ddc776SDavid Howells 1883d2ddc776SDavid Howells call->unmarshall++; 1884d2ddc776SDavid Howells break; 1885d2ddc776SDavid Howells } 1886d2ddc776SDavid Howells 1887d2ddc776SDavid Howells _leave(" = 0 [done]"); 1888d2ddc776SDavid Howells return 0; 1889d2ddc776SDavid Howells } 1890d2ddc776SDavid Howells 1891d2ddc776SDavid Howells /* 1892d2ddc776SDavid Howells * FS.GetCapabilities operation type 1893d2ddc776SDavid Howells */ 1894d2ddc776SDavid Howells static const struct afs_call_type afs_RXFSGetCapabilities = { 1895d2ddc776SDavid Howells .name = "FS.GetCapabilities", 1896025db80cSDavid Howells .op = afs_FS_GetCapabilities, 1897d2ddc776SDavid Howells .deliver = afs_deliver_fs_get_capabilities, 18983bf0fb6fSDavid Howells .done = afs_fileserver_probe_result, 1899ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 1900d2ddc776SDavid Howells }; 1901d2ddc776SDavid Howells 1902d2ddc776SDavid Howells /* 1903d2ddc776SDavid Howells * Probe a fileserver for the capabilities that it supports. This can 1904d2ddc776SDavid Howells * return up to 196 words. 1905d2ddc776SDavid Howells */ 19060b9bf381SDavid Howells struct afs_call *afs_fs_get_capabilities(struct afs_net *net, 1907d2ddc776SDavid Howells struct afs_server *server, 1908d2ddc776SDavid Howells struct afs_addr_cursor *ac, 19093bf0fb6fSDavid Howells struct key *key, 19100b9bf381SDavid Howells unsigned int server_index) 1911d2ddc776SDavid Howells { 1912d2ddc776SDavid Howells struct afs_call *call; 1913d2ddc776SDavid Howells __be32 *bp; 1914d2ddc776SDavid Howells 1915d2ddc776SDavid Howells _enter(""); 1916d2ddc776SDavid Howells 1917d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4); 1918d2ddc776SDavid Howells if (!call) 19190b9bf381SDavid Howells return ERR_PTR(-ENOMEM); 1920d2ddc776SDavid Howells 1921d2ddc776SDavid Howells call->key = key; 192245218193SDavid Howells call->server = afs_get_server(server, afs_server_trace_get_caps); 1923ffba718eSDavid Howells call->server_index = server_index; 192430062bd1SDavid Howells call->upgrade = true; 19250b9bf381SDavid Howells call->async = true; 192694f699c9SDavid Howells call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; 1927d2ddc776SDavid Howells 1928d2ddc776SDavid Howells /* marshall the parameters */ 1929d2ddc776SDavid Howells bp = call->request; 1930d2ddc776SDavid Howells *bp++ = htonl(FSGETCAPABILITIES); 1931d2ddc776SDavid Howells 1932d2ddc776SDavid Howells /* Can't take a ref on server */ 1933025db80cSDavid Howells trace_afs_make_fs_call(call, NULL); 19340b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 19350b9bf381SDavid Howells return call; 1936e8d6c554SDavid Howells } 19375cf9dd55SDavid Howells 19385cf9dd55SDavid Howells /* 19395cf9dd55SDavid Howells * Deliver reply data to an FS.FetchStatus with no vnode. 19405cf9dd55SDavid Howells */ 19415cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status(struct afs_call *call) 19425cf9dd55SDavid Howells { 19435cf9dd55SDavid Howells const __be32 *bp; 19445cf9dd55SDavid Howells int ret; 19455cf9dd55SDavid Howells 19465cf9dd55SDavid Howells ret = afs_transfer_reply(call); 19475cf9dd55SDavid Howells if (ret < 0) 19485cf9dd55SDavid Howells return ret; 19495cf9dd55SDavid Howells 19505cf9dd55SDavid Howells /* unmarshall the reply once we've received all of it */ 19515cf9dd55SDavid Howells bp = call->buffer; 1952a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1953160cb957SDavid Howells if (ret < 0) 1954160cb957SDavid Howells return ret; 1955a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 1956a58823acSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 19575cf9dd55SDavid Howells 19585cf9dd55SDavid Howells _leave(" = 0 [done]"); 19595cf9dd55SDavid Howells return 0; 19605cf9dd55SDavid Howells } 19615cf9dd55SDavid Howells 19625cf9dd55SDavid Howells /* 19635cf9dd55SDavid Howells * FS.FetchStatus operation type 19645cf9dd55SDavid Howells */ 19655cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus = { 19665cf9dd55SDavid Howells .name = "FS.FetchStatus", 19675cf9dd55SDavid Howells .op = afs_FS_FetchStatus, 19685cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status, 19695cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 19705cf9dd55SDavid Howells }; 19715cf9dd55SDavid Howells 19725cf9dd55SDavid Howells /* 19735cf9dd55SDavid Howells * Fetch the status information for a fid without needing a vnode handle. 19745cf9dd55SDavid Howells */ 19755cf9dd55SDavid Howells int afs_fs_fetch_status(struct afs_fs_cursor *fc, 19765cf9dd55SDavid Howells struct afs_net *net, 19775cf9dd55SDavid Howells struct afs_fid *fid, 1978a58823acSDavid Howells struct afs_status_cb *scb, 19795cf9dd55SDavid Howells struct afs_volsync *volsync) 19805cf9dd55SDavid Howells { 19815cf9dd55SDavid Howells struct afs_call *call; 19825cf9dd55SDavid Howells __be32 *bp; 19835cf9dd55SDavid Howells 198430062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1985a58823acSDavid Howells return yfs_fs_fetch_status(fc, net, fid, scb, volsync); 198630062bd1SDavid Howells 19873b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 19885cf9dd55SDavid Howells key_serial(fc->key), fid->vid, fid->vnode); 19895cf9dd55SDavid Howells 19905cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); 19915cf9dd55SDavid Howells if (!call) { 19925cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 19935cf9dd55SDavid Howells return -ENOMEM; 19945cf9dd55SDavid Howells } 19955cf9dd55SDavid Howells 19965cf9dd55SDavid Howells call->key = fc->key; 1997ffba718eSDavid Howells call->out_fid = fid; 1998a58823acSDavid Howells call->out_scb = scb; 1999ffba718eSDavid Howells call->out_volsync = volsync; 20005cf9dd55SDavid Howells 20015cf9dd55SDavid Howells /* marshall the parameters */ 20025cf9dd55SDavid Howells bp = call->request; 20035cf9dd55SDavid Howells bp[0] = htonl(FSFETCHSTATUS); 20045cf9dd55SDavid Howells bp[1] = htonl(fid->vid); 20055cf9dd55SDavid Howells bp[2] = htonl(fid->vnode); 20065cf9dd55SDavid Howells bp[3] = htonl(fid->unique); 20075cf9dd55SDavid Howells 20085cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 20095cf9dd55SDavid Howells trace_afs_make_fs_call(call, fid); 201020b8391fSDavid Howells afs_set_fc_call(call, fc); 20110b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 20120b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 20135cf9dd55SDavid Howells } 20145cf9dd55SDavid Howells 20155cf9dd55SDavid Howells /* 20165cf9dd55SDavid Howells * Deliver reply data to an FS.InlineBulkStatus call 20175cf9dd55SDavid Howells */ 20185cf9dd55SDavid Howells static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) 20195cf9dd55SDavid Howells { 202087182759SDavid Howells struct afs_status_cb *scb; 20215cf9dd55SDavid Howells const __be32 *bp; 20225cf9dd55SDavid Howells u32 tmp; 20235cf9dd55SDavid Howells int ret; 20245cf9dd55SDavid Howells 20255cf9dd55SDavid Howells _enter("{%u}", call->unmarshall); 20265cf9dd55SDavid Howells 20275cf9dd55SDavid Howells switch (call->unmarshall) { 20285cf9dd55SDavid Howells case 0: 202912bdcf33SDavid Howells afs_extract_to_tmp(call); 20305cf9dd55SDavid Howells call->unmarshall++; 203129881608SGustavo A. R. Silva /* Fall through */ 20325cf9dd55SDavid Howells 20335cf9dd55SDavid Howells /* Extract the file status count and array in two steps */ 20345cf9dd55SDavid Howells case 1: 20355cf9dd55SDavid Howells _debug("extract status count"); 203612bdcf33SDavid Howells ret = afs_extract_data(call, true); 20375cf9dd55SDavid Howells if (ret < 0) 20385cf9dd55SDavid Howells return ret; 20395cf9dd55SDavid Howells 20405cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20415cf9dd55SDavid Howells _debug("status count: %u/%u", tmp, call->count2); 20425cf9dd55SDavid Howells if (tmp != call->count2) 2043160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2044160cb957SDavid Howells afs_eproto_ibulkst_count); 20455cf9dd55SDavid Howells 20465cf9dd55SDavid Howells call->count = 0; 20475cf9dd55SDavid Howells call->unmarshall++; 20485cf9dd55SDavid Howells more_counts: 204912bdcf33SDavid Howells afs_extract_to_buf(call, 21 * sizeof(__be32)); 2050e690c9e3SGustavo A. R. Silva /* Fall through */ 205129881608SGustavo A. R. Silva 20525cf9dd55SDavid Howells case 2: 20535cf9dd55SDavid Howells _debug("extract status array %u", call->count); 205412bdcf33SDavid Howells ret = afs_extract_data(call, true); 20555cf9dd55SDavid Howells if (ret < 0) 20565cf9dd55SDavid Howells return ret; 20575cf9dd55SDavid Howells 20585cf9dd55SDavid Howells bp = call->buffer; 205987182759SDavid Howells scb = &call->out_scb[call->count]; 2060a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, scb); 2061160cb957SDavid Howells if (ret < 0) 2062160cb957SDavid Howells return ret; 20635cf9dd55SDavid Howells 20645cf9dd55SDavid Howells call->count++; 20655cf9dd55SDavid Howells if (call->count < call->count2) 20665cf9dd55SDavid Howells goto more_counts; 20675cf9dd55SDavid Howells 20685cf9dd55SDavid Howells call->count = 0; 20695cf9dd55SDavid Howells call->unmarshall++; 207012bdcf33SDavid Howells afs_extract_to_tmp(call); 207129881608SGustavo A. R. Silva /* Fall through */ 20725cf9dd55SDavid Howells 20735cf9dd55SDavid Howells /* Extract the callback count and array in two steps */ 20745cf9dd55SDavid Howells case 3: 20755cf9dd55SDavid Howells _debug("extract CB count"); 207612bdcf33SDavid Howells ret = afs_extract_data(call, true); 20775cf9dd55SDavid Howells if (ret < 0) 20785cf9dd55SDavid Howells return ret; 20795cf9dd55SDavid Howells 20805cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20815cf9dd55SDavid Howells _debug("CB count: %u", tmp); 20825cf9dd55SDavid Howells if (tmp != call->count2) 2083160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2084160cb957SDavid Howells afs_eproto_ibulkst_cb_count); 20855cf9dd55SDavid Howells call->count = 0; 20865cf9dd55SDavid Howells call->unmarshall++; 20875cf9dd55SDavid Howells more_cbs: 208812bdcf33SDavid Howells afs_extract_to_buf(call, 3 * sizeof(__be32)); 2089e690c9e3SGustavo A. R. Silva /* Fall through */ 209029881608SGustavo A. R. Silva 20915cf9dd55SDavid Howells case 4: 20925cf9dd55SDavid Howells _debug("extract CB array"); 209312bdcf33SDavid Howells ret = afs_extract_data(call, true); 20945cf9dd55SDavid Howells if (ret < 0) 20955cf9dd55SDavid Howells return ret; 20965cf9dd55SDavid Howells 20975cf9dd55SDavid Howells _debug("unmarshall CB array"); 20985cf9dd55SDavid Howells bp = call->buffer; 209987182759SDavid Howells scb = &call->out_scb[call->count]; 2100a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, scb); 21015cf9dd55SDavid Howells call->count++; 21025cf9dd55SDavid Howells if (call->count < call->count2) 21035cf9dd55SDavid Howells goto more_cbs; 21045cf9dd55SDavid Howells 210512bdcf33SDavid Howells afs_extract_to_buf(call, 6 * sizeof(__be32)); 21065cf9dd55SDavid Howells call->unmarshall++; 2107e690c9e3SGustavo A. R. Silva /* Fall through */ 210829881608SGustavo A. R. Silva 21095cf9dd55SDavid Howells case 5: 211012bdcf33SDavid Howells ret = afs_extract_data(call, false); 21115cf9dd55SDavid Howells if (ret < 0) 21125cf9dd55SDavid Howells return ret; 21135cf9dd55SDavid Howells 21145cf9dd55SDavid Howells bp = call->buffer; 2115ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 21165cf9dd55SDavid Howells 21175cf9dd55SDavid Howells call->unmarshall++; 21185cf9dd55SDavid Howells 21195cf9dd55SDavid Howells case 6: 21205cf9dd55SDavid Howells break; 21215cf9dd55SDavid Howells } 21225cf9dd55SDavid Howells 21235cf9dd55SDavid Howells _leave(" = 0 [done]"); 21245cf9dd55SDavid Howells return 0; 21255cf9dd55SDavid Howells } 21265cf9dd55SDavid Howells 21275cf9dd55SDavid Howells /* 21285cf9dd55SDavid Howells * FS.InlineBulkStatus operation type 21295cf9dd55SDavid Howells */ 21305cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSInlineBulkStatus = { 21315cf9dd55SDavid Howells .name = "FS.InlineBulkStatus", 21325cf9dd55SDavid Howells .op = afs_FS_InlineBulkStatus, 21335cf9dd55SDavid Howells .deliver = afs_deliver_fs_inline_bulk_status, 21345cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 21355cf9dd55SDavid Howells }; 21365cf9dd55SDavid Howells 21375cf9dd55SDavid Howells /* 21385cf9dd55SDavid Howells * Fetch the status information for up to 50 files 21395cf9dd55SDavid Howells */ 21405cf9dd55SDavid Howells int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, 21415cf9dd55SDavid Howells struct afs_net *net, 21425cf9dd55SDavid Howells struct afs_fid *fids, 214387182759SDavid Howells struct afs_status_cb *statuses, 21445cf9dd55SDavid Howells unsigned int nr_fids, 21455cf9dd55SDavid Howells struct afs_volsync *volsync) 21465cf9dd55SDavid Howells { 21475cf9dd55SDavid Howells struct afs_call *call; 21485cf9dd55SDavid Howells __be32 *bp; 21495cf9dd55SDavid Howells int i; 21505cf9dd55SDavid Howells 215130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 215287182759SDavid Howells return yfs_fs_inline_bulk_status(fc, net, fids, statuses, 215330062bd1SDavid Howells nr_fids, volsync); 215430062bd1SDavid Howells 21553b6492dfSDavid Howells _enter(",%x,{%llx:%llu},%u", 21565cf9dd55SDavid Howells key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); 21575cf9dd55SDavid Howells 21585cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus, 21595cf9dd55SDavid Howells (2 + nr_fids * 3) * 4, 21605cf9dd55SDavid Howells 21 * 4); 21615cf9dd55SDavid Howells if (!call) { 21625cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 21635cf9dd55SDavid Howells return -ENOMEM; 21645cf9dd55SDavid Howells } 21655cf9dd55SDavid Howells 21665cf9dd55SDavid Howells call->key = fc->key; 216787182759SDavid Howells call->out_scb = statuses; 2168ffba718eSDavid Howells call->out_volsync = volsync; 21695cf9dd55SDavid Howells call->count2 = nr_fids; 21705cf9dd55SDavid Howells 21715cf9dd55SDavid Howells /* marshall the parameters */ 21725cf9dd55SDavid Howells bp = call->request; 21735cf9dd55SDavid Howells *bp++ = htonl(FSINLINEBULKSTATUS); 21745cf9dd55SDavid Howells *bp++ = htonl(nr_fids); 21755cf9dd55SDavid Howells for (i = 0; i < nr_fids; i++) { 21765cf9dd55SDavid Howells *bp++ = htonl(fids[i].vid); 21775cf9dd55SDavid Howells *bp++ = htonl(fids[i].vnode); 21785cf9dd55SDavid Howells *bp++ = htonl(fids[i].unique); 21795cf9dd55SDavid Howells } 21805cf9dd55SDavid Howells 21815cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 21825cf9dd55SDavid Howells trace_afs_make_fs_call(call, &fids[0]); 218320b8391fSDavid Howells afs_set_fc_call(call, fc); 21840b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 21850b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 21865cf9dd55SDavid Howells } 2187260f082bSDavid Howells 2188260f082bSDavid Howells /* 2189260f082bSDavid Howells * deliver reply data to an FS.FetchACL 2190260f082bSDavid Howells */ 2191260f082bSDavid Howells static int afs_deliver_fs_fetch_acl(struct afs_call *call) 2192260f082bSDavid Howells { 2193260f082bSDavid Howells struct afs_acl *acl; 2194260f082bSDavid Howells const __be32 *bp; 2195260f082bSDavid Howells unsigned int size; 2196260f082bSDavid Howells int ret; 2197260f082bSDavid Howells 2198260f082bSDavid Howells _enter("{%u}", call->unmarshall); 2199260f082bSDavid Howells 2200260f082bSDavid Howells switch (call->unmarshall) { 2201260f082bSDavid Howells case 0: 2202260f082bSDavid Howells afs_extract_to_tmp(call); 2203260f082bSDavid Howells call->unmarshall++; 220429881608SGustavo A. R. Silva /* Fall through */ 2205260f082bSDavid Howells 2206260f082bSDavid Howells /* extract the returned data length */ 2207260f082bSDavid Howells case 1: 2208260f082bSDavid Howells ret = afs_extract_data(call, true); 2209260f082bSDavid Howells if (ret < 0) 2210260f082bSDavid Howells return ret; 2211260f082bSDavid Howells 2212260f082bSDavid Howells size = call->count2 = ntohl(call->tmp); 2213260f082bSDavid Howells size = round_up(size, 4); 2214260f082bSDavid Howells 2215260f082bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); 2216260f082bSDavid Howells if (!acl) 2217260f082bSDavid Howells return -ENOMEM; 2218ffba718eSDavid Howells call->ret_acl = acl; 2219260f082bSDavid Howells acl->size = call->count2; 2220260f082bSDavid Howells afs_extract_begin(call, acl->data, size); 2221260f082bSDavid Howells call->unmarshall++; 222229881608SGustavo A. R. Silva /* Fall through */ 2223260f082bSDavid Howells 2224260f082bSDavid Howells /* extract the returned data */ 2225260f082bSDavid Howells case 2: 2226260f082bSDavid Howells ret = afs_extract_data(call, true); 2227260f082bSDavid Howells if (ret < 0) 2228260f082bSDavid Howells return ret; 2229260f082bSDavid Howells 2230260f082bSDavid Howells afs_extract_to_buf(call, (21 + 6) * 4); 2231260f082bSDavid Howells call->unmarshall++; 223229881608SGustavo A. R. Silva /* Fall through */ 2233260f082bSDavid Howells 2234260f082bSDavid Howells /* extract the metadata */ 2235260f082bSDavid Howells case 3: 2236260f082bSDavid Howells ret = afs_extract_data(call, false); 2237260f082bSDavid Howells if (ret < 0) 2238260f082bSDavid Howells return ret; 2239260f082bSDavid Howells 2240260f082bSDavid Howells bp = call->buffer; 2241a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2242260f082bSDavid Howells if (ret < 0) 2243260f082bSDavid Howells return ret; 2244ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2245260f082bSDavid Howells 2246260f082bSDavid Howells call->unmarshall++; 2247260f082bSDavid Howells 2248260f082bSDavid Howells case 4: 2249260f082bSDavid Howells break; 2250260f082bSDavid Howells } 2251260f082bSDavid Howells 2252260f082bSDavid Howells _leave(" = 0 [done]"); 2253260f082bSDavid Howells return 0; 2254260f082bSDavid Howells } 2255260f082bSDavid Howells 2256260f082bSDavid Howells static void afs_destroy_fs_fetch_acl(struct afs_call *call) 2257260f082bSDavid Howells { 2258ffba718eSDavid Howells kfree(call->ret_acl); 2259260f082bSDavid Howells afs_flat_call_destructor(call); 2260260f082bSDavid Howells } 2261260f082bSDavid Howells 2262260f082bSDavid Howells /* 2263260f082bSDavid Howells * FS.FetchACL operation type 2264260f082bSDavid Howells */ 2265260f082bSDavid Howells static const struct afs_call_type afs_RXFSFetchACL = { 2266260f082bSDavid Howells .name = "FS.FetchACL", 2267260f082bSDavid Howells .op = afs_FS_FetchACL, 2268260f082bSDavid Howells .deliver = afs_deliver_fs_fetch_acl, 2269260f082bSDavid Howells .destructor = afs_destroy_fs_fetch_acl, 2270260f082bSDavid Howells }; 2271260f082bSDavid Howells 2272260f082bSDavid Howells /* 2273260f082bSDavid Howells * Fetch the ACL for a file. 2274260f082bSDavid Howells */ 2275a58823acSDavid Howells struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc, 2276a58823acSDavid Howells struct afs_status_cb *scb) 2277260f082bSDavid Howells { 2278260f082bSDavid Howells struct afs_vnode *vnode = fc->vnode; 2279260f082bSDavid Howells struct afs_call *call; 2280260f082bSDavid Howells struct afs_net *net = afs_v2net(vnode); 2281260f082bSDavid Howells __be32 *bp; 2282260f082bSDavid Howells 2283260f082bSDavid Howells _enter(",%x,{%llx:%llu},,", 2284260f082bSDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2285260f082bSDavid Howells 2286260f082bSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4); 2287260f082bSDavid Howells if (!call) { 2288260f082bSDavid Howells fc->ac.error = -ENOMEM; 2289260f082bSDavid Howells return ERR_PTR(-ENOMEM); 2290260f082bSDavid Howells } 2291260f082bSDavid Howells 2292260f082bSDavid Howells call->key = fc->key; 2293ffba718eSDavid Howells call->ret_acl = NULL; 2294a58823acSDavid Howells call->out_scb = scb; 2295ffba718eSDavid Howells call->out_volsync = NULL; 2296260f082bSDavid Howells 2297260f082bSDavid Howells /* marshall the parameters */ 2298260f082bSDavid Howells bp = call->request; 2299260f082bSDavid Howells bp[0] = htonl(FSFETCHACL); 2300260f082bSDavid Howells bp[1] = htonl(vnode->fid.vid); 2301260f082bSDavid Howells bp[2] = htonl(vnode->fid.vnode); 2302260f082bSDavid Howells bp[3] = htonl(vnode->fid.unique); 2303260f082bSDavid Howells 2304260f082bSDavid Howells afs_use_fs_server(call, fc->cbi); 2305260f082bSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 2306260f082bSDavid Howells afs_make_call(&fc->ac, call, GFP_KERNEL); 2307260f082bSDavid Howells return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac); 2308260f082bSDavid Howells } 2309b10494afSJoe Gorse 2310b10494afSJoe Gorse /* 2311ffba718eSDavid Howells * Deliver reply data to any operation that returns file status and volume 2312ffba718eSDavid Howells * sync. 2313ffba718eSDavid Howells */ 2314ffba718eSDavid Howells static int afs_deliver_fs_file_status_and_vol(struct afs_call *call) 2315ffba718eSDavid Howells { 2316ffba718eSDavid Howells const __be32 *bp; 2317ffba718eSDavid Howells int ret; 2318ffba718eSDavid Howells 2319ffba718eSDavid Howells ret = afs_transfer_reply(call); 2320ffba718eSDavid Howells if (ret < 0) 2321ffba718eSDavid Howells return ret; 2322ffba718eSDavid Howells 2323ffba718eSDavid Howells bp = call->buffer; 2324a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2325ffba718eSDavid Howells if (ret < 0) 2326ffba718eSDavid Howells return ret; 2327ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2328ffba718eSDavid Howells 2329ffba718eSDavid Howells _leave(" = 0 [done]"); 2330ffba718eSDavid Howells return 0; 2331ffba718eSDavid Howells } 2332ffba718eSDavid Howells 2333ffba718eSDavid Howells /* 2334b10494afSJoe Gorse * FS.StoreACL operation type 2335b10494afSJoe Gorse */ 2336b10494afSJoe Gorse static const struct afs_call_type afs_RXFSStoreACL = { 2337b10494afSJoe Gorse .name = "FS.StoreACL", 2338b10494afSJoe Gorse .op = afs_FS_StoreACL, 2339ffba718eSDavid Howells .deliver = afs_deliver_fs_file_status_and_vol, 2340b10494afSJoe Gorse .destructor = afs_flat_call_destructor, 2341b10494afSJoe Gorse }; 2342b10494afSJoe Gorse 2343b10494afSJoe Gorse /* 2344b10494afSJoe Gorse * Fetch the ACL for a file. 2345b10494afSJoe Gorse */ 2346a58823acSDavid Howells int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl, 2347a58823acSDavid Howells struct afs_status_cb *scb) 2348b10494afSJoe Gorse { 2349b10494afSJoe Gorse struct afs_vnode *vnode = fc->vnode; 2350b10494afSJoe Gorse struct afs_call *call; 2351b10494afSJoe Gorse struct afs_net *net = afs_v2net(vnode); 2352b10494afSJoe Gorse size_t size; 2353b10494afSJoe Gorse __be32 *bp; 2354b10494afSJoe Gorse 2355b10494afSJoe Gorse _enter(",%x,{%llx:%llu},,", 2356b10494afSJoe Gorse key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2357b10494afSJoe Gorse 2358b10494afSJoe Gorse size = round_up(acl->size, 4); 2359b10494afSJoe Gorse call = afs_alloc_flat_call(net, &afs_RXFSStoreACL, 2360b10494afSJoe Gorse 5 * 4 + size, (21 + 6) * 4); 2361b10494afSJoe Gorse if (!call) { 2362b10494afSJoe Gorse fc->ac.error = -ENOMEM; 2363b10494afSJoe Gorse return -ENOMEM; 2364b10494afSJoe Gorse } 2365b10494afSJoe Gorse 2366b10494afSJoe Gorse call->key = fc->key; 2367a58823acSDavid Howells call->out_scb = scb; 2368ffba718eSDavid Howells call->out_volsync = NULL; 2369b10494afSJoe Gorse 2370b10494afSJoe Gorse /* marshall the parameters */ 2371b10494afSJoe Gorse bp = call->request; 2372b10494afSJoe Gorse bp[0] = htonl(FSSTOREACL); 2373b10494afSJoe Gorse bp[1] = htonl(vnode->fid.vid); 2374b10494afSJoe Gorse bp[2] = htonl(vnode->fid.vnode); 2375b10494afSJoe Gorse bp[3] = htonl(vnode->fid.unique); 2376b10494afSJoe Gorse bp[4] = htonl(acl->size); 2377b10494afSJoe Gorse memcpy(&bp[5], acl->data, acl->size); 2378b10494afSJoe Gorse if (acl->size != size) 2379b10494afSJoe Gorse memset((void *)&bp[5] + acl->size, 0, size - acl->size); 2380b10494afSJoe Gorse 2381b10494afSJoe Gorse trace_afs_make_fs_call(call, &vnode->fid); 2382b10494afSJoe Gorse afs_make_call(&fc->ac, call, GFP_KERNEL); 2383b10494afSJoe Gorse return afs_wait_for_call_to_complete(call, &fc->ac); 23841da177e4SLinus Torvalds } 2385