12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 208e0e7c8SDavid Howells /* AFS File Server client stubs 31da177e4SLinus Torvalds * 408e0e7c8SDavid Howells * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved. 51da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds #include <linux/init.h> 95a0e3ad6STejun Heo #include <linux/slab.h> 101da177e4SLinus Torvalds #include <linux/sched.h> 1108e0e7c8SDavid Howells #include <linux/circ_buf.h> 12a01179e6SJeff Layton #include <linux/iversion.h> 131da177e4SLinus Torvalds #include "internal.h" 1408e0e7c8SDavid Howells #include "afs_fs.h" 15dd9fbcb8SDavid Howells #include "xdr_fs.h" 1630062bd1SDavid Howells #include "protocol_yfs.h" 171da177e4SLinus Torvalds 18d2ddc776SDavid Howells static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi) 19c435ee34SDavid Howells { 20d2ddc776SDavid Howells call->cbi = afs_get_cb_interest(cbi); 21c435ee34SDavid Howells } 22c435ee34SDavid Howells 236db3ac3cSDavid Howells /* 24260a9803SDavid Howells * decode an AFSFid block 25260a9803SDavid Howells */ 26260a9803SDavid Howells static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid) 27260a9803SDavid Howells { 28260a9803SDavid Howells const __be32 *bp = *_bp; 29260a9803SDavid Howells 30260a9803SDavid Howells fid->vid = ntohl(*bp++); 31260a9803SDavid Howells fid->vnode = ntohl(*bp++); 32260a9803SDavid Howells fid->unique = ntohl(*bp++); 33260a9803SDavid Howells *_bp = bp; 34260a9803SDavid Howells } 35260a9803SDavid Howells 36260a9803SDavid Howells /* 37888b3384SDavid Howells * Dump a bad file status record. 38888b3384SDavid Howells */ 39888b3384SDavid Howells static void xdr_dump_bad(const __be32 *bp) 40888b3384SDavid Howells { 41888b3384SDavid Howells __be32 x[4]; 42888b3384SDavid Howells int i; 43888b3384SDavid Howells 44888b3384SDavid Howells pr_notice("AFS XDR: Bad status record\n"); 45888b3384SDavid Howells for (i = 0; i < 5 * 4 * 4; i += 16) { 46888b3384SDavid Howells memcpy(x, bp, 16); 47888b3384SDavid Howells bp += 4; 48888b3384SDavid Howells pr_notice("%03x: %08x %08x %08x %08x\n", 49888b3384SDavid Howells i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3])); 50888b3384SDavid Howells } 51888b3384SDavid Howells 52888b3384SDavid Howells memcpy(x, bp, 4); 53888b3384SDavid Howells pr_notice("0x50: %08x\n", ntohl(x[0])); 54888b3384SDavid Howells } 55888b3384SDavid Howells 56888b3384SDavid Howells /* 57dd9fbcb8SDavid Howells * decode an AFSFetchStatus block 58dd9fbcb8SDavid Howells */ 59a58823acSDavid Howells static int xdr_decode_AFSFetchStatus(const __be32 **_bp, 60a58823acSDavid Howells struct afs_call *call, 61a58823acSDavid Howells struct afs_status_cb *scb) 62dd9fbcb8SDavid Howells { 63dd9fbcb8SDavid Howells const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp; 64a58823acSDavid Howells struct afs_file_status *status = &scb->status; 65684b0f68SDavid Howells bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus); 66dd9fbcb8SDavid Howells u64 data_version, size; 67dd9fbcb8SDavid Howells u32 type, abort_code; 68c72057b5SDavid Howells int ret; 69dd9fbcb8SDavid Howells 70684b0f68SDavid Howells abort_code = ntohl(xdr->abort_code); 71684b0f68SDavid Howells 72dd9fbcb8SDavid Howells if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { 73684b0f68SDavid Howells if (xdr->if_version == htonl(0) && 74684b0f68SDavid Howells abort_code != 0 && 75684b0f68SDavid Howells inline_error) { 76684b0f68SDavid Howells /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus 77684b0f68SDavid Howells * whereby it doesn't set the interface version in the error 78684b0f68SDavid Howells * case. 79684b0f68SDavid Howells */ 80684b0f68SDavid Howells status->abort_code = abort_code; 81a38a7558SDavid Howells scb->have_error = true; 82c72057b5SDavid Howells goto good; 83684b0f68SDavid Howells } 84684b0f68SDavid Howells 85dd9fbcb8SDavid Howells pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); 86dd9fbcb8SDavid Howells goto bad; 87dd9fbcb8SDavid Howells } 88dd9fbcb8SDavid Howells 89684b0f68SDavid Howells if (abort_code != 0 && inline_error) { 90684b0f68SDavid Howells status->abort_code = abort_code; 913e0d9892SDavid Howells scb->have_error = true; 92c72057b5SDavid Howells goto good; 93684b0f68SDavid Howells } 94684b0f68SDavid Howells 95dd9fbcb8SDavid Howells type = ntohl(xdr->type); 96dd9fbcb8SDavid Howells switch (type) { 97dd9fbcb8SDavid Howells case AFS_FTYPE_FILE: 98dd9fbcb8SDavid Howells case AFS_FTYPE_DIR: 99dd9fbcb8SDavid Howells case AFS_FTYPE_SYMLINK: 100dd9fbcb8SDavid Howells status->type = type; 101dd9fbcb8SDavid Howells break; 102dd9fbcb8SDavid Howells default: 103dd9fbcb8SDavid Howells goto bad; 104dd9fbcb8SDavid Howells } 105dd9fbcb8SDavid Howells 106a58823acSDavid Howells status->nlink = ntohl(xdr->nlink); 107a58823acSDavid Howells status->author = ntohl(xdr->author); 108a58823acSDavid Howells status->owner = ntohl(xdr->owner); 109a58823acSDavid Howells status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */ 110a58823acSDavid Howells status->anon_access = ntohl(xdr->anon_access); 111a58823acSDavid Howells status->mode = ntohl(xdr->mode) & S_IALLUGO; 112a58823acSDavid Howells status->group = ntohl(xdr->group); 113a58823acSDavid Howells status->lock_count = ntohl(xdr->lock_count); 114dd9fbcb8SDavid Howells 115d4936803SDavid Howells status->mtime_client.tv_sec = ntohl(xdr->mtime_client); 116d4936803SDavid Howells status->mtime_client.tv_nsec = 0; 117d4936803SDavid Howells status->mtime_server.tv_sec = ntohl(xdr->mtime_server); 118d4936803SDavid Howells status->mtime_server.tv_nsec = 0; 119dd9fbcb8SDavid Howells 120dd9fbcb8SDavid Howells size = (u64)ntohl(xdr->size_lo); 121dd9fbcb8SDavid Howells size |= (u64)ntohl(xdr->size_hi) << 32; 122dd9fbcb8SDavid Howells status->size = size; 123dd9fbcb8SDavid Howells 124dd9fbcb8SDavid Howells data_version = (u64)ntohl(xdr->data_version_lo); 125dd9fbcb8SDavid Howells data_version |= (u64)ntohl(xdr->data_version_hi) << 32; 126dd9fbcb8SDavid Howells status->data_version = data_version; 127a38a7558SDavid Howells scb->have_status = true; 128c72057b5SDavid Howells good: 129c72057b5SDavid Howells ret = 0; 130c72057b5SDavid Howells advance: 131dd9fbcb8SDavid Howells *_bp = (const void *)*_bp + sizeof(*xdr); 132c72057b5SDavid Howells return ret; 133dd9fbcb8SDavid Howells 134dd9fbcb8SDavid Howells bad: 135dd9fbcb8SDavid Howells xdr_dump_bad(*_bp); 136c72057b5SDavid Howells ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); 137c72057b5SDavid Howells goto advance; 138c875c76aSDavid Howells } 139c875c76aSDavid Howells 14078107055SDavid Howells static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) 14178107055SDavid Howells { 14278107055SDavid Howells return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; 14378107055SDavid Howells } 14478107055SDavid Howells 145a58823acSDavid Howells static void xdr_decode_AFSCallBack(const __be32 **_bp, 146a58823acSDavid Howells struct afs_call *call, 147a58823acSDavid Howells struct afs_status_cb *scb) 14878107055SDavid Howells { 149a58823acSDavid Howells struct afs_callback *cb = &scb->callback; 15078107055SDavid Howells const __be32 *bp = *_bp; 15178107055SDavid Howells 1527c712458SDavid Howells bp++; /* version */ 15378107055SDavid Howells cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); 1547c712458SDavid Howells bp++; /* type */ 155a58823acSDavid Howells scb->have_cb = true; 15678107055SDavid Howells *_bp = bp; 15778107055SDavid Howells } 15878107055SDavid Howells 1591da177e4SLinus Torvalds /* 16008e0e7c8SDavid Howells * decode an AFSVolSync block 1611da177e4SLinus Torvalds */ 16208e0e7c8SDavid Howells static void xdr_decode_AFSVolSync(const __be32 **_bp, 16308e0e7c8SDavid Howells struct afs_volsync *volsync) 1641da177e4SLinus Torvalds { 16508e0e7c8SDavid Howells const __be32 *bp = *_bp; 16630062bd1SDavid Howells u32 creation; 1671da177e4SLinus Torvalds 16830062bd1SDavid Howells creation = ntohl(*bp++); 16908e0e7c8SDavid Howells bp++; /* spare2 */ 17008e0e7c8SDavid Howells bp++; /* spare3 */ 17108e0e7c8SDavid Howells bp++; /* spare4 */ 17208e0e7c8SDavid Howells bp++; /* spare5 */ 17308e0e7c8SDavid Howells bp++; /* spare6 */ 17408e0e7c8SDavid Howells *_bp = bp; 17530062bd1SDavid Howells 17630062bd1SDavid Howells if (volsync) 17730062bd1SDavid Howells volsync->creation = creation; 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds 18008e0e7c8SDavid Howells /* 18131143d5dSDavid Howells * encode the requested attributes into an AFSStoreStatus block 18231143d5dSDavid Howells */ 18331143d5dSDavid Howells static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr) 18431143d5dSDavid Howells { 18531143d5dSDavid Howells __be32 *bp = *_bp; 18631143d5dSDavid Howells u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0; 18731143d5dSDavid Howells 18831143d5dSDavid Howells mask = 0; 18931143d5dSDavid Howells if (attr->ia_valid & ATTR_MTIME) { 19031143d5dSDavid Howells mask |= AFS_SET_MTIME; 19131143d5dSDavid Howells mtime = attr->ia_mtime.tv_sec; 19231143d5dSDavid Howells } 19331143d5dSDavid Howells 19431143d5dSDavid Howells if (attr->ia_valid & ATTR_UID) { 19531143d5dSDavid Howells mask |= AFS_SET_OWNER; 196a0a5386aSEric W. Biederman owner = from_kuid(&init_user_ns, attr->ia_uid); 19731143d5dSDavid Howells } 19831143d5dSDavid Howells 19931143d5dSDavid Howells if (attr->ia_valid & ATTR_GID) { 20031143d5dSDavid Howells mask |= AFS_SET_GROUP; 201a0a5386aSEric W. Biederman group = from_kgid(&init_user_ns, attr->ia_gid); 20231143d5dSDavid Howells } 20331143d5dSDavid Howells 20431143d5dSDavid Howells if (attr->ia_valid & ATTR_MODE) { 20531143d5dSDavid Howells mask |= AFS_SET_MODE; 20631143d5dSDavid Howells mode = attr->ia_mode & S_IALLUGO; 20731143d5dSDavid Howells } 20831143d5dSDavid Howells 20931143d5dSDavid Howells *bp++ = htonl(mask); 21031143d5dSDavid Howells *bp++ = htonl(mtime); 21131143d5dSDavid Howells *bp++ = htonl(owner); 21231143d5dSDavid Howells *bp++ = htonl(group); 21331143d5dSDavid Howells *bp++ = htonl(mode); 21431143d5dSDavid Howells *bp++ = 0; /* segment size */ 21531143d5dSDavid Howells *_bp = bp; 21631143d5dSDavid Howells } 21731143d5dSDavid Howells 21831143d5dSDavid Howells /* 21945222b9eSDavid Howells * decode an AFSFetchVolumeStatus block 22045222b9eSDavid Howells */ 22145222b9eSDavid Howells static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, 22245222b9eSDavid Howells struct afs_volume_status *vs) 22345222b9eSDavid Howells { 22445222b9eSDavid Howells const __be32 *bp = *_bp; 22545222b9eSDavid Howells 22645222b9eSDavid Howells vs->vid = ntohl(*bp++); 22745222b9eSDavid Howells vs->parent_id = ntohl(*bp++); 22845222b9eSDavid Howells vs->online = ntohl(*bp++); 22945222b9eSDavid Howells vs->in_service = ntohl(*bp++); 23045222b9eSDavid Howells vs->blessed = ntohl(*bp++); 23145222b9eSDavid Howells vs->needs_salvage = ntohl(*bp++); 23245222b9eSDavid Howells vs->type = ntohl(*bp++); 23345222b9eSDavid Howells vs->min_quota = ntohl(*bp++); 23445222b9eSDavid Howells vs->max_quota = ntohl(*bp++); 23545222b9eSDavid Howells vs->blocks_in_use = ntohl(*bp++); 23645222b9eSDavid Howells vs->part_blocks_avail = ntohl(*bp++); 23745222b9eSDavid Howells vs->part_max_blocks = ntohl(*bp++); 23830062bd1SDavid Howells vs->vol_copy_date = 0; 23930062bd1SDavid Howells vs->vol_backup_date = 0; 24045222b9eSDavid Howells *_bp = bp; 24145222b9eSDavid Howells } 24245222b9eSDavid Howells 24345222b9eSDavid Howells /* 24408e0e7c8SDavid Howells * deliver reply data to an FS.FetchStatus 24508e0e7c8SDavid Howells */ 2465cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) 24708e0e7c8SDavid Howells { 24808e0e7c8SDavid Howells const __be32 *bp; 249372ee163SDavid Howells int ret; 2501da177e4SLinus Torvalds 251d001648eSDavid Howells ret = afs_transfer_reply(call); 252372ee163SDavid Howells if (ret < 0) 253372ee163SDavid Howells return ret; 2541da177e4SLinus Torvalds 25508e0e7c8SDavid Howells /* unmarshall the reply once we've received all of it */ 25608e0e7c8SDavid Howells bp = call->buffer; 257a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 258160cb957SDavid Howells if (ret < 0) 259160cb957SDavid Howells return ret; 260a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 261ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2621da177e4SLinus Torvalds 26308e0e7c8SDavid Howells _leave(" = 0 [done]"); 26408e0e7c8SDavid Howells return 0; 265ec26815aSDavid Howells } 26608e0e7c8SDavid Howells 26708e0e7c8SDavid Howells /* 26808e0e7c8SDavid Howells * FS.FetchStatus operation type 26908e0e7c8SDavid Howells */ 2705cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus_vnode = { 2715cf9dd55SDavid Howells .name = "FS.FetchStatus(vnode)", 272025db80cSDavid Howells .op = afs_FS_FetchStatus, 2735cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status_vnode, 27408e0e7c8SDavid Howells .destructor = afs_flat_call_destructor, 27508e0e7c8SDavid Howells }; 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds /* 2781da177e4SLinus Torvalds * fetch the status information for a file 2791da177e4SLinus Torvalds */ 280a58823acSDavid Howells int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb, 281a58823acSDavid Howells struct afs_volsync *volsync) 2821da177e4SLinus Torvalds { 283d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 28408e0e7c8SDavid Howells struct afs_call *call; 285f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 2861da177e4SLinus Torvalds __be32 *bp; 2871da177e4SLinus Torvalds 28830062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 289a58823acSDavid Howells return yfs_fs_fetch_file_status(fc, scb, volsync); 29030062bd1SDavid Howells 2913b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 292d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2931da177e4SLinus Torvalds 2945cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode, 2955cf9dd55SDavid Howells 16, (21 + 3 + 6) * 4); 296d2ddc776SDavid Howells if (!call) { 297d2ddc776SDavid Howells fc->ac.error = -ENOMEM; 29808e0e7c8SDavid Howells return -ENOMEM; 299d2ddc776SDavid Howells } 3001da177e4SLinus Torvalds 301d2ddc776SDavid Howells call->key = fc->key; 302a58823acSDavid Howells call->out_scb = scb; 303ffba718eSDavid Howells call->out_volsync = volsync; 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds /* marshall the parameters */ 30608e0e7c8SDavid Howells bp = call->request; 3071da177e4SLinus Torvalds bp[0] = htonl(FSFETCHSTATUS); 3081da177e4SLinus Torvalds bp[1] = htonl(vnode->fid.vid); 3091da177e4SLinus Torvalds bp[2] = htonl(vnode->fid.vnode); 3101da177e4SLinus Torvalds bp[3] = htonl(vnode->fid.unique); 3111da177e4SLinus Torvalds 312d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 313025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 3140b9bf381SDavid Howells 31520b8391fSDavid Howells afs_set_fc_call(call, fc); 3160b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 3170b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 318ec26815aSDavid Howells } 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds /* 32108e0e7c8SDavid Howells * deliver reply data to an FS.FetchData 3221da177e4SLinus Torvalds */ 323d001648eSDavid Howells static int afs_deliver_fs_fetch_data(struct afs_call *call) 3241da177e4SLinus Torvalds { 325ffba718eSDavid Howells struct afs_read *req = call->read_request; 32608e0e7c8SDavid Howells const __be32 *bp; 327196ee9cdSDavid Howells unsigned int size; 3281da177e4SLinus Torvalds int ret; 3291da177e4SLinus Torvalds 33012bdcf33SDavid Howells _enter("{%u,%zu/%llu}", 331fc276122SDavid Howells call->unmarshall, iov_iter_count(call->iter), req->actual_len); 3321da177e4SLinus Torvalds 33308e0e7c8SDavid Howells switch (call->unmarshall) { 33408e0e7c8SDavid Howells case 0: 335196ee9cdSDavid Howells req->actual_len = 0; 33612bdcf33SDavid Howells req->index = 0; 33712bdcf33SDavid Howells req->offset = req->pos & (PAGE_SIZE - 1); 33808e0e7c8SDavid Howells call->unmarshall++; 33912bdcf33SDavid Howells if (call->operation_ID == FSFETCHDATA64) { 34012bdcf33SDavid Howells afs_extract_to_tmp64(call); 34112bdcf33SDavid Howells } else { 34212bdcf33SDavid Howells call->tmp_u = htonl(0); 34312bdcf33SDavid Howells afs_extract_to_tmp(call); 344b9b1f8d5SDavid Howells } 34529881608SGustavo A. R. Silva /* Fall through */ 3461da177e4SLinus Torvalds 34729881608SGustavo A. R. Silva /* extract the returned data length */ 34812bdcf33SDavid Howells case 1: 34908e0e7c8SDavid Howells _debug("extract data length"); 35012bdcf33SDavid Howells ret = afs_extract_data(call, true); 351372ee163SDavid Howells if (ret < 0) 352372ee163SDavid Howells return ret; 3531da177e4SLinus Torvalds 35412bdcf33SDavid Howells req->actual_len = be64_to_cpu(call->tmp64); 355196ee9cdSDavid Howells _debug("DATA length: %llu", req->actual_len); 35612bdcf33SDavid Howells req->remain = min(req->len, req->actual_len); 35712bdcf33SDavid Howells if (req->remain == 0) 358196ee9cdSDavid Howells goto no_more_data; 35912bdcf33SDavid Howells 36008e0e7c8SDavid Howells call->unmarshall++; 3611da177e4SLinus Torvalds 362196ee9cdSDavid Howells begin_page: 3636db3ac3cSDavid Howells ASSERTCMP(req->index, <, req->nr_pages); 36412bdcf33SDavid Howells if (req->remain > PAGE_SIZE - req->offset) 36512bdcf33SDavid Howells size = PAGE_SIZE - req->offset; 366196ee9cdSDavid Howells else 367196ee9cdSDavid Howells size = req->remain; 36812bdcf33SDavid Howells call->bvec[0].bv_len = size; 36912bdcf33SDavid Howells call->bvec[0].bv_offset = req->offset; 37012bdcf33SDavid Howells call->bvec[0].bv_page = req->pages[req->index]; 371fc276122SDavid Howells iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); 37212bdcf33SDavid Howells ASSERTCMP(size, <=, PAGE_SIZE); 37329881608SGustavo A. R. Silva /* Fall through */ 374196ee9cdSDavid Howells 37529881608SGustavo A. R. Silva /* extract the returned data */ 37612bdcf33SDavid Howells case 2: 37712bdcf33SDavid Howells _debug("extract data %zu/%llu", 378fc276122SDavid Howells iov_iter_count(call->iter), req->remain); 379196ee9cdSDavid Howells 38012bdcf33SDavid Howells ret = afs_extract_data(call, true); 381372ee163SDavid Howells if (ret < 0) 382372ee163SDavid Howells return ret; 38312bdcf33SDavid Howells req->remain -= call->bvec[0].bv_len; 38412bdcf33SDavid Howells req->offset += call->bvec[0].bv_len; 38512bdcf33SDavid Howells ASSERTCMP(req->offset, <=, PAGE_SIZE); 38612bdcf33SDavid Howells if (req->offset == PAGE_SIZE) { 38712bdcf33SDavid Howells req->offset = 0; 388196ee9cdSDavid Howells if (req->page_done) 389a58823acSDavid Howells req->page_done(req); 39029f06985SDavid Howells req->index++; 39112bdcf33SDavid Howells if (req->remain > 0) 392196ee9cdSDavid Howells goto begin_page; 393196ee9cdSDavid Howells } 39412bdcf33SDavid Howells 39512bdcf33SDavid Howells ASSERTCMP(req->remain, ==, 0); 39612bdcf33SDavid Howells if (req->actual_len <= req->len) 3976db3ac3cSDavid Howells goto no_more_data; 3986db3ac3cSDavid Howells 3996db3ac3cSDavid Howells /* Discard any excess data the server gave us */ 40023a28913SDavid Howells afs_extract_discard(call, req->actual_len - req->len); 40112bdcf33SDavid Howells call->unmarshall = 3; 402e690c9e3SGustavo A. R. Silva /* Fall through */ 40329881608SGustavo A. R. Silva 40412bdcf33SDavid Howells case 3: 40512bdcf33SDavid Howells _debug("extract discard %zu/%llu", 406fc276122SDavid Howells iov_iter_count(call->iter), req->actual_len - req->len); 4076db3ac3cSDavid Howells 40812bdcf33SDavid Howells ret = afs_extract_data(call, true); 4096db3ac3cSDavid Howells if (ret < 0) 4106db3ac3cSDavid Howells return ret; 4111da177e4SLinus Torvalds 412196ee9cdSDavid Howells no_more_data: 41312bdcf33SDavid Howells call->unmarshall = 4; 41412bdcf33SDavid Howells afs_extract_to_buf(call, (21 + 3 + 6) * 4); 41529881608SGustavo A. R. Silva /* Fall through */ 41608e0e7c8SDavid Howells 41729881608SGustavo A. R. Silva /* extract the metadata */ 41812bdcf33SDavid Howells case 4: 41912bdcf33SDavid Howells ret = afs_extract_data(call, false); 420372ee163SDavid Howells if (ret < 0) 421372ee163SDavid Howells return ret; 4221da177e4SLinus Torvalds 42308e0e7c8SDavid Howells bp = call->buffer; 424a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 425160cb957SDavid Howells if (ret < 0) 426160cb957SDavid Howells return ret; 427a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 428ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 4291da177e4SLinus Torvalds 430a58823acSDavid Howells req->data_version = call->out_scb->status.data_version; 431a58823acSDavid Howells req->file_size = call->out_scb->status.size; 432a58823acSDavid Howells 43308e0e7c8SDavid Howells call->unmarshall++; 4341da177e4SLinus Torvalds 43512bdcf33SDavid Howells case 5: 4361da177e4SLinus Torvalds break; 4371da177e4SLinus Torvalds } 4381da177e4SLinus Torvalds 4396db3ac3cSDavid Howells for (; req->index < req->nr_pages; req->index++) { 44012bdcf33SDavid Howells if (req->offset < PAGE_SIZE) 4416db3ac3cSDavid Howells zero_user_segment(req->pages[req->index], 44212bdcf33SDavid Howells req->offset, PAGE_SIZE); 443196ee9cdSDavid Howells if (req->page_done) 444a58823acSDavid Howells req->page_done(req); 44512bdcf33SDavid Howells req->offset = 0; 446416351f2SDavid Howells } 447416351f2SDavid Howells 44808e0e7c8SDavid Howells _leave(" = 0 [done]"); 44908e0e7c8SDavid Howells return 0; 450ec26815aSDavid Howells } 4511da177e4SLinus Torvalds 452196ee9cdSDavid Howells static void afs_fetch_data_destructor(struct afs_call *call) 453196ee9cdSDavid Howells { 454ffba718eSDavid Howells struct afs_read *req = call->read_request; 455196ee9cdSDavid Howells 456196ee9cdSDavid Howells afs_put_read(req); 457196ee9cdSDavid Howells afs_flat_call_destructor(call); 458196ee9cdSDavid Howells } 459196ee9cdSDavid Howells 4601da177e4SLinus Torvalds /* 46108e0e7c8SDavid Howells * FS.FetchData operation type 4621da177e4SLinus Torvalds */ 46308e0e7c8SDavid Howells static const struct afs_call_type afs_RXFSFetchData = { 46400d3b7a4SDavid Howells .name = "FS.FetchData", 465025db80cSDavid Howells .op = afs_FS_FetchData, 46608e0e7c8SDavid Howells .deliver = afs_deliver_fs_fetch_data, 467196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 46808e0e7c8SDavid Howells }; 46908e0e7c8SDavid Howells 470b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSFetchData64 = { 471b9b1f8d5SDavid Howells .name = "FS.FetchData64", 472025db80cSDavid Howells .op = afs_FS_FetchData64, 473b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_fetch_data, 474196ee9cdSDavid Howells .destructor = afs_fetch_data_destructor, 475b9b1f8d5SDavid Howells }; 476b9b1f8d5SDavid Howells 477b9b1f8d5SDavid Howells /* 478b9b1f8d5SDavid Howells * fetch data from a very large file 479b9b1f8d5SDavid Howells */ 480a58823acSDavid Howells static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, 481a58823acSDavid Howells struct afs_status_cb *scb, 482a58823acSDavid Howells struct afs_read *req) 483b9b1f8d5SDavid Howells { 484d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 485b9b1f8d5SDavid Howells struct afs_call *call; 486f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 487b9b1f8d5SDavid Howells __be32 *bp; 488b9b1f8d5SDavid Howells 489b9b1f8d5SDavid Howells _enter(""); 490b9b1f8d5SDavid Howells 491f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4); 492b9b1f8d5SDavid Howells if (!call) 493b9b1f8d5SDavid Howells return -ENOMEM; 494b9b1f8d5SDavid Howells 495d2ddc776SDavid Howells call->key = fc->key; 496a58823acSDavid Howells call->out_scb = scb; 497ffba718eSDavid Howells call->out_volsync = NULL; 498d4438a25SDavid Howells call->read_request = afs_get_read(req); 499b9b1f8d5SDavid Howells 500b9b1f8d5SDavid Howells /* marshall the parameters */ 501b9b1f8d5SDavid Howells bp = call->request; 502b9b1f8d5SDavid Howells bp[0] = htonl(FSFETCHDATA64); 503b9b1f8d5SDavid Howells bp[1] = htonl(vnode->fid.vid); 504b9b1f8d5SDavid Howells bp[2] = htonl(vnode->fid.vnode); 505b9b1f8d5SDavid Howells bp[3] = htonl(vnode->fid.unique); 506196ee9cdSDavid Howells bp[4] = htonl(upper_32_bits(req->pos)); 507196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->pos)); 508b9b1f8d5SDavid Howells bp[6] = 0; 509196ee9cdSDavid Howells bp[7] = htonl(lower_32_bits(req->len)); 510b9b1f8d5SDavid Howells 511d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 512025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 51320b8391fSDavid Howells afs_set_fc_call(call, fc); 5140b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5150b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 516b9b1f8d5SDavid Howells } 517b9b1f8d5SDavid Howells 51808e0e7c8SDavid Howells /* 51908e0e7c8SDavid Howells * fetch data from a file 52008e0e7c8SDavid Howells */ 521a58823acSDavid Howells int afs_fs_fetch_data(struct afs_fs_cursor *fc, 522a58823acSDavid Howells struct afs_status_cb *scb, 523a58823acSDavid Howells struct afs_read *req) 5241da177e4SLinus Torvalds { 525d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 52608e0e7c8SDavid Howells struct afs_call *call; 527f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 52808e0e7c8SDavid Howells __be32 *bp; 5291da177e4SLinus Torvalds 53030062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 531a58823acSDavid Howells return yfs_fs_fetch_data(fc, scb, req); 53230062bd1SDavid Howells 533196ee9cdSDavid Howells if (upper_32_bits(req->pos) || 534196ee9cdSDavid Howells upper_32_bits(req->len) || 535196ee9cdSDavid Howells upper_32_bits(req->pos + req->len)) 536a58823acSDavid Howells return afs_fs_fetch_data64(fc, scb, req); 537b9b1f8d5SDavid Howells 53808e0e7c8SDavid Howells _enter(""); 5391da177e4SLinus Torvalds 540f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4); 54108e0e7c8SDavid Howells if (!call) 54208e0e7c8SDavid Howells return -ENOMEM; 5431da177e4SLinus Torvalds 544d2ddc776SDavid Howells call->key = fc->key; 545a58823acSDavid Howells call->out_scb = scb; 546ffba718eSDavid Howells call->out_volsync = NULL; 547d4438a25SDavid Howells call->read_request = afs_get_read(req); 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds /* marshall the parameters */ 55008e0e7c8SDavid Howells bp = call->request; 55108e0e7c8SDavid Howells bp[0] = htonl(FSFETCHDATA); 55208e0e7c8SDavid Howells bp[1] = htonl(vnode->fid.vid); 55308e0e7c8SDavid Howells bp[2] = htonl(vnode->fid.vnode); 55408e0e7c8SDavid Howells bp[3] = htonl(vnode->fid.unique); 555196ee9cdSDavid Howells bp[4] = htonl(lower_32_bits(req->pos)); 556196ee9cdSDavid Howells bp[5] = htonl(lower_32_bits(req->len)); 5571da177e4SLinus Torvalds 558d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 559025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 56020b8391fSDavid Howells afs_set_fc_call(call, fc); 5610b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 5620b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 56308e0e7c8SDavid Howells } 564260a9803SDavid Howells 565260a9803SDavid Howells /* 566260a9803SDavid Howells * deliver reply data to an FS.CreateFile or an FS.MakeDir 567260a9803SDavid Howells */ 568d001648eSDavid Howells static int afs_deliver_fs_create_vnode(struct afs_call *call) 569260a9803SDavid Howells { 570260a9803SDavid Howells const __be32 *bp; 571372ee163SDavid Howells int ret; 572260a9803SDavid Howells 573d001648eSDavid Howells ret = afs_transfer_reply(call); 574372ee163SDavid Howells if (ret < 0) 575372ee163SDavid Howells return ret; 576260a9803SDavid Howells 577260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 578260a9803SDavid Howells bp = call->buffer; 579ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 580a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 581160cb957SDavid Howells if (ret < 0) 582160cb957SDavid Howells return ret; 583a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 584160cb957SDavid Howells if (ret < 0) 585160cb957SDavid Howells return ret; 586a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 587ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 588260a9803SDavid Howells 589260a9803SDavid Howells _leave(" = 0 [done]"); 590260a9803SDavid Howells return 0; 591260a9803SDavid Howells } 592260a9803SDavid Howells 593260a9803SDavid Howells /* 594260a9803SDavid Howells * FS.CreateFile and FS.MakeDir operation type 595260a9803SDavid Howells */ 596025db80cSDavid Howells static const struct afs_call_type afs_RXFSCreateFile = { 597025db80cSDavid Howells .name = "FS.CreateFile", 598025db80cSDavid Howells .op = afs_FS_CreateFile, 599025db80cSDavid Howells .deliver = afs_deliver_fs_create_vnode, 600025db80cSDavid Howells .destructor = afs_flat_call_destructor, 601025db80cSDavid Howells }; 602025db80cSDavid Howells 603025db80cSDavid Howells static const struct afs_call_type afs_RXFSMakeDir = { 604025db80cSDavid Howells .name = "FS.MakeDir", 605025db80cSDavid Howells .op = afs_FS_MakeDir, 606260a9803SDavid Howells .deliver = afs_deliver_fs_create_vnode, 607260a9803SDavid Howells .destructor = afs_flat_call_destructor, 608260a9803SDavid Howells }; 609260a9803SDavid Howells 610260a9803SDavid Howells /* 611260a9803SDavid Howells * create a file or make a directory 612260a9803SDavid Howells */ 6138b2a464cSDavid Howells int afs_fs_create(struct afs_fs_cursor *fc, 614260a9803SDavid Howells const char *name, 615260a9803SDavid Howells umode_t mode, 616a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 617260a9803SDavid Howells struct afs_fid *newfid, 618a58823acSDavid Howells struct afs_status_cb *new_scb) 619260a9803SDavid Howells { 620ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 621260a9803SDavid Howells struct afs_call *call; 622ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 623260a9803SDavid Howells size_t namesz, reqsz, padsz; 624260a9803SDavid Howells __be32 *bp; 625260a9803SDavid Howells 62630062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){ 62730062bd1SDavid Howells if (S_ISDIR(mode)) 628a58823acSDavid Howells return yfs_fs_make_dir(fc, name, mode, dvnode_scb, 629a58823acSDavid Howells newfid, new_scb); 63030062bd1SDavid Howells else 631a58823acSDavid Howells return yfs_fs_create_file(fc, name, mode, dvnode_scb, 632a58823acSDavid Howells newfid, new_scb); 63330062bd1SDavid Howells } 63430062bd1SDavid Howells 635260a9803SDavid Howells _enter(""); 636260a9803SDavid Howells 637260a9803SDavid Howells namesz = strlen(name); 638260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 639260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (6 * 4); 640260a9803SDavid Howells 641025db80cSDavid Howells call = afs_alloc_flat_call( 642025db80cSDavid Howells net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile, 643025db80cSDavid Howells reqsz, (3 + 21 + 21 + 3 + 6) * 4); 644260a9803SDavid Howells if (!call) 645260a9803SDavid Howells return -ENOMEM; 646260a9803SDavid Howells 647d2ddc776SDavid Howells call->key = fc->key; 648a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 649ffba718eSDavid Howells call->out_fid = newfid; 650a58823acSDavid Howells call->out_scb = new_scb; 651260a9803SDavid Howells 652260a9803SDavid Howells /* marshall the parameters */ 653260a9803SDavid Howells bp = call->request; 654260a9803SDavid Howells *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); 655ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 656ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 657ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 658260a9803SDavid Howells *bp++ = htonl(namesz); 659260a9803SDavid Howells memcpy(bp, name, namesz); 660260a9803SDavid Howells bp = (void *) bp + namesz; 661260a9803SDavid Howells if (padsz > 0) { 662260a9803SDavid Howells memset(bp, 0, padsz); 663260a9803SDavid Howells bp = (void *) bp + padsz; 664260a9803SDavid Howells } 665ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 666ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 667260a9803SDavid Howells *bp++ = 0; /* owner */ 668260a9803SDavid Howells *bp++ = 0; /* group */ 669260a9803SDavid Howells *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ 670260a9803SDavid Howells *bp++ = 0; /* segment size */ 671260a9803SDavid Howells 672d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 673ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 67420b8391fSDavid Howells afs_set_fc_call(call, fc); 6750b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 6760b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 677260a9803SDavid Howells } 678260a9803SDavid Howells 679260a9803SDavid Howells /* 680ffba718eSDavid Howells * Deliver reply data to any operation that returns directory status and volume 681b10494afSJoe Gorse * sync. 682260a9803SDavid Howells */ 683ffba718eSDavid Howells static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call) 684260a9803SDavid Howells { 685260a9803SDavid Howells const __be32 *bp; 686372ee163SDavid Howells int ret; 687260a9803SDavid Howells 688d001648eSDavid Howells ret = afs_transfer_reply(call); 689372ee163SDavid Howells if (ret < 0) 690372ee163SDavid Howells return ret; 691260a9803SDavid Howells 692260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 693260a9803SDavid Howells bp = call->buffer; 694a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 695160cb957SDavid Howells if (ret < 0) 696160cb957SDavid Howells return ret; 697ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 698260a9803SDavid Howells 699260a9803SDavid Howells _leave(" = 0 [done]"); 700260a9803SDavid Howells return 0; 701260a9803SDavid Howells } 702260a9803SDavid Howells 703260a9803SDavid Howells /* 704260a9803SDavid Howells * FS.RemoveDir/FS.RemoveFile operation type 705260a9803SDavid Howells */ 706025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveFile = { 707025db80cSDavid Howells .name = "FS.RemoveFile", 708025db80cSDavid Howells .op = afs_FS_RemoveFile, 709ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 710025db80cSDavid Howells .destructor = afs_flat_call_destructor, 711025db80cSDavid Howells }; 712025db80cSDavid Howells 713025db80cSDavid Howells static const struct afs_call_type afs_RXFSRemoveDir = { 714025db80cSDavid Howells .name = "FS.RemoveDir", 715025db80cSDavid Howells .op = afs_FS_RemoveDir, 716ffba718eSDavid Howells .deliver = afs_deliver_fs_dir_status_and_vol, 717260a9803SDavid Howells .destructor = afs_flat_call_destructor, 718260a9803SDavid Howells }; 719260a9803SDavid Howells 720260a9803SDavid Howells /* 721260a9803SDavid Howells * remove a file or directory 722260a9803SDavid Howells */ 72330062bd1SDavid Howells int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 724a58823acSDavid Howells const char *name, bool isdir, struct afs_status_cb *dvnode_scb) 725260a9803SDavid Howells { 72630062bd1SDavid Howells struct afs_vnode *dvnode = fc->vnode; 727260a9803SDavid Howells struct afs_call *call; 72830062bd1SDavid Howells struct afs_net *net = afs_v2net(dvnode); 729260a9803SDavid Howells size_t namesz, reqsz, padsz; 730260a9803SDavid Howells __be32 *bp; 731260a9803SDavid Howells 73230062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 733a58823acSDavid Howells return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb); 73430062bd1SDavid Howells 735260a9803SDavid Howells _enter(""); 736260a9803SDavid Howells 737260a9803SDavid Howells namesz = strlen(name); 738260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 739260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz; 740260a9803SDavid Howells 741025db80cSDavid Howells call = afs_alloc_flat_call( 742025db80cSDavid Howells net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile, 743025db80cSDavid Howells reqsz, (21 + 6) * 4); 744260a9803SDavid Howells if (!call) 745260a9803SDavid Howells return -ENOMEM; 746260a9803SDavid Howells 747d2ddc776SDavid Howells call->key = fc->key; 748a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 749260a9803SDavid Howells 750260a9803SDavid Howells /* marshall the parameters */ 751260a9803SDavid Howells bp = call->request; 752260a9803SDavid Howells *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); 75330062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vid); 75430062bd1SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 75530062bd1SDavid Howells *bp++ = htonl(dvnode->fid.unique); 756260a9803SDavid Howells *bp++ = htonl(namesz); 757260a9803SDavid Howells memcpy(bp, name, namesz); 758260a9803SDavid Howells bp = (void *) bp + namesz; 759260a9803SDavid Howells if (padsz > 0) { 760260a9803SDavid Howells memset(bp, 0, padsz); 761260a9803SDavid Howells bp = (void *) bp + padsz; 762260a9803SDavid Howells } 763260a9803SDavid Howells 764d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 76580548b03SDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 76620b8391fSDavid Howells afs_set_fc_call(call, fc); 7670b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 7680b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 769260a9803SDavid Howells } 770260a9803SDavid Howells 771260a9803SDavid Howells /* 772260a9803SDavid Howells * deliver reply data to an FS.Link 773260a9803SDavid Howells */ 774d001648eSDavid Howells static int afs_deliver_fs_link(struct afs_call *call) 775260a9803SDavid Howells { 776260a9803SDavid Howells const __be32 *bp; 777372ee163SDavid Howells int ret; 778260a9803SDavid Howells 779d001648eSDavid Howells _enter("{%u}", call->unmarshall); 780260a9803SDavid Howells 781d001648eSDavid Howells ret = afs_transfer_reply(call); 782372ee163SDavid Howells if (ret < 0) 783372ee163SDavid Howells return ret; 784260a9803SDavid Howells 785260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 786260a9803SDavid Howells bp = call->buffer; 787a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 788160cb957SDavid Howells if (ret < 0) 789160cb957SDavid Howells return ret; 790a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 791160cb957SDavid Howells if (ret < 0) 792160cb957SDavid Howells return ret; 793ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 794260a9803SDavid Howells 795260a9803SDavid Howells _leave(" = 0 [done]"); 796260a9803SDavid Howells return 0; 797260a9803SDavid Howells } 798260a9803SDavid Howells 799260a9803SDavid Howells /* 800260a9803SDavid Howells * FS.Link operation type 801260a9803SDavid Howells */ 802260a9803SDavid Howells static const struct afs_call_type afs_RXFSLink = { 803260a9803SDavid Howells .name = "FS.Link", 804025db80cSDavid Howells .op = afs_FS_Link, 805260a9803SDavid Howells .deliver = afs_deliver_fs_link, 806260a9803SDavid Howells .destructor = afs_flat_call_destructor, 807260a9803SDavid Howells }; 808260a9803SDavid Howells 809260a9803SDavid Howells /* 810260a9803SDavid Howells * make a hard link 811260a9803SDavid Howells */ 812d2ddc776SDavid Howells int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, 813a58823acSDavid Howells const char *name, 814a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 815a58823acSDavid Howells struct afs_status_cb *vnode_scb) 816260a9803SDavid Howells { 817d2ddc776SDavid Howells struct afs_vnode *dvnode = fc->vnode; 818260a9803SDavid Howells struct afs_call *call; 819f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 820260a9803SDavid Howells size_t namesz, reqsz, padsz; 821260a9803SDavid Howells __be32 *bp; 822260a9803SDavid Howells 82330062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 824a58823acSDavid Howells return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb); 82530062bd1SDavid Howells 826260a9803SDavid Howells _enter(""); 827260a9803SDavid Howells 828260a9803SDavid Howells namesz = strlen(name); 829260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 830260a9803SDavid Howells reqsz = (5 * 4) + namesz + padsz + (3 * 4); 831260a9803SDavid Howells 832f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4); 833260a9803SDavid Howells if (!call) 834260a9803SDavid Howells return -ENOMEM; 835260a9803SDavid Howells 836d2ddc776SDavid Howells call->key = fc->key; 837a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 838a58823acSDavid Howells call->out_scb = vnode_scb; 839260a9803SDavid Howells 840260a9803SDavid Howells /* marshall the parameters */ 841260a9803SDavid Howells bp = call->request; 842260a9803SDavid Howells *bp++ = htonl(FSLINK); 843260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vid); 844260a9803SDavid Howells *bp++ = htonl(dvnode->fid.vnode); 845260a9803SDavid Howells *bp++ = htonl(dvnode->fid.unique); 846260a9803SDavid Howells *bp++ = htonl(namesz); 847260a9803SDavid Howells memcpy(bp, name, namesz); 848260a9803SDavid Howells bp = (void *) bp + namesz; 849260a9803SDavid Howells if (padsz > 0) { 850260a9803SDavid Howells memset(bp, 0, padsz); 851260a9803SDavid Howells bp = (void *) bp + padsz; 852260a9803SDavid Howells } 853260a9803SDavid Howells *bp++ = htonl(vnode->fid.vid); 854260a9803SDavid Howells *bp++ = htonl(vnode->fid.vnode); 855260a9803SDavid Howells *bp++ = htonl(vnode->fid.unique); 856260a9803SDavid Howells 857d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 85880548b03SDavid Howells trace_afs_make_fs_call1(call, &vnode->fid, name); 85920b8391fSDavid Howells afs_set_fc_call(call, fc); 8600b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 8610b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 862260a9803SDavid Howells } 863260a9803SDavid Howells 864260a9803SDavid Howells /* 865260a9803SDavid Howells * deliver reply data to an FS.Symlink 866260a9803SDavid Howells */ 867d001648eSDavid Howells static int afs_deliver_fs_symlink(struct afs_call *call) 868260a9803SDavid Howells { 869260a9803SDavid Howells const __be32 *bp; 870372ee163SDavid Howells int ret; 871260a9803SDavid Howells 872d001648eSDavid Howells _enter("{%u}", call->unmarshall); 873260a9803SDavid Howells 874d001648eSDavid Howells ret = afs_transfer_reply(call); 875372ee163SDavid Howells if (ret < 0) 876372ee163SDavid Howells return ret; 877260a9803SDavid Howells 878260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 879260a9803SDavid Howells bp = call->buffer; 880ffba718eSDavid Howells xdr_decode_AFSFid(&bp, call->out_fid); 881a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 882160cb957SDavid Howells if (ret < 0) 883160cb957SDavid Howells return ret; 884a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 885160cb957SDavid Howells if (ret < 0) 886160cb957SDavid Howells return ret; 887ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 888260a9803SDavid Howells 889260a9803SDavid Howells _leave(" = 0 [done]"); 890260a9803SDavid Howells return 0; 891260a9803SDavid Howells } 892260a9803SDavid Howells 893260a9803SDavid Howells /* 894260a9803SDavid Howells * FS.Symlink operation type 895260a9803SDavid Howells */ 896260a9803SDavid Howells static const struct afs_call_type afs_RXFSSymlink = { 897260a9803SDavid Howells .name = "FS.Symlink", 898025db80cSDavid Howells .op = afs_FS_Symlink, 899260a9803SDavid Howells .deliver = afs_deliver_fs_symlink, 900260a9803SDavid Howells .destructor = afs_flat_call_destructor, 901260a9803SDavid Howells }; 902260a9803SDavid Howells 903260a9803SDavid Howells /* 904260a9803SDavid Howells * create a symbolic link 905260a9803SDavid Howells */ 9068b2a464cSDavid Howells int afs_fs_symlink(struct afs_fs_cursor *fc, 907260a9803SDavid Howells const char *name, 908260a9803SDavid Howells const char *contents, 909a58823acSDavid Howells struct afs_status_cb *dvnode_scb, 910260a9803SDavid Howells struct afs_fid *newfid, 911a58823acSDavid Howells struct afs_status_cb *new_scb) 912260a9803SDavid Howells { 913ffba718eSDavid Howells struct afs_vnode *dvnode = fc->vnode; 914260a9803SDavid Howells struct afs_call *call; 915ffba718eSDavid Howells struct afs_net *net = afs_v2net(dvnode); 916260a9803SDavid Howells size_t namesz, reqsz, padsz, c_namesz, c_padsz; 917260a9803SDavid Howells __be32 *bp; 918260a9803SDavid Howells 91930062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 920a58823acSDavid Howells return yfs_fs_symlink(fc, name, contents, dvnode_scb, 921a58823acSDavid Howells newfid, new_scb); 92230062bd1SDavid Howells 923260a9803SDavid Howells _enter(""); 924260a9803SDavid Howells 925260a9803SDavid Howells namesz = strlen(name); 926260a9803SDavid Howells padsz = (4 - (namesz & 3)) & 3; 927260a9803SDavid Howells 928260a9803SDavid Howells c_namesz = strlen(contents); 929260a9803SDavid Howells c_padsz = (4 - (c_namesz & 3)) & 3; 930260a9803SDavid Howells 931260a9803SDavid Howells reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4); 932260a9803SDavid Howells 933f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz, 934260a9803SDavid Howells (3 + 21 + 21 + 6) * 4); 935260a9803SDavid Howells if (!call) 936260a9803SDavid Howells return -ENOMEM; 937260a9803SDavid Howells 938d2ddc776SDavid Howells call->key = fc->key; 939a58823acSDavid Howells call->out_dir_scb = dvnode_scb; 940ffba718eSDavid Howells call->out_fid = newfid; 941a58823acSDavid Howells call->out_scb = new_scb; 942260a9803SDavid Howells 943260a9803SDavid Howells /* marshall the parameters */ 944260a9803SDavid Howells bp = call->request; 945260a9803SDavid Howells *bp++ = htonl(FSSYMLINK); 946ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vid); 947ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.vnode); 948ffba718eSDavid Howells *bp++ = htonl(dvnode->fid.unique); 949260a9803SDavid Howells *bp++ = htonl(namesz); 950260a9803SDavid Howells memcpy(bp, name, namesz); 951260a9803SDavid Howells bp = (void *) bp + namesz; 952260a9803SDavid Howells if (padsz > 0) { 953260a9803SDavid Howells memset(bp, 0, padsz); 954260a9803SDavid Howells bp = (void *) bp + padsz; 955260a9803SDavid Howells } 956260a9803SDavid Howells *bp++ = htonl(c_namesz); 957260a9803SDavid Howells memcpy(bp, contents, c_namesz); 958260a9803SDavid Howells bp = (void *) bp + c_namesz; 959260a9803SDavid Howells if (c_padsz > 0) { 960260a9803SDavid Howells memset(bp, 0, c_padsz); 961260a9803SDavid Howells bp = (void *) bp + c_padsz; 962260a9803SDavid Howells } 963ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); 964ffba718eSDavid Howells *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 965260a9803SDavid Howells *bp++ = 0; /* owner */ 966260a9803SDavid Howells *bp++ = 0; /* group */ 967260a9803SDavid Howells *bp++ = htonl(S_IRWXUGO); /* unix mode */ 968260a9803SDavid Howells *bp++ = 0; /* segment size */ 969260a9803SDavid Howells 970d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 971ffba718eSDavid Howells trace_afs_make_fs_call1(call, &dvnode->fid, name); 97220b8391fSDavid Howells afs_set_fc_call(call, fc); 9730b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 9740b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 975260a9803SDavid Howells } 976260a9803SDavid Howells 977260a9803SDavid Howells /* 978260a9803SDavid Howells * deliver reply data to an FS.Rename 979260a9803SDavid Howells */ 980d001648eSDavid Howells static int afs_deliver_fs_rename(struct afs_call *call) 981260a9803SDavid Howells { 982260a9803SDavid Howells const __be32 *bp; 983372ee163SDavid Howells int ret; 984260a9803SDavid Howells 985d001648eSDavid Howells ret = afs_transfer_reply(call); 986372ee163SDavid Howells if (ret < 0) 987372ee163SDavid Howells return ret; 988260a9803SDavid Howells 989260a9803SDavid Howells /* unmarshall the reply once we've received all of it */ 990260a9803SDavid Howells bp = call->buffer; 991a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); 992160cb957SDavid Howells if (ret < 0) 993160cb957SDavid Howells return ret; 994a58823acSDavid Howells if (call->out_dir_scb != call->out_scb) { 995a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 996160cb957SDavid Howells if (ret < 0) 997160cb957SDavid Howells return ret; 998160cb957SDavid Howells } 999ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 1000260a9803SDavid Howells 1001260a9803SDavid Howells _leave(" = 0 [done]"); 1002260a9803SDavid Howells return 0; 1003260a9803SDavid Howells } 1004260a9803SDavid Howells 1005260a9803SDavid Howells /* 1006260a9803SDavid Howells * FS.Rename operation type 1007260a9803SDavid Howells */ 1008260a9803SDavid Howells static const struct afs_call_type afs_RXFSRename = { 1009260a9803SDavid Howells .name = "FS.Rename", 1010025db80cSDavid Howells .op = afs_FS_Rename, 1011260a9803SDavid Howells .deliver = afs_deliver_fs_rename, 1012260a9803SDavid Howells .destructor = afs_flat_call_destructor, 1013260a9803SDavid Howells }; 1014260a9803SDavid Howells 1015260a9803SDavid Howells /* 1016a58823acSDavid Howells * Rename/move a file or directory. 1017260a9803SDavid Howells */ 10188b2a464cSDavid Howells int afs_fs_rename(struct afs_fs_cursor *fc, 1019260a9803SDavid Howells const char *orig_name, 1020260a9803SDavid Howells struct afs_vnode *new_dvnode, 102163a4681fSDavid Howells const char *new_name, 1022a58823acSDavid Howells struct afs_status_cb *orig_dvnode_scb, 1023a58823acSDavid Howells struct afs_status_cb *new_dvnode_scb) 1024260a9803SDavid Howells { 1025d2ddc776SDavid Howells struct afs_vnode *orig_dvnode = fc->vnode; 1026260a9803SDavid Howells struct afs_call *call; 1027f044c884SDavid Howells struct afs_net *net = afs_v2net(orig_dvnode); 1028260a9803SDavid Howells size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; 1029260a9803SDavid Howells __be32 *bp; 1030260a9803SDavid Howells 103130062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 103230062bd1SDavid Howells return yfs_fs_rename(fc, orig_name, 103330062bd1SDavid Howells new_dvnode, new_name, 1034a58823acSDavid Howells orig_dvnode_scb, 1035a58823acSDavid Howells new_dvnode_scb); 103630062bd1SDavid Howells 1037260a9803SDavid Howells _enter(""); 1038260a9803SDavid Howells 1039260a9803SDavid Howells o_namesz = strlen(orig_name); 1040260a9803SDavid Howells o_padsz = (4 - (o_namesz & 3)) & 3; 1041260a9803SDavid Howells 1042260a9803SDavid Howells n_namesz = strlen(new_name); 1043260a9803SDavid Howells n_padsz = (4 - (n_namesz & 3)) & 3; 1044260a9803SDavid Howells 1045260a9803SDavid Howells reqsz = (4 * 4) + 1046260a9803SDavid Howells 4 + o_namesz + o_padsz + 1047260a9803SDavid Howells (3 * 4) + 1048260a9803SDavid Howells 4 + n_namesz + n_padsz; 1049260a9803SDavid Howells 1050f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4); 1051260a9803SDavid Howells if (!call) 1052260a9803SDavid Howells return -ENOMEM; 1053260a9803SDavid Howells 1054d2ddc776SDavid Howells call->key = fc->key; 1055a58823acSDavid Howells call->out_dir_scb = orig_dvnode_scb; 1056a58823acSDavid Howells call->out_scb = new_dvnode_scb; 1057260a9803SDavid Howells 1058260a9803SDavid Howells /* marshall the parameters */ 1059260a9803SDavid Howells bp = call->request; 1060260a9803SDavid Howells *bp++ = htonl(FSRENAME); 1061260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vid); 1062260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.vnode); 1063260a9803SDavid Howells *bp++ = htonl(orig_dvnode->fid.unique); 1064260a9803SDavid Howells *bp++ = htonl(o_namesz); 1065260a9803SDavid Howells memcpy(bp, orig_name, o_namesz); 1066260a9803SDavid Howells bp = (void *) bp + o_namesz; 1067260a9803SDavid Howells if (o_padsz > 0) { 1068260a9803SDavid Howells memset(bp, 0, o_padsz); 1069260a9803SDavid Howells bp = (void *) bp + o_padsz; 1070260a9803SDavid Howells } 1071260a9803SDavid Howells 1072260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vid); 1073260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.vnode); 1074260a9803SDavid Howells *bp++ = htonl(new_dvnode->fid.unique); 1075260a9803SDavid Howells *bp++ = htonl(n_namesz); 1076260a9803SDavid Howells memcpy(bp, new_name, n_namesz); 1077260a9803SDavid Howells bp = (void *) bp + n_namesz; 1078260a9803SDavid Howells if (n_padsz > 0) { 1079260a9803SDavid Howells memset(bp, 0, n_padsz); 1080260a9803SDavid Howells bp = (void *) bp + n_padsz; 1081260a9803SDavid Howells } 1082260a9803SDavid Howells 1083d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 108480548b03SDavid Howells trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name); 108520b8391fSDavid Howells afs_set_fc_call(call, fc); 10860b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 10870b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1088260a9803SDavid Howells } 108931143d5dSDavid Howells 109031143d5dSDavid Howells /* 109131143d5dSDavid Howells * deliver reply data to an FS.StoreData 109231143d5dSDavid Howells */ 1093d001648eSDavid Howells static int afs_deliver_fs_store_data(struct afs_call *call) 109431143d5dSDavid Howells { 109531143d5dSDavid Howells const __be32 *bp; 1096372ee163SDavid Howells int ret; 109731143d5dSDavid Howells 1098d001648eSDavid Howells _enter(""); 109931143d5dSDavid Howells 1100d001648eSDavid Howells ret = afs_transfer_reply(call); 1101372ee163SDavid Howells if (ret < 0) 1102372ee163SDavid Howells return ret; 110331143d5dSDavid Howells 110431143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 110531143d5dSDavid Howells bp = call->buffer; 1106a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1107160cb957SDavid Howells if (ret < 0) 1108160cb957SDavid Howells return ret; 1109ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 111031143d5dSDavid Howells 111131143d5dSDavid Howells _leave(" = 0 [done]"); 111231143d5dSDavid Howells return 0; 111331143d5dSDavid Howells } 111431143d5dSDavid Howells 111531143d5dSDavid Howells /* 111631143d5dSDavid Howells * FS.StoreData operation type 111731143d5dSDavid Howells */ 111831143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData = { 111931143d5dSDavid Howells .name = "FS.StoreData", 1120025db80cSDavid Howells .op = afs_FS_StoreData, 112131143d5dSDavid Howells .deliver = afs_deliver_fs_store_data, 112231143d5dSDavid Howells .destructor = afs_flat_call_destructor, 112331143d5dSDavid Howells }; 112431143d5dSDavid Howells 1125b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64 = { 1126b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1127025db80cSDavid Howells .op = afs_FS_StoreData64, 1128b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_data, 1129b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1130b9b1f8d5SDavid Howells }; 1131b9b1f8d5SDavid Howells 1132b9b1f8d5SDavid Howells /* 1133b9b1f8d5SDavid Howells * store a set of pages to a very large file 1134b9b1f8d5SDavid Howells */ 11358b2a464cSDavid Howells static int afs_fs_store_data64(struct afs_fs_cursor *fc, 11364343d008SDavid Howells struct address_space *mapping, 1137b9b1f8d5SDavid Howells pgoff_t first, pgoff_t last, 1138b9b1f8d5SDavid Howells unsigned offset, unsigned to, 1139a58823acSDavid Howells loff_t size, loff_t pos, loff_t i_size, 1140a58823acSDavid Howells struct afs_status_cb *scb) 1141b9b1f8d5SDavid Howells { 11424343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 1143b9b1f8d5SDavid Howells struct afs_call *call; 1144f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1145b9b1f8d5SDavid Howells __be32 *bp; 1146b9b1f8d5SDavid Howells 11473b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 11484343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1149b9b1f8d5SDavid Howells 1150f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64, 1151b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1152b9b1f8d5SDavid Howells (21 + 6) * 4); 1153b9b1f8d5SDavid Howells if (!call) 1154b9b1f8d5SDavid Howells return -ENOMEM; 1155b9b1f8d5SDavid Howells 11564343d008SDavid Howells call->key = fc->key; 11574343d008SDavid Howells call->mapping = mapping; 1158b9b1f8d5SDavid Howells call->first = first; 1159b9b1f8d5SDavid Howells call->last = last; 1160b9b1f8d5SDavid Howells call->first_offset = offset; 1161b9b1f8d5SDavid Howells call->last_to = to; 1162b9b1f8d5SDavid Howells call->send_pages = true; 1163a58823acSDavid Howells call->out_scb = scb; 1164b9b1f8d5SDavid Howells 1165b9b1f8d5SDavid Howells /* marshall the parameters */ 1166b9b1f8d5SDavid Howells bp = call->request; 1167b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1168b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1169b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1170b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1171b9b1f8d5SDavid Howells 1172ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1173ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 1174b9b1f8d5SDavid Howells *bp++ = 0; /* owner */ 1175b9b1f8d5SDavid Howells *bp++ = 0; /* group */ 1176b9b1f8d5SDavid Howells *bp++ = 0; /* unix mode */ 1177b9b1f8d5SDavid Howells *bp++ = 0; /* segment size */ 1178b9b1f8d5SDavid Howells 1179b9b1f8d5SDavid Howells *bp++ = htonl(pos >> 32); 1180b9b1f8d5SDavid Howells *bp++ = htonl((u32) pos); 1181b9b1f8d5SDavid Howells *bp++ = htonl(size >> 32); 1182b9b1f8d5SDavid Howells *bp++ = htonl((u32) size); 1183b9b1f8d5SDavid Howells *bp++ = htonl(i_size >> 32); 1184b9b1f8d5SDavid Howells *bp++ = htonl((u32) i_size); 1185b9b1f8d5SDavid Howells 1186025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 118720b8391fSDavid Howells afs_set_fc_call(call, fc); 11880b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 11890b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1190b9b1f8d5SDavid Howells } 1191b9b1f8d5SDavid Howells 119231143d5dSDavid Howells /* 119331143d5dSDavid Howells * store a set of pages 119431143d5dSDavid Howells */ 11954343d008SDavid Howells int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, 119631143d5dSDavid Howells pgoff_t first, pgoff_t last, 1197a58823acSDavid Howells unsigned offset, unsigned to, 1198a58823acSDavid Howells struct afs_status_cb *scb) 119931143d5dSDavid Howells { 12004343d008SDavid Howells struct afs_vnode *vnode = fc->vnode; 120131143d5dSDavid Howells struct afs_call *call; 1202f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 120331143d5dSDavid Howells loff_t size, pos, i_size; 120431143d5dSDavid Howells __be32 *bp; 120531143d5dSDavid Howells 120630062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1207a58823acSDavid Howells return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb); 120830062bd1SDavid Howells 12093b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 12104343d008SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 121131143d5dSDavid Howells 1212146a1192SDavid Howells size = (loff_t)to - (loff_t)offset; 121331143d5dSDavid Howells if (first != last) 121431143d5dSDavid Howells size += (loff_t)(last - first) << PAGE_SHIFT; 121531143d5dSDavid Howells pos = (loff_t)first << PAGE_SHIFT; 121631143d5dSDavid Howells pos += offset; 121731143d5dSDavid Howells 121831143d5dSDavid Howells i_size = i_size_read(&vnode->vfs_inode); 121931143d5dSDavid Howells if (pos + size > i_size) 122031143d5dSDavid Howells i_size = size + pos; 122131143d5dSDavid Howells 122231143d5dSDavid Howells _debug("size %llx, at %llx, i_size %llx", 122331143d5dSDavid Howells (unsigned long long) size, (unsigned long long) pos, 122431143d5dSDavid Howells (unsigned long long) i_size); 122531143d5dSDavid Howells 1226b9b1f8d5SDavid Howells if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32) 12274343d008SDavid Howells return afs_fs_store_data64(fc, mapping, first, last, offset, to, 1228a58823acSDavid Howells size, pos, i_size, scb); 122931143d5dSDavid Howells 1230f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData, 123131143d5dSDavid Howells (4 + 6 + 3) * 4, 123231143d5dSDavid Howells (21 + 6) * 4); 123331143d5dSDavid Howells if (!call) 123431143d5dSDavid Howells return -ENOMEM; 123531143d5dSDavid Howells 12364343d008SDavid Howells call->key = fc->key; 12374343d008SDavid Howells call->mapping = mapping; 123831143d5dSDavid Howells call->first = first; 123931143d5dSDavid Howells call->last = last; 124031143d5dSDavid Howells call->first_offset = offset; 124131143d5dSDavid Howells call->last_to = to; 124231143d5dSDavid Howells call->send_pages = true; 1243a58823acSDavid Howells call->out_scb = scb; 124431143d5dSDavid Howells 124531143d5dSDavid Howells /* marshall the parameters */ 124631143d5dSDavid Howells bp = call->request; 124731143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 124831143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 124931143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 125031143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 125131143d5dSDavid Howells 1252ab94f5d0SMarc Dionne *bp++ = htonl(AFS_SET_MTIME); /* mask */ 1253ab94f5d0SMarc Dionne *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ 125431143d5dSDavid Howells *bp++ = 0; /* owner */ 125531143d5dSDavid Howells *bp++ = 0; /* group */ 125631143d5dSDavid Howells *bp++ = 0; /* unix mode */ 125731143d5dSDavid Howells *bp++ = 0; /* segment size */ 125831143d5dSDavid Howells 125931143d5dSDavid Howells *bp++ = htonl(pos); 126031143d5dSDavid Howells *bp++ = htonl(size); 126131143d5dSDavid Howells *bp++ = htonl(i_size); 126231143d5dSDavid Howells 1263d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1264025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 126520b8391fSDavid Howells afs_set_fc_call(call, fc); 12660b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 12670b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 126831143d5dSDavid Howells } 126931143d5dSDavid Howells 127031143d5dSDavid Howells /* 127131143d5dSDavid Howells * deliver reply data to an FS.StoreStatus 127231143d5dSDavid Howells */ 1273d001648eSDavid Howells static int afs_deliver_fs_store_status(struct afs_call *call) 127431143d5dSDavid Howells { 127531143d5dSDavid Howells const __be32 *bp; 1276372ee163SDavid Howells int ret; 127731143d5dSDavid Howells 1278d001648eSDavid Howells _enter(""); 127931143d5dSDavid Howells 1280d001648eSDavid Howells ret = afs_transfer_reply(call); 1281372ee163SDavid Howells if (ret < 0) 1282372ee163SDavid Howells return ret; 128331143d5dSDavid Howells 128431143d5dSDavid Howells /* unmarshall the reply once we've received all of it */ 128531143d5dSDavid Howells bp = call->buffer; 1286a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1287160cb957SDavid Howells if (ret < 0) 1288160cb957SDavid Howells return ret; 1289ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 129031143d5dSDavid Howells 129131143d5dSDavid Howells _leave(" = 0 [done]"); 129231143d5dSDavid Howells return 0; 129331143d5dSDavid Howells } 129431143d5dSDavid Howells 129531143d5dSDavid Howells /* 129631143d5dSDavid Howells * FS.StoreStatus operation type 129731143d5dSDavid Howells */ 129831143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreStatus = { 129931143d5dSDavid Howells .name = "FS.StoreStatus", 1300025db80cSDavid Howells .op = afs_FS_StoreStatus, 130131143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 130231143d5dSDavid Howells .destructor = afs_flat_call_destructor, 130331143d5dSDavid Howells }; 130431143d5dSDavid Howells 130531143d5dSDavid Howells static const struct afs_call_type afs_RXFSStoreData_as_Status = { 130631143d5dSDavid Howells .name = "FS.StoreData", 1307025db80cSDavid Howells .op = afs_FS_StoreData, 130831143d5dSDavid Howells .deliver = afs_deliver_fs_store_status, 130931143d5dSDavid Howells .destructor = afs_flat_call_destructor, 131031143d5dSDavid Howells }; 131131143d5dSDavid Howells 1312b9b1f8d5SDavid Howells static const struct afs_call_type afs_RXFSStoreData64_as_Status = { 1313b9b1f8d5SDavid Howells .name = "FS.StoreData64", 1314025db80cSDavid Howells .op = afs_FS_StoreData64, 1315b9b1f8d5SDavid Howells .deliver = afs_deliver_fs_store_status, 1316b9b1f8d5SDavid Howells .destructor = afs_flat_call_destructor, 1317b9b1f8d5SDavid Howells }; 1318b9b1f8d5SDavid Howells 1319b9b1f8d5SDavid Howells /* 1320b9b1f8d5SDavid Howells * set the attributes on a very large file, using FS.StoreData rather than 1321b9b1f8d5SDavid Howells * FS.StoreStatus so as to alter the file size also 1322b9b1f8d5SDavid Howells */ 1323a58823acSDavid Howells static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr, 1324a58823acSDavid Howells struct afs_status_cb *scb) 1325b9b1f8d5SDavid Howells { 1326d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1327b9b1f8d5SDavid Howells struct afs_call *call; 1328f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1329b9b1f8d5SDavid Howells __be32 *bp; 1330b9b1f8d5SDavid Howells 13313b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1332d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 1333b9b1f8d5SDavid Howells 1334b9b1f8d5SDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1335b9b1f8d5SDavid Howells 1336f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status, 1337b9b1f8d5SDavid Howells (4 + 6 + 3 * 2) * 4, 1338b9b1f8d5SDavid Howells (21 + 6) * 4); 1339b9b1f8d5SDavid Howells if (!call) 1340b9b1f8d5SDavid Howells return -ENOMEM; 1341b9b1f8d5SDavid Howells 1342d2ddc776SDavid Howells call->key = fc->key; 1343a58823acSDavid Howells call->out_scb = scb; 1344b9b1f8d5SDavid Howells 1345b9b1f8d5SDavid Howells /* marshall the parameters */ 1346b9b1f8d5SDavid Howells bp = call->request; 1347b9b1f8d5SDavid Howells *bp++ = htonl(FSSTOREDATA64); 1348b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vid); 1349b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1350b9b1f8d5SDavid Howells *bp++ = htonl(vnode->fid.unique); 1351b9b1f8d5SDavid Howells 1352b9b1f8d5SDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 1353b9b1f8d5SDavid Howells 13548c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* position of start of write */ 13558c7ae38dSDavid Howells *bp++ = htonl((u32) attr->ia_size); 1356b9b1f8d5SDavid Howells *bp++ = 0; /* size of write */ 1357b9b1f8d5SDavid Howells *bp++ = 0; 1358b9b1f8d5SDavid Howells *bp++ = htonl(attr->ia_size >> 32); /* new file length */ 1359b9b1f8d5SDavid Howells *bp++ = htonl((u32) attr->ia_size); 1360b9b1f8d5SDavid Howells 1361d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1362025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 136320b8391fSDavid Howells afs_set_fc_call(call, fc); 13640b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 13650b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1366b9b1f8d5SDavid Howells } 1367b9b1f8d5SDavid Howells 136831143d5dSDavid Howells /* 136931143d5dSDavid Howells * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus 137031143d5dSDavid Howells * so as to alter the file size also 137131143d5dSDavid Howells */ 1372a58823acSDavid Howells static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr, 1373a58823acSDavid Howells struct afs_status_cb *scb) 137431143d5dSDavid Howells { 1375d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 137631143d5dSDavid Howells struct afs_call *call; 1377f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 137831143d5dSDavid Howells __be32 *bp; 137931143d5dSDavid Howells 13803b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1381d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 138231143d5dSDavid Howells 138331143d5dSDavid Howells ASSERT(attr->ia_valid & ATTR_SIZE); 1384b9b1f8d5SDavid Howells if (attr->ia_size >> 32) 1385a58823acSDavid Howells return afs_fs_setattr_size64(fc, attr, scb); 138631143d5dSDavid Howells 1387f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status, 138831143d5dSDavid Howells (4 + 6 + 3) * 4, 138931143d5dSDavid Howells (21 + 6) * 4); 139031143d5dSDavid Howells if (!call) 139131143d5dSDavid Howells return -ENOMEM; 139231143d5dSDavid Howells 1393d2ddc776SDavid Howells call->key = fc->key; 1394a58823acSDavid Howells call->out_scb = scb; 139531143d5dSDavid Howells 139631143d5dSDavid Howells /* marshall the parameters */ 139731143d5dSDavid Howells bp = call->request; 139831143d5dSDavid Howells *bp++ = htonl(FSSTOREDATA); 139931143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 140031143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 140131143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 140231143d5dSDavid Howells 140331143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 140431143d5dSDavid Howells 14058c7ae38dSDavid Howells *bp++ = htonl(attr->ia_size); /* position of start of write */ 140631143d5dSDavid Howells *bp++ = 0; /* size of write */ 140731143d5dSDavid Howells *bp++ = htonl(attr->ia_size); /* new file length */ 140831143d5dSDavid Howells 1409d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1410025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 141120b8391fSDavid Howells afs_set_fc_call(call, fc); 14120b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14130b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 141431143d5dSDavid Howells } 141531143d5dSDavid Howells 141631143d5dSDavid Howells /* 141731143d5dSDavid Howells * set the attributes on a file, using FS.StoreData if there's a change in file 141831143d5dSDavid Howells * size, and FS.StoreStatus otherwise 141931143d5dSDavid Howells */ 1420a58823acSDavid Howells int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr, 1421a58823acSDavid Howells struct afs_status_cb *scb) 142231143d5dSDavid Howells { 1423d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 142431143d5dSDavid Howells struct afs_call *call; 1425f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 142631143d5dSDavid Howells __be32 *bp; 142731143d5dSDavid Howells 142830062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1429a58823acSDavid Howells return yfs_fs_setattr(fc, attr, scb); 143030062bd1SDavid Howells 143131143d5dSDavid Howells if (attr->ia_valid & ATTR_SIZE) 1432a58823acSDavid Howells return afs_fs_setattr_size(fc, attr, scb); 143331143d5dSDavid Howells 14343b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 1435d2ddc776SDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 143631143d5dSDavid Howells 1437f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus, 143831143d5dSDavid Howells (4 + 6) * 4, 143931143d5dSDavid Howells (21 + 6) * 4); 144031143d5dSDavid Howells if (!call) 144131143d5dSDavid Howells return -ENOMEM; 144231143d5dSDavid Howells 1443d2ddc776SDavid Howells call->key = fc->key; 1444a58823acSDavid Howells call->out_scb = scb; 144531143d5dSDavid Howells 144631143d5dSDavid Howells /* marshall the parameters */ 144731143d5dSDavid Howells bp = call->request; 144831143d5dSDavid Howells *bp++ = htonl(FSSTORESTATUS); 144931143d5dSDavid Howells *bp++ = htonl(vnode->fid.vid); 145031143d5dSDavid Howells *bp++ = htonl(vnode->fid.vnode); 145131143d5dSDavid Howells *bp++ = htonl(vnode->fid.unique); 145231143d5dSDavid Howells 145331143d5dSDavid Howells xdr_encode_AFS_StoreStatus(&bp, attr); 145431143d5dSDavid Howells 1455d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1456025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 145720b8391fSDavid Howells afs_set_fc_call(call, fc); 14580b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 14590b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 146031143d5dSDavid Howells } 146145222b9eSDavid Howells 146245222b9eSDavid Howells /* 146345222b9eSDavid Howells * deliver reply data to an FS.GetVolumeStatus 146445222b9eSDavid Howells */ 1465d001648eSDavid Howells static int afs_deliver_fs_get_volume_status(struct afs_call *call) 146645222b9eSDavid Howells { 146745222b9eSDavid Howells const __be32 *bp; 146845222b9eSDavid Howells char *p; 146912bdcf33SDavid Howells u32 size; 147045222b9eSDavid Howells int ret; 147145222b9eSDavid Howells 1472d001648eSDavid Howells _enter("{%u}", call->unmarshall); 147345222b9eSDavid Howells 147445222b9eSDavid Howells switch (call->unmarshall) { 147545222b9eSDavid Howells case 0: 147645222b9eSDavid Howells call->unmarshall++; 147712bdcf33SDavid Howells afs_extract_to_buf(call, 12 * 4); 147829881608SGustavo A. R. Silva /* Fall through */ 147945222b9eSDavid Howells 148029881608SGustavo A. R. Silva /* extract the returned status record */ 148145222b9eSDavid Howells case 1: 148245222b9eSDavid Howells _debug("extract status"); 148312bdcf33SDavid Howells ret = afs_extract_data(call, true); 1484372ee163SDavid Howells if (ret < 0) 1485372ee163SDavid Howells return ret; 148645222b9eSDavid Howells 148745222b9eSDavid Howells bp = call->buffer; 1488ffba718eSDavid Howells xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus); 148945222b9eSDavid Howells call->unmarshall++; 149012bdcf33SDavid Howells afs_extract_to_tmp(call); 149129881608SGustavo A. R. Silva /* Fall through */ 149245222b9eSDavid Howells 149329881608SGustavo A. R. Silva /* extract the volume name length */ 149445222b9eSDavid Howells case 2: 149512bdcf33SDavid Howells ret = afs_extract_data(call, true); 1496372ee163SDavid Howells if (ret < 0) 1497372ee163SDavid Howells return ret; 149845222b9eSDavid Howells 149945222b9eSDavid Howells call->count = ntohl(call->tmp); 150045222b9eSDavid Howells _debug("volname length: %u", call->count); 150145222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1502160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1503160cb957SDavid Howells afs_eproto_volname_len); 150412bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1505ffba718eSDavid Howells afs_extract_to_buf(call, size); 150645222b9eSDavid Howells call->unmarshall++; 150729881608SGustavo A. R. Silva /* Fall through */ 150845222b9eSDavid Howells 150929881608SGustavo A. R. Silva /* extract the volume name */ 151045222b9eSDavid Howells case 3: 151145222b9eSDavid Howells _debug("extract volname"); 151212bdcf33SDavid Howells ret = afs_extract_data(call, true); 1513372ee163SDavid Howells if (ret < 0) 1514372ee163SDavid Howells return ret; 151545222b9eSDavid Howells 1516ffba718eSDavid Howells p = call->buffer; 151745222b9eSDavid Howells p[call->count] = 0; 151845222b9eSDavid Howells _debug("volname '%s'", p); 151912bdcf33SDavid Howells afs_extract_to_tmp(call); 152045222b9eSDavid Howells call->unmarshall++; 152129881608SGustavo A. R. Silva /* Fall through */ 152245222b9eSDavid Howells 152329881608SGustavo A. R. Silva /* extract the offline message length */ 152412bdcf33SDavid Howells case 4: 152512bdcf33SDavid Howells ret = afs_extract_data(call, true); 1526372ee163SDavid Howells if (ret < 0) 1527372ee163SDavid Howells return ret; 152845222b9eSDavid Howells 152945222b9eSDavid Howells call->count = ntohl(call->tmp); 153045222b9eSDavid Howells _debug("offline msg length: %u", call->count); 153145222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1532160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1533160cb957SDavid Howells afs_eproto_offline_msg_len); 153412bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1535ffba718eSDavid Howells afs_extract_to_buf(call, size); 153645222b9eSDavid Howells call->unmarshall++; 153729881608SGustavo A. R. Silva /* Fall through */ 153845222b9eSDavid Howells 153929881608SGustavo A. R. Silva /* extract the offline message */ 154012bdcf33SDavid Howells case 5: 154145222b9eSDavid Howells _debug("extract offline"); 154212bdcf33SDavid Howells ret = afs_extract_data(call, true); 1543372ee163SDavid Howells if (ret < 0) 1544372ee163SDavid Howells return ret; 154545222b9eSDavid Howells 1546ffba718eSDavid Howells p = call->buffer; 154745222b9eSDavid Howells p[call->count] = 0; 154845222b9eSDavid Howells _debug("offline '%s'", p); 154945222b9eSDavid Howells 155012bdcf33SDavid Howells afs_extract_to_tmp(call); 155145222b9eSDavid Howells call->unmarshall++; 155229881608SGustavo A. R. Silva /* Fall through */ 155345222b9eSDavid Howells 155429881608SGustavo A. R. Silva /* extract the message of the day length */ 155512bdcf33SDavid Howells case 6: 155612bdcf33SDavid Howells ret = afs_extract_data(call, true); 1557372ee163SDavid Howells if (ret < 0) 1558372ee163SDavid Howells return ret; 155945222b9eSDavid Howells 156045222b9eSDavid Howells call->count = ntohl(call->tmp); 156145222b9eSDavid Howells _debug("motd length: %u", call->count); 156245222b9eSDavid Howells if (call->count >= AFSNAMEMAX) 1563160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 1564160cb957SDavid Howells afs_eproto_motd_len); 156512bdcf33SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1566ffba718eSDavid Howells afs_extract_to_buf(call, size); 156745222b9eSDavid Howells call->unmarshall++; 156829881608SGustavo A. R. Silva /* Fall through */ 156945222b9eSDavid Howells 157029881608SGustavo A. R. Silva /* extract the message of the day */ 157112bdcf33SDavid Howells case 7: 157245222b9eSDavid Howells _debug("extract motd"); 157312bdcf33SDavid Howells ret = afs_extract_data(call, false); 1574372ee163SDavid Howells if (ret < 0) 1575372ee163SDavid Howells return ret; 157645222b9eSDavid Howells 1577ffba718eSDavid Howells p = call->buffer; 157845222b9eSDavid Howells p[call->count] = 0; 157945222b9eSDavid Howells _debug("motd '%s'", p); 158045222b9eSDavid Howells 158145222b9eSDavid Howells call->unmarshall++; 158245222b9eSDavid Howells 158312bdcf33SDavid Howells case 8: 158445222b9eSDavid Howells break; 158545222b9eSDavid Howells } 158645222b9eSDavid Howells 158745222b9eSDavid Howells _leave(" = 0 [done]"); 158845222b9eSDavid Howells return 0; 158945222b9eSDavid Howells } 159045222b9eSDavid Howells 159145222b9eSDavid Howells /* 159245222b9eSDavid Howells * FS.GetVolumeStatus operation type 159345222b9eSDavid Howells */ 159445222b9eSDavid Howells static const struct afs_call_type afs_RXFSGetVolumeStatus = { 159545222b9eSDavid Howells .name = "FS.GetVolumeStatus", 1596025db80cSDavid Howells .op = afs_FS_GetVolumeStatus, 159745222b9eSDavid Howells .deliver = afs_deliver_fs_get_volume_status, 1598ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 159945222b9eSDavid Howells }; 160045222b9eSDavid Howells 160145222b9eSDavid Howells /* 160245222b9eSDavid Howells * fetch the status of a volume 160345222b9eSDavid Howells */ 16048b2a464cSDavid Howells int afs_fs_get_volume_status(struct afs_fs_cursor *fc, 1605d2ddc776SDavid Howells struct afs_volume_status *vs) 160645222b9eSDavid Howells { 1607d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 160845222b9eSDavid Howells struct afs_call *call; 1609f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 161045222b9eSDavid Howells __be32 *bp; 161145222b9eSDavid Howells 161230062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 161330062bd1SDavid Howells return yfs_fs_get_volume_status(fc, vs); 161430062bd1SDavid Howells 161545222b9eSDavid Howells _enter(""); 161645222b9eSDavid Howells 1617ffba718eSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 1618ffba718eSDavid Howells max(12 * 4, AFSOPAQUEMAX + 1)); 1619ffba718eSDavid Howells if (!call) 162045222b9eSDavid Howells return -ENOMEM; 162145222b9eSDavid Howells 1622d2ddc776SDavid Howells call->key = fc->key; 1623ffba718eSDavid Howells call->out_volstatus = vs; 162445222b9eSDavid Howells 162545222b9eSDavid Howells /* marshall the parameters */ 162645222b9eSDavid Howells bp = call->request; 162745222b9eSDavid Howells bp[0] = htonl(FSGETVOLUMESTATUS); 162845222b9eSDavid Howells bp[1] = htonl(vnode->fid.vid); 162945222b9eSDavid Howells 1630d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1631025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 163220b8391fSDavid Howells afs_set_fc_call(call, fc); 16330b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 16340b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 163545222b9eSDavid Howells } 1636e8d6c554SDavid Howells 1637e8d6c554SDavid Howells /* 1638e8d6c554SDavid Howells * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock 1639e8d6c554SDavid Howells */ 1640d001648eSDavid Howells static int afs_deliver_fs_xxxx_lock(struct afs_call *call) 1641e8d6c554SDavid Howells { 1642e8d6c554SDavid Howells const __be32 *bp; 1643372ee163SDavid Howells int ret; 1644e8d6c554SDavid Howells 1645d001648eSDavid Howells _enter("{%u}", call->unmarshall); 1646e8d6c554SDavid Howells 1647d001648eSDavid Howells ret = afs_transfer_reply(call); 1648372ee163SDavid Howells if (ret < 0) 1649372ee163SDavid Howells return ret; 1650e8d6c554SDavid Howells 1651e8d6c554SDavid Howells /* unmarshall the reply once we've received all of it */ 1652e8d6c554SDavid Howells bp = call->buffer; 1653ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 1654e8d6c554SDavid Howells 1655e8d6c554SDavid Howells _leave(" = 0 [done]"); 1656e8d6c554SDavid Howells return 0; 1657e8d6c554SDavid Howells } 1658e8d6c554SDavid Howells 1659e8d6c554SDavid Howells /* 1660e8d6c554SDavid Howells * FS.SetLock operation type 1661e8d6c554SDavid Howells */ 1662e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSSetLock = { 1663e8d6c554SDavid Howells .name = "FS.SetLock", 1664025db80cSDavid Howells .op = afs_FS_SetLock, 1665e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1666a690f60aSDavid Howells .done = afs_lock_op_done, 1667e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1668e8d6c554SDavid Howells }; 1669e8d6c554SDavid Howells 1670e8d6c554SDavid Howells /* 1671e8d6c554SDavid Howells * FS.ExtendLock operation type 1672e8d6c554SDavid Howells */ 1673e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSExtendLock = { 1674e8d6c554SDavid Howells .name = "FS.ExtendLock", 1675025db80cSDavid Howells .op = afs_FS_ExtendLock, 1676e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1677a690f60aSDavid Howells .done = afs_lock_op_done, 1678e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1679e8d6c554SDavid Howells }; 1680e8d6c554SDavid Howells 1681e8d6c554SDavid Howells /* 1682e8d6c554SDavid Howells * FS.ReleaseLock operation type 1683e8d6c554SDavid Howells */ 1684e8d6c554SDavid Howells static const struct afs_call_type afs_RXFSReleaseLock = { 1685e8d6c554SDavid Howells .name = "FS.ReleaseLock", 1686025db80cSDavid Howells .op = afs_FS_ReleaseLock, 1687e8d6c554SDavid Howells .deliver = afs_deliver_fs_xxxx_lock, 1688e8d6c554SDavid Howells .destructor = afs_flat_call_destructor, 1689e8d6c554SDavid Howells }; 1690e8d6c554SDavid Howells 1691e8d6c554SDavid Howells /* 1692d2ddc776SDavid Howells * Set a lock on a file 1693e8d6c554SDavid Howells */ 1694a58823acSDavid Howells int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type, 1695a58823acSDavid Howells struct afs_status_cb *scb) 1696e8d6c554SDavid Howells { 1697d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1698e8d6c554SDavid Howells struct afs_call *call; 1699f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1700e8d6c554SDavid Howells __be32 *bp; 1701e8d6c554SDavid Howells 170230062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1703a58823acSDavid Howells return yfs_fs_set_lock(fc, type, scb); 170430062bd1SDavid Howells 1705e8d6c554SDavid Howells _enter(""); 1706e8d6c554SDavid Howells 1707f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4); 1708e8d6c554SDavid Howells if (!call) 1709e8d6c554SDavid Howells return -ENOMEM; 1710e8d6c554SDavid Howells 1711d2ddc776SDavid Howells call->key = fc->key; 1712a58823acSDavid Howells call->lvnode = vnode; 1713a58823acSDavid Howells call->out_scb = scb; 1714e8d6c554SDavid Howells 1715e8d6c554SDavid Howells /* marshall the parameters */ 1716e8d6c554SDavid Howells bp = call->request; 1717e8d6c554SDavid Howells *bp++ = htonl(FSSETLOCK); 1718e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1719e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1720e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1721e8d6c554SDavid Howells *bp++ = htonl(type); 1722e8d6c554SDavid Howells 1723d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 17246c6c1d63SDavid Howells trace_afs_make_fs_calli(call, &vnode->fid, type); 172520b8391fSDavid Howells afs_set_fc_call(call, fc); 17260b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17270b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1728e8d6c554SDavid Howells } 1729e8d6c554SDavid Howells 1730e8d6c554SDavid Howells /* 1731e8d6c554SDavid Howells * extend a lock on a file 1732e8d6c554SDavid Howells */ 1733a58823acSDavid Howells int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1734e8d6c554SDavid Howells { 1735d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1736e8d6c554SDavid Howells struct afs_call *call; 1737f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1738e8d6c554SDavid Howells __be32 *bp; 1739e8d6c554SDavid Howells 174030062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1741a58823acSDavid Howells return yfs_fs_extend_lock(fc, scb); 174230062bd1SDavid Howells 1743e8d6c554SDavid Howells _enter(""); 1744e8d6c554SDavid Howells 1745f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4); 1746e8d6c554SDavid Howells if (!call) 1747e8d6c554SDavid Howells return -ENOMEM; 1748e8d6c554SDavid Howells 1749d2ddc776SDavid Howells call->key = fc->key; 1750a58823acSDavid Howells call->lvnode = vnode; 1751a58823acSDavid Howells call->out_scb = scb; 1752e8d6c554SDavid Howells 1753e8d6c554SDavid Howells /* marshall the parameters */ 1754e8d6c554SDavid Howells bp = call->request; 1755e8d6c554SDavid Howells *bp++ = htonl(FSEXTENDLOCK); 1756e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1757e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1758e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1759e8d6c554SDavid Howells 1760d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1761025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 176220b8391fSDavid Howells afs_set_fc_call(call, fc); 17630b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 17640b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1765e8d6c554SDavid Howells } 1766e8d6c554SDavid Howells 1767e8d6c554SDavid Howells /* 1768e8d6c554SDavid Howells * release a lock on a file 1769e8d6c554SDavid Howells */ 1770a58823acSDavid Howells int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) 1771e8d6c554SDavid Howells { 1772d2ddc776SDavid Howells struct afs_vnode *vnode = fc->vnode; 1773e8d6c554SDavid Howells struct afs_call *call; 1774f044c884SDavid Howells struct afs_net *net = afs_v2net(vnode); 1775e8d6c554SDavid Howells __be32 *bp; 1776e8d6c554SDavid Howells 177730062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1778a58823acSDavid Howells return yfs_fs_release_lock(fc, scb); 177930062bd1SDavid Howells 1780e8d6c554SDavid Howells _enter(""); 1781e8d6c554SDavid Howells 1782f044c884SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4); 1783e8d6c554SDavid Howells if (!call) 1784e8d6c554SDavid Howells return -ENOMEM; 1785e8d6c554SDavid Howells 1786d2ddc776SDavid Howells call->key = fc->key; 1787a58823acSDavid Howells call->lvnode = vnode; 1788a58823acSDavid Howells call->out_scb = scb; 1789e8d6c554SDavid Howells 1790e8d6c554SDavid Howells /* marshall the parameters */ 1791e8d6c554SDavid Howells bp = call->request; 1792e8d6c554SDavid Howells *bp++ = htonl(FSRELEASELOCK); 1793e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vid); 1794e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.vnode); 1795e8d6c554SDavid Howells *bp++ = htonl(vnode->fid.unique); 1796e8d6c554SDavid Howells 1797d2ddc776SDavid Howells afs_use_fs_server(call, fc->cbi); 1798025db80cSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 179920b8391fSDavid Howells afs_set_fc_call(call, fc); 18000b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 18010b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 1802c435ee34SDavid Howells } 1803c435ee34SDavid Howells 1804c435ee34SDavid Howells /* 1805c435ee34SDavid Howells * Deliver reply data to an FS.GiveUpAllCallBacks operation. 1806c435ee34SDavid Howells */ 1807c435ee34SDavid Howells static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call) 1808c435ee34SDavid Howells { 1809c435ee34SDavid Howells return afs_transfer_reply(call); 1810c435ee34SDavid Howells } 1811c435ee34SDavid Howells 1812c435ee34SDavid Howells /* 1813c435ee34SDavid Howells * FS.GiveUpAllCallBacks operation type 1814c435ee34SDavid Howells */ 1815c435ee34SDavid Howells static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = { 1816c435ee34SDavid Howells .name = "FS.GiveUpAllCallBacks", 1817025db80cSDavid Howells .op = afs_FS_GiveUpAllCallBacks, 1818c435ee34SDavid Howells .deliver = afs_deliver_fs_give_up_all_callbacks, 1819c435ee34SDavid Howells .destructor = afs_flat_call_destructor, 1820c435ee34SDavid Howells }; 1821c435ee34SDavid Howells 1822c435ee34SDavid Howells /* 1823c435ee34SDavid Howells * Flush all the callbacks we have on a server. 1824c435ee34SDavid Howells */ 1825d2ddc776SDavid Howells int afs_fs_give_up_all_callbacks(struct afs_net *net, 1826d2ddc776SDavid Howells struct afs_server *server, 18278b2a464cSDavid Howells struct afs_addr_cursor *ac, 1828d2ddc776SDavid Howells struct key *key) 1829c435ee34SDavid Howells { 1830c435ee34SDavid Howells struct afs_call *call; 1831c435ee34SDavid Howells __be32 *bp; 1832c435ee34SDavid Howells 1833c435ee34SDavid Howells _enter(""); 1834c435ee34SDavid Howells 1835d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0); 1836c435ee34SDavid Howells if (!call) 1837c435ee34SDavid Howells return -ENOMEM; 1838c435ee34SDavid Howells 1839c435ee34SDavid Howells call->key = key; 1840c435ee34SDavid Howells 1841c435ee34SDavid Howells /* marshall the parameters */ 1842c435ee34SDavid Howells bp = call->request; 1843c435ee34SDavid Howells *bp++ = htonl(FSGIVEUPALLCALLBACKS); 1844c435ee34SDavid Howells 1845c435ee34SDavid Howells /* Can't take a ref on server */ 18460b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 18470b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, ac); 1848d2ddc776SDavid Howells } 1849d2ddc776SDavid Howells 1850d2ddc776SDavid Howells /* 1851d2ddc776SDavid Howells * Deliver reply data to an FS.GetCapabilities operation. 1852d2ddc776SDavid Howells */ 1853d2ddc776SDavid Howells static int afs_deliver_fs_get_capabilities(struct afs_call *call) 1854d2ddc776SDavid Howells { 1855d2ddc776SDavid Howells u32 count; 1856d2ddc776SDavid Howells int ret; 1857d2ddc776SDavid Howells 1858fc276122SDavid Howells _enter("{%u,%zu}", call->unmarshall, iov_iter_count(call->iter)); 1859d2ddc776SDavid Howells 1860d2ddc776SDavid Howells switch (call->unmarshall) { 1861d2ddc776SDavid Howells case 0: 186212bdcf33SDavid Howells afs_extract_to_tmp(call); 1863d2ddc776SDavid Howells call->unmarshall++; 186429881608SGustavo A. R. Silva /* Fall through */ 1865d2ddc776SDavid Howells 186629881608SGustavo A. R. Silva /* Extract the capabilities word count */ 1867d2ddc776SDavid Howells case 1: 186812bdcf33SDavid Howells ret = afs_extract_data(call, true); 1869d2ddc776SDavid Howells if (ret < 0) 1870d2ddc776SDavid Howells return ret; 1871d2ddc776SDavid Howells 1872d2ddc776SDavid Howells count = ntohl(call->tmp); 1873d2ddc776SDavid Howells 1874d2ddc776SDavid Howells call->count = count; 1875d2ddc776SDavid Howells call->count2 = count; 187623a28913SDavid Howells afs_extract_discard(call, count * sizeof(__be32)); 1877d2ddc776SDavid Howells call->unmarshall++; 187829881608SGustavo A. R. Silva /* Fall through */ 1879d2ddc776SDavid Howells 188029881608SGustavo A. R. Silva /* Extract capabilities words */ 1881d2ddc776SDavid Howells case 2: 188212bdcf33SDavid Howells ret = afs_extract_data(call, false); 1883d2ddc776SDavid Howells if (ret < 0) 1884d2ddc776SDavid Howells return ret; 1885d2ddc776SDavid Howells 1886d2ddc776SDavid Howells /* TODO: Examine capabilities */ 1887d2ddc776SDavid Howells 1888d2ddc776SDavid Howells call->unmarshall++; 1889d2ddc776SDavid Howells break; 1890d2ddc776SDavid Howells } 1891d2ddc776SDavid Howells 1892d2ddc776SDavid Howells _leave(" = 0 [done]"); 1893d2ddc776SDavid Howells return 0; 1894d2ddc776SDavid Howells } 1895d2ddc776SDavid Howells 1896d2ddc776SDavid Howells /* 1897d2ddc776SDavid Howells * FS.GetCapabilities operation type 1898d2ddc776SDavid Howells */ 1899d2ddc776SDavid Howells static const struct afs_call_type afs_RXFSGetCapabilities = { 1900d2ddc776SDavid Howells .name = "FS.GetCapabilities", 1901025db80cSDavid Howells .op = afs_FS_GetCapabilities, 1902d2ddc776SDavid Howells .deliver = afs_deliver_fs_get_capabilities, 19033bf0fb6fSDavid Howells .done = afs_fileserver_probe_result, 1904ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 1905d2ddc776SDavid Howells }; 1906d2ddc776SDavid Howells 1907d2ddc776SDavid Howells /* 1908d2ddc776SDavid Howells * Probe a fileserver for the capabilities that it supports. This can 1909d2ddc776SDavid Howells * return up to 196 words. 1910d2ddc776SDavid Howells */ 19110b9bf381SDavid Howells struct afs_call *afs_fs_get_capabilities(struct afs_net *net, 1912d2ddc776SDavid Howells struct afs_server *server, 1913d2ddc776SDavid Howells struct afs_addr_cursor *ac, 19143bf0fb6fSDavid Howells struct key *key, 19150b9bf381SDavid Howells unsigned int server_index) 1916d2ddc776SDavid Howells { 1917d2ddc776SDavid Howells struct afs_call *call; 1918d2ddc776SDavid Howells __be32 *bp; 1919d2ddc776SDavid Howells 1920d2ddc776SDavid Howells _enter(""); 1921d2ddc776SDavid Howells 1922d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4); 1923d2ddc776SDavid Howells if (!call) 19240b9bf381SDavid Howells return ERR_PTR(-ENOMEM); 1925d2ddc776SDavid Howells 1926d2ddc776SDavid Howells call->key = key; 192745218193SDavid Howells call->server = afs_get_server(server, afs_server_trace_get_caps); 1928ffba718eSDavid Howells call->server_index = server_index; 192930062bd1SDavid Howells call->upgrade = true; 19300b9bf381SDavid Howells call->async = true; 193194f699c9SDavid Howells call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; 1932d2ddc776SDavid Howells 1933d2ddc776SDavid Howells /* marshall the parameters */ 1934d2ddc776SDavid Howells bp = call->request; 1935d2ddc776SDavid Howells *bp++ = htonl(FSGETCAPABILITIES); 1936d2ddc776SDavid Howells 1937d2ddc776SDavid Howells /* Can't take a ref on server */ 1938025db80cSDavid Howells trace_afs_make_fs_call(call, NULL); 19390b9bf381SDavid Howells afs_make_call(ac, call, GFP_NOFS); 19400b9bf381SDavid Howells return call; 1941e8d6c554SDavid Howells } 19425cf9dd55SDavid Howells 19435cf9dd55SDavid Howells /* 19445cf9dd55SDavid Howells * Deliver reply data to an FS.FetchStatus with no vnode. 19455cf9dd55SDavid Howells */ 19465cf9dd55SDavid Howells static int afs_deliver_fs_fetch_status(struct afs_call *call) 19475cf9dd55SDavid Howells { 19485cf9dd55SDavid Howells const __be32 *bp; 19495cf9dd55SDavid Howells int ret; 19505cf9dd55SDavid Howells 19515cf9dd55SDavid Howells ret = afs_transfer_reply(call); 19525cf9dd55SDavid Howells if (ret < 0) 19535cf9dd55SDavid Howells return ret; 19545cf9dd55SDavid Howells 19555cf9dd55SDavid Howells /* unmarshall the reply once we've received all of it */ 19565cf9dd55SDavid Howells bp = call->buffer; 1957a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 1958160cb957SDavid Howells if (ret < 0) 1959160cb957SDavid Howells return ret; 1960a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, call->out_scb); 1961a58823acSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 19625cf9dd55SDavid Howells 19635cf9dd55SDavid Howells _leave(" = 0 [done]"); 19645cf9dd55SDavid Howells return 0; 19655cf9dd55SDavid Howells } 19665cf9dd55SDavid Howells 19675cf9dd55SDavid Howells /* 19685cf9dd55SDavid Howells * FS.FetchStatus operation type 19695cf9dd55SDavid Howells */ 19705cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSFetchStatus = { 19715cf9dd55SDavid Howells .name = "FS.FetchStatus", 19725cf9dd55SDavid Howells .op = afs_FS_FetchStatus, 19735cf9dd55SDavid Howells .deliver = afs_deliver_fs_fetch_status, 19745cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 19755cf9dd55SDavid Howells }; 19765cf9dd55SDavid Howells 19775cf9dd55SDavid Howells /* 19785cf9dd55SDavid Howells * Fetch the status information for a fid without needing a vnode handle. 19795cf9dd55SDavid Howells */ 19805cf9dd55SDavid Howells int afs_fs_fetch_status(struct afs_fs_cursor *fc, 19815cf9dd55SDavid Howells struct afs_net *net, 19825cf9dd55SDavid Howells struct afs_fid *fid, 1983a58823acSDavid Howells struct afs_status_cb *scb, 19845cf9dd55SDavid Howells struct afs_volsync *volsync) 19855cf9dd55SDavid Howells { 19865cf9dd55SDavid Howells struct afs_call *call; 19875cf9dd55SDavid Howells __be32 *bp; 19885cf9dd55SDavid Howells 198930062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 1990a58823acSDavid Howells return yfs_fs_fetch_status(fc, net, fid, scb, volsync); 199130062bd1SDavid Howells 19923b6492dfSDavid Howells _enter(",%x,{%llx:%llu},,", 19935cf9dd55SDavid Howells key_serial(fc->key), fid->vid, fid->vnode); 19945cf9dd55SDavid Howells 19955cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); 19965cf9dd55SDavid Howells if (!call) { 19975cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 19985cf9dd55SDavid Howells return -ENOMEM; 19995cf9dd55SDavid Howells } 20005cf9dd55SDavid Howells 20015cf9dd55SDavid Howells call->key = fc->key; 2002ffba718eSDavid Howells call->out_fid = fid; 2003a58823acSDavid Howells call->out_scb = scb; 2004ffba718eSDavid Howells call->out_volsync = volsync; 20055cf9dd55SDavid Howells 20065cf9dd55SDavid Howells /* marshall the parameters */ 20075cf9dd55SDavid Howells bp = call->request; 20085cf9dd55SDavid Howells bp[0] = htonl(FSFETCHSTATUS); 20095cf9dd55SDavid Howells bp[1] = htonl(fid->vid); 20105cf9dd55SDavid Howells bp[2] = htonl(fid->vnode); 20115cf9dd55SDavid Howells bp[3] = htonl(fid->unique); 20125cf9dd55SDavid Howells 20135cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 20145cf9dd55SDavid Howells trace_afs_make_fs_call(call, fid); 201520b8391fSDavid Howells afs_set_fc_call(call, fc); 20160b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 20170b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 20185cf9dd55SDavid Howells } 20195cf9dd55SDavid Howells 20205cf9dd55SDavid Howells /* 20215cf9dd55SDavid Howells * Deliver reply data to an FS.InlineBulkStatus call 20225cf9dd55SDavid Howells */ 20235cf9dd55SDavid Howells static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) 20245cf9dd55SDavid Howells { 202587182759SDavid Howells struct afs_status_cb *scb; 20265cf9dd55SDavid Howells const __be32 *bp; 20275cf9dd55SDavid Howells u32 tmp; 20285cf9dd55SDavid Howells int ret; 20295cf9dd55SDavid Howells 20305cf9dd55SDavid Howells _enter("{%u}", call->unmarshall); 20315cf9dd55SDavid Howells 20325cf9dd55SDavid Howells switch (call->unmarshall) { 20335cf9dd55SDavid Howells case 0: 203412bdcf33SDavid Howells afs_extract_to_tmp(call); 20355cf9dd55SDavid Howells call->unmarshall++; 203629881608SGustavo A. R. Silva /* Fall through */ 20375cf9dd55SDavid Howells 20385cf9dd55SDavid Howells /* Extract the file status count and array in two steps */ 20395cf9dd55SDavid Howells case 1: 20405cf9dd55SDavid Howells _debug("extract status count"); 204112bdcf33SDavid Howells ret = afs_extract_data(call, true); 20425cf9dd55SDavid Howells if (ret < 0) 20435cf9dd55SDavid Howells return ret; 20445cf9dd55SDavid Howells 20455cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20465cf9dd55SDavid Howells _debug("status count: %u/%u", tmp, call->count2); 20475cf9dd55SDavid Howells if (tmp != call->count2) 2048160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2049160cb957SDavid Howells afs_eproto_ibulkst_count); 20505cf9dd55SDavid Howells 20515cf9dd55SDavid Howells call->count = 0; 20525cf9dd55SDavid Howells call->unmarshall++; 20535cf9dd55SDavid Howells more_counts: 205412bdcf33SDavid Howells afs_extract_to_buf(call, 21 * sizeof(__be32)); 2055e690c9e3SGustavo A. R. Silva /* Fall through */ 205629881608SGustavo A. R. Silva 20575cf9dd55SDavid Howells case 2: 20585cf9dd55SDavid Howells _debug("extract status array %u", call->count); 205912bdcf33SDavid Howells ret = afs_extract_data(call, true); 20605cf9dd55SDavid Howells if (ret < 0) 20615cf9dd55SDavid Howells return ret; 20625cf9dd55SDavid Howells 20635cf9dd55SDavid Howells bp = call->buffer; 206487182759SDavid Howells scb = &call->out_scb[call->count]; 2065a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, scb); 2066160cb957SDavid Howells if (ret < 0) 2067160cb957SDavid Howells return ret; 20685cf9dd55SDavid Howells 20695cf9dd55SDavid Howells call->count++; 20705cf9dd55SDavid Howells if (call->count < call->count2) 20715cf9dd55SDavid Howells goto more_counts; 20725cf9dd55SDavid Howells 20735cf9dd55SDavid Howells call->count = 0; 20745cf9dd55SDavid Howells call->unmarshall++; 207512bdcf33SDavid Howells afs_extract_to_tmp(call); 207629881608SGustavo A. R. Silva /* Fall through */ 20775cf9dd55SDavid Howells 20785cf9dd55SDavid Howells /* Extract the callback count and array in two steps */ 20795cf9dd55SDavid Howells case 3: 20805cf9dd55SDavid Howells _debug("extract CB count"); 208112bdcf33SDavid Howells ret = afs_extract_data(call, true); 20825cf9dd55SDavid Howells if (ret < 0) 20835cf9dd55SDavid Howells return ret; 20845cf9dd55SDavid Howells 20855cf9dd55SDavid Howells tmp = ntohl(call->tmp); 20865cf9dd55SDavid Howells _debug("CB count: %u", tmp); 20875cf9dd55SDavid Howells if (tmp != call->count2) 2088160cb957SDavid Howells return afs_protocol_error(call, -EBADMSG, 2089160cb957SDavid Howells afs_eproto_ibulkst_cb_count); 20905cf9dd55SDavid Howells call->count = 0; 20915cf9dd55SDavid Howells call->unmarshall++; 20925cf9dd55SDavid Howells more_cbs: 209312bdcf33SDavid Howells afs_extract_to_buf(call, 3 * sizeof(__be32)); 2094e690c9e3SGustavo A. R. Silva /* Fall through */ 209529881608SGustavo A. R. Silva 20965cf9dd55SDavid Howells case 4: 20975cf9dd55SDavid Howells _debug("extract CB array"); 209812bdcf33SDavid Howells ret = afs_extract_data(call, true); 20995cf9dd55SDavid Howells if (ret < 0) 21005cf9dd55SDavid Howells return ret; 21015cf9dd55SDavid Howells 21025cf9dd55SDavid Howells _debug("unmarshall CB array"); 21035cf9dd55SDavid Howells bp = call->buffer; 210487182759SDavid Howells scb = &call->out_scb[call->count]; 2105a58823acSDavid Howells xdr_decode_AFSCallBack(&bp, call, scb); 21065cf9dd55SDavid Howells call->count++; 21075cf9dd55SDavid Howells if (call->count < call->count2) 21085cf9dd55SDavid Howells goto more_cbs; 21095cf9dd55SDavid Howells 211012bdcf33SDavid Howells afs_extract_to_buf(call, 6 * sizeof(__be32)); 21115cf9dd55SDavid Howells call->unmarshall++; 2112e690c9e3SGustavo A. R. Silva /* Fall through */ 211329881608SGustavo A. R. Silva 21145cf9dd55SDavid Howells case 5: 211512bdcf33SDavid Howells ret = afs_extract_data(call, false); 21165cf9dd55SDavid Howells if (ret < 0) 21175cf9dd55SDavid Howells return ret; 21185cf9dd55SDavid Howells 21195cf9dd55SDavid Howells bp = call->buffer; 2120ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 21215cf9dd55SDavid Howells 21225cf9dd55SDavid Howells call->unmarshall++; 21235cf9dd55SDavid Howells 21245cf9dd55SDavid Howells case 6: 21255cf9dd55SDavid Howells break; 21265cf9dd55SDavid Howells } 21275cf9dd55SDavid Howells 21285cf9dd55SDavid Howells _leave(" = 0 [done]"); 21295cf9dd55SDavid Howells return 0; 21305cf9dd55SDavid Howells } 21315cf9dd55SDavid Howells 21325cf9dd55SDavid Howells /* 21335cf9dd55SDavid Howells * FS.InlineBulkStatus operation type 21345cf9dd55SDavid Howells */ 21355cf9dd55SDavid Howells static const struct afs_call_type afs_RXFSInlineBulkStatus = { 21365cf9dd55SDavid Howells .name = "FS.InlineBulkStatus", 21375cf9dd55SDavid Howells .op = afs_FS_InlineBulkStatus, 21385cf9dd55SDavid Howells .deliver = afs_deliver_fs_inline_bulk_status, 21395cf9dd55SDavid Howells .destructor = afs_flat_call_destructor, 21405cf9dd55SDavid Howells }; 21415cf9dd55SDavid Howells 21425cf9dd55SDavid Howells /* 21435cf9dd55SDavid Howells * Fetch the status information for up to 50 files 21445cf9dd55SDavid Howells */ 21455cf9dd55SDavid Howells int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, 21465cf9dd55SDavid Howells struct afs_net *net, 21475cf9dd55SDavid Howells struct afs_fid *fids, 214887182759SDavid Howells struct afs_status_cb *statuses, 21495cf9dd55SDavid Howells unsigned int nr_fids, 21505cf9dd55SDavid Howells struct afs_volsync *volsync) 21515cf9dd55SDavid Howells { 21525cf9dd55SDavid Howells struct afs_call *call; 21535cf9dd55SDavid Howells __be32 *bp; 21545cf9dd55SDavid Howells int i; 21555cf9dd55SDavid Howells 215630062bd1SDavid Howells if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) 215787182759SDavid Howells return yfs_fs_inline_bulk_status(fc, net, fids, statuses, 215830062bd1SDavid Howells nr_fids, volsync); 215930062bd1SDavid Howells 21603b6492dfSDavid Howells _enter(",%x,{%llx:%llu},%u", 21615cf9dd55SDavid Howells key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); 21625cf9dd55SDavid Howells 21635cf9dd55SDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus, 21645cf9dd55SDavid Howells (2 + nr_fids * 3) * 4, 21655cf9dd55SDavid Howells 21 * 4); 21665cf9dd55SDavid Howells if (!call) { 21675cf9dd55SDavid Howells fc->ac.error = -ENOMEM; 21685cf9dd55SDavid Howells return -ENOMEM; 21695cf9dd55SDavid Howells } 21705cf9dd55SDavid Howells 21715cf9dd55SDavid Howells call->key = fc->key; 217287182759SDavid Howells call->out_scb = statuses; 2173ffba718eSDavid Howells call->out_volsync = volsync; 21745cf9dd55SDavid Howells call->count2 = nr_fids; 21755cf9dd55SDavid Howells 21765cf9dd55SDavid Howells /* marshall the parameters */ 21775cf9dd55SDavid Howells bp = call->request; 21785cf9dd55SDavid Howells *bp++ = htonl(FSINLINEBULKSTATUS); 21795cf9dd55SDavid Howells *bp++ = htonl(nr_fids); 21805cf9dd55SDavid Howells for (i = 0; i < nr_fids; i++) { 21815cf9dd55SDavid Howells *bp++ = htonl(fids[i].vid); 21825cf9dd55SDavid Howells *bp++ = htonl(fids[i].vnode); 21835cf9dd55SDavid Howells *bp++ = htonl(fids[i].unique); 21845cf9dd55SDavid Howells } 21855cf9dd55SDavid Howells 21865cf9dd55SDavid Howells afs_use_fs_server(call, fc->cbi); 21875cf9dd55SDavid Howells trace_afs_make_fs_call(call, &fids[0]); 218820b8391fSDavid Howells afs_set_fc_call(call, fc); 21890b9bf381SDavid Howells afs_make_call(&fc->ac, call, GFP_NOFS); 21900b9bf381SDavid Howells return afs_wait_for_call_to_complete(call, &fc->ac); 21915cf9dd55SDavid Howells } 2192260f082bSDavid Howells 2193260f082bSDavid Howells /* 2194260f082bSDavid Howells * deliver reply data to an FS.FetchACL 2195260f082bSDavid Howells */ 2196260f082bSDavid Howells static int afs_deliver_fs_fetch_acl(struct afs_call *call) 2197260f082bSDavid Howells { 2198260f082bSDavid Howells struct afs_acl *acl; 2199260f082bSDavid Howells const __be32 *bp; 2200260f082bSDavid Howells unsigned int size; 2201260f082bSDavid Howells int ret; 2202260f082bSDavid Howells 2203260f082bSDavid Howells _enter("{%u}", call->unmarshall); 2204260f082bSDavid Howells 2205260f082bSDavid Howells switch (call->unmarshall) { 2206260f082bSDavid Howells case 0: 2207260f082bSDavid Howells afs_extract_to_tmp(call); 2208260f082bSDavid Howells call->unmarshall++; 220929881608SGustavo A. R. Silva /* Fall through */ 2210260f082bSDavid Howells 2211260f082bSDavid Howells /* extract the returned data length */ 2212260f082bSDavid Howells case 1: 2213260f082bSDavid Howells ret = afs_extract_data(call, true); 2214260f082bSDavid Howells if (ret < 0) 2215260f082bSDavid Howells return ret; 2216260f082bSDavid Howells 2217260f082bSDavid Howells size = call->count2 = ntohl(call->tmp); 2218260f082bSDavid Howells size = round_up(size, 4); 2219260f082bSDavid Howells 2220260f082bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); 2221260f082bSDavid Howells if (!acl) 2222260f082bSDavid Howells return -ENOMEM; 2223ffba718eSDavid Howells call->ret_acl = acl; 2224260f082bSDavid Howells acl->size = call->count2; 2225260f082bSDavid Howells afs_extract_begin(call, acl->data, size); 2226260f082bSDavid Howells call->unmarshall++; 222729881608SGustavo A. R. Silva /* Fall through */ 2228260f082bSDavid Howells 2229260f082bSDavid Howells /* extract the returned data */ 2230260f082bSDavid Howells case 2: 2231260f082bSDavid Howells ret = afs_extract_data(call, true); 2232260f082bSDavid Howells if (ret < 0) 2233260f082bSDavid Howells return ret; 2234260f082bSDavid Howells 2235260f082bSDavid Howells afs_extract_to_buf(call, (21 + 6) * 4); 2236260f082bSDavid Howells call->unmarshall++; 223729881608SGustavo A. R. Silva /* Fall through */ 2238260f082bSDavid Howells 2239260f082bSDavid Howells /* extract the metadata */ 2240260f082bSDavid Howells case 3: 2241260f082bSDavid Howells ret = afs_extract_data(call, false); 2242260f082bSDavid Howells if (ret < 0) 2243260f082bSDavid Howells return ret; 2244260f082bSDavid Howells 2245260f082bSDavid Howells bp = call->buffer; 2246a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2247260f082bSDavid Howells if (ret < 0) 2248260f082bSDavid Howells return ret; 2249ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2250260f082bSDavid Howells 2251260f082bSDavid Howells call->unmarshall++; 2252260f082bSDavid Howells 2253260f082bSDavid Howells case 4: 2254260f082bSDavid Howells break; 2255260f082bSDavid Howells } 2256260f082bSDavid Howells 2257260f082bSDavid Howells _leave(" = 0 [done]"); 2258260f082bSDavid Howells return 0; 2259260f082bSDavid Howells } 2260260f082bSDavid Howells 2261260f082bSDavid Howells static void afs_destroy_fs_fetch_acl(struct afs_call *call) 2262260f082bSDavid Howells { 2263ffba718eSDavid Howells kfree(call->ret_acl); 2264260f082bSDavid Howells afs_flat_call_destructor(call); 2265260f082bSDavid Howells } 2266260f082bSDavid Howells 2267260f082bSDavid Howells /* 2268260f082bSDavid Howells * FS.FetchACL operation type 2269260f082bSDavid Howells */ 2270260f082bSDavid Howells static const struct afs_call_type afs_RXFSFetchACL = { 2271260f082bSDavid Howells .name = "FS.FetchACL", 2272260f082bSDavid Howells .op = afs_FS_FetchACL, 2273260f082bSDavid Howells .deliver = afs_deliver_fs_fetch_acl, 2274260f082bSDavid Howells .destructor = afs_destroy_fs_fetch_acl, 2275260f082bSDavid Howells }; 2276260f082bSDavid Howells 2277260f082bSDavid Howells /* 2278260f082bSDavid Howells * Fetch the ACL for a file. 2279260f082bSDavid Howells */ 2280a58823acSDavid Howells struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc, 2281a58823acSDavid Howells struct afs_status_cb *scb) 2282260f082bSDavid Howells { 2283260f082bSDavid Howells struct afs_vnode *vnode = fc->vnode; 2284260f082bSDavid Howells struct afs_call *call; 2285260f082bSDavid Howells struct afs_net *net = afs_v2net(vnode); 2286260f082bSDavid Howells __be32 *bp; 2287260f082bSDavid Howells 2288260f082bSDavid Howells _enter(",%x,{%llx:%llu},,", 2289260f082bSDavid Howells key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2290260f082bSDavid Howells 2291260f082bSDavid Howells call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4); 2292260f082bSDavid Howells if (!call) { 2293260f082bSDavid Howells fc->ac.error = -ENOMEM; 2294260f082bSDavid Howells return ERR_PTR(-ENOMEM); 2295260f082bSDavid Howells } 2296260f082bSDavid Howells 2297260f082bSDavid Howells call->key = fc->key; 2298ffba718eSDavid Howells call->ret_acl = NULL; 2299a58823acSDavid Howells call->out_scb = scb; 2300ffba718eSDavid Howells call->out_volsync = NULL; 2301260f082bSDavid Howells 2302260f082bSDavid Howells /* marshall the parameters */ 2303260f082bSDavid Howells bp = call->request; 2304260f082bSDavid Howells bp[0] = htonl(FSFETCHACL); 2305260f082bSDavid Howells bp[1] = htonl(vnode->fid.vid); 2306260f082bSDavid Howells bp[2] = htonl(vnode->fid.vnode); 2307260f082bSDavid Howells bp[3] = htonl(vnode->fid.unique); 2308260f082bSDavid Howells 2309260f082bSDavid Howells afs_use_fs_server(call, fc->cbi); 2310260f082bSDavid Howells trace_afs_make_fs_call(call, &vnode->fid); 2311260f082bSDavid Howells afs_make_call(&fc->ac, call, GFP_KERNEL); 2312260f082bSDavid Howells return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac); 2313260f082bSDavid Howells } 2314b10494afSJoe Gorse 2315b10494afSJoe Gorse /* 2316ffba718eSDavid Howells * Deliver reply data to any operation that returns file status and volume 2317ffba718eSDavid Howells * sync. 2318ffba718eSDavid Howells */ 2319ffba718eSDavid Howells static int afs_deliver_fs_file_status_and_vol(struct afs_call *call) 2320ffba718eSDavid Howells { 2321ffba718eSDavid Howells const __be32 *bp; 2322ffba718eSDavid Howells int ret; 2323ffba718eSDavid Howells 2324ffba718eSDavid Howells ret = afs_transfer_reply(call); 2325ffba718eSDavid Howells if (ret < 0) 2326ffba718eSDavid Howells return ret; 2327ffba718eSDavid Howells 2328ffba718eSDavid Howells bp = call->buffer; 2329a58823acSDavid Howells ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); 2330ffba718eSDavid Howells if (ret < 0) 2331ffba718eSDavid Howells return ret; 2332ffba718eSDavid Howells xdr_decode_AFSVolSync(&bp, call->out_volsync); 2333ffba718eSDavid Howells 2334ffba718eSDavid Howells _leave(" = 0 [done]"); 2335ffba718eSDavid Howells return 0; 2336ffba718eSDavid Howells } 2337ffba718eSDavid Howells 2338ffba718eSDavid Howells /* 2339b10494afSJoe Gorse * FS.StoreACL operation type 2340b10494afSJoe Gorse */ 2341b10494afSJoe Gorse static const struct afs_call_type afs_RXFSStoreACL = { 2342b10494afSJoe Gorse .name = "FS.StoreACL", 2343b10494afSJoe Gorse .op = afs_FS_StoreACL, 2344ffba718eSDavid Howells .deliver = afs_deliver_fs_file_status_and_vol, 2345b10494afSJoe Gorse .destructor = afs_flat_call_destructor, 2346b10494afSJoe Gorse }; 2347b10494afSJoe Gorse 2348b10494afSJoe Gorse /* 2349b10494afSJoe Gorse * Fetch the ACL for a file. 2350b10494afSJoe Gorse */ 2351a58823acSDavid Howells int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl, 2352a58823acSDavid Howells struct afs_status_cb *scb) 2353b10494afSJoe Gorse { 2354b10494afSJoe Gorse struct afs_vnode *vnode = fc->vnode; 2355b10494afSJoe Gorse struct afs_call *call; 2356b10494afSJoe Gorse struct afs_net *net = afs_v2net(vnode); 2357b10494afSJoe Gorse size_t size; 2358b10494afSJoe Gorse __be32 *bp; 2359b10494afSJoe Gorse 2360b10494afSJoe Gorse _enter(",%x,{%llx:%llu},,", 2361b10494afSJoe Gorse key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); 2362b10494afSJoe Gorse 2363b10494afSJoe Gorse size = round_up(acl->size, 4); 2364b10494afSJoe Gorse call = afs_alloc_flat_call(net, &afs_RXFSStoreACL, 2365b10494afSJoe Gorse 5 * 4 + size, (21 + 6) * 4); 2366b10494afSJoe Gorse if (!call) { 2367b10494afSJoe Gorse fc->ac.error = -ENOMEM; 2368b10494afSJoe Gorse return -ENOMEM; 2369b10494afSJoe Gorse } 2370b10494afSJoe Gorse 2371b10494afSJoe Gorse call->key = fc->key; 2372a58823acSDavid Howells call->out_scb = scb; 2373ffba718eSDavid Howells call->out_volsync = NULL; 2374b10494afSJoe Gorse 2375b10494afSJoe Gorse /* marshall the parameters */ 2376b10494afSJoe Gorse bp = call->request; 2377b10494afSJoe Gorse bp[0] = htonl(FSSTOREACL); 2378b10494afSJoe Gorse bp[1] = htonl(vnode->fid.vid); 2379b10494afSJoe Gorse bp[2] = htonl(vnode->fid.vnode); 2380b10494afSJoe Gorse bp[3] = htonl(vnode->fid.unique); 2381b10494afSJoe Gorse bp[4] = htonl(acl->size); 2382b10494afSJoe Gorse memcpy(&bp[5], acl->data, acl->size); 2383b10494afSJoe Gorse if (acl->size != size) 2384b10494afSJoe Gorse memset((void *)&bp[5] + acl->size, 0, size - acl->size); 2385b10494afSJoe Gorse 2386b10494afSJoe Gorse trace_afs_make_fs_call(call, &vnode->fid); 2387b10494afSJoe Gorse afs_make_call(&fc->ac, call, GFP_KERNEL); 2388b10494afSJoe Gorse return afs_wait_for_call_to_complete(call, &fc->ac); 23891da177e4SLinus Torvalds } 2390