1b4d0d230SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 230062bd1SDavid Howells /* YFS File Server client stubs 330062bd1SDavid Howells * 430062bd1SDavid Howells * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. 530062bd1SDavid Howells * Written by David Howells (dhowells@redhat.com) 630062bd1SDavid Howells */ 730062bd1SDavid Howells 830062bd1SDavid Howells #include <linux/init.h> 930062bd1SDavid Howells #include <linux/slab.h> 1030062bd1SDavid Howells #include <linux/sched.h> 1130062bd1SDavid Howells #include <linux/circ_buf.h> 1230062bd1SDavid Howells #include <linux/iversion.h> 1330062bd1SDavid Howells #include "internal.h" 1430062bd1SDavid Howells #include "afs_fs.h" 1530062bd1SDavid Howells #include "xdr_fs.h" 1630062bd1SDavid Howells #include "protocol_yfs.h" 1730062bd1SDavid Howells 1830062bd1SDavid Howells #define xdr_size(x) (sizeof(*x) / sizeof(__be32)) 1930062bd1SDavid Howells 2030062bd1SDavid Howells static void xdr_decode_YFSFid(const __be32 **_bp, struct afs_fid *fid) 2130062bd1SDavid Howells { 2230062bd1SDavid Howells const struct yfs_xdr_YFSFid *x = (const void *)*_bp; 2330062bd1SDavid Howells 2430062bd1SDavid Howells fid->vid = xdr_to_u64(x->volume); 2530062bd1SDavid Howells fid->vnode = xdr_to_u64(x->vnode.lo); 2630062bd1SDavid Howells fid->vnode_hi = ntohl(x->vnode.hi); 2730062bd1SDavid Howells fid->unique = ntohl(x->vnode.unique); 2830062bd1SDavid Howells *_bp += xdr_size(x); 2930062bd1SDavid Howells } 3030062bd1SDavid Howells 3130062bd1SDavid Howells static __be32 *xdr_encode_u32(__be32 *bp, u32 n) 3230062bd1SDavid Howells { 3330062bd1SDavid Howells *bp++ = htonl(n); 3430062bd1SDavid Howells return bp; 3530062bd1SDavid Howells } 3630062bd1SDavid Howells 3730062bd1SDavid Howells static __be32 *xdr_encode_u64(__be32 *bp, u64 n) 3830062bd1SDavid Howells { 3930062bd1SDavid Howells struct yfs_xdr_u64 *x = (void *)bp; 4030062bd1SDavid Howells 4130062bd1SDavid Howells *x = u64_to_xdr(n); 4230062bd1SDavid Howells return bp + xdr_size(x); 4330062bd1SDavid Howells } 4430062bd1SDavid Howells 4530062bd1SDavid Howells static __be32 *xdr_encode_YFSFid(__be32 *bp, struct afs_fid *fid) 4630062bd1SDavid Howells { 4730062bd1SDavid Howells struct yfs_xdr_YFSFid *x = (void *)bp; 4830062bd1SDavid Howells 4930062bd1SDavid Howells x->volume = u64_to_xdr(fid->vid); 5030062bd1SDavid Howells x->vnode.lo = u64_to_xdr(fid->vnode); 5130062bd1SDavid Howells x->vnode.hi = htonl(fid->vnode_hi); 5230062bd1SDavid Howells x->vnode.unique = htonl(fid->unique); 5330062bd1SDavid Howells return bp + xdr_size(x); 5430062bd1SDavid Howells } 5530062bd1SDavid Howells 5630062bd1SDavid Howells static size_t xdr_strlen(unsigned int len) 5730062bd1SDavid Howells { 5830062bd1SDavid Howells return sizeof(__be32) + round_up(len, sizeof(__be32)); 5930062bd1SDavid Howells } 6030062bd1SDavid Howells 6130062bd1SDavid Howells static __be32 *xdr_encode_string(__be32 *bp, const char *p, unsigned int len) 6230062bd1SDavid Howells { 6330062bd1SDavid Howells bp = xdr_encode_u32(bp, len); 6430062bd1SDavid Howells bp = memcpy(bp, p, len); 6530062bd1SDavid Howells if (len & 3) { 6630062bd1SDavid Howells unsigned int pad = 4 - (len & 3); 6730062bd1SDavid Howells 6830062bd1SDavid Howells memset((u8 *)bp + len, 0, pad); 6930062bd1SDavid Howells len += pad; 7030062bd1SDavid Howells } 7130062bd1SDavid Howells 7230062bd1SDavid Howells return bp + len / sizeof(__be32); 7330062bd1SDavid Howells } 7430062bd1SDavid Howells 75e49c7b2fSDavid Howells static __be32 *xdr_encode_name(__be32 *bp, const struct qstr *p) 76e49c7b2fSDavid Howells { 77e49c7b2fSDavid Howells return xdr_encode_string(bp, p->name, p->len); 78e49c7b2fSDavid Howells } 79e49c7b2fSDavid Howells 8030062bd1SDavid Howells static s64 linux_to_yfs_time(const struct timespec64 *t) 8130062bd1SDavid Howells { 8230062bd1SDavid Howells /* Convert to 100ns intervals. */ 8330062bd1SDavid Howells return (u64)t->tv_sec * 10000000 + t->tv_nsec/100; 8430062bd1SDavid Howells } 8530062bd1SDavid Howells 8630062bd1SDavid Howells static __be32 *xdr_encode_YFSStoreStatus_mode(__be32 *bp, mode_t mode) 8730062bd1SDavid Howells { 8830062bd1SDavid Howells struct yfs_xdr_YFSStoreStatus *x = (void *)bp; 8930062bd1SDavid Howells 9030062bd1SDavid Howells x->mask = htonl(AFS_SET_MODE); 9130062bd1SDavid Howells x->mode = htonl(mode & S_IALLUGO); 9230062bd1SDavid Howells x->mtime_client = u64_to_xdr(0); 9330062bd1SDavid Howells x->owner = u64_to_xdr(0); 9430062bd1SDavid Howells x->group = u64_to_xdr(0); 9530062bd1SDavid Howells return bp + xdr_size(x); 9630062bd1SDavid Howells } 9730062bd1SDavid Howells 9830062bd1SDavid Howells static __be32 *xdr_encode_YFSStoreStatus_mtime(__be32 *bp, const struct timespec64 *t) 9930062bd1SDavid Howells { 10030062bd1SDavid Howells struct yfs_xdr_YFSStoreStatus *x = (void *)bp; 10130062bd1SDavid Howells s64 mtime = linux_to_yfs_time(t); 10230062bd1SDavid Howells 10330062bd1SDavid Howells x->mask = htonl(AFS_SET_MTIME); 10430062bd1SDavid Howells x->mode = htonl(0); 10530062bd1SDavid Howells x->mtime_client = u64_to_xdr(mtime); 10630062bd1SDavid Howells x->owner = u64_to_xdr(0); 10730062bd1SDavid Howells x->group = u64_to_xdr(0); 10830062bd1SDavid Howells return bp + xdr_size(x); 10930062bd1SDavid Howells } 11030062bd1SDavid Howells 11130062bd1SDavid Howells /* 11230062bd1SDavid Howells * Convert a signed 100ns-resolution 64-bit time into a timespec. 11330062bd1SDavid Howells */ 11430062bd1SDavid Howells static struct timespec64 yfs_time_to_linux(s64 t) 11530062bd1SDavid Howells { 11630062bd1SDavid Howells struct timespec64 ts; 11730062bd1SDavid Howells u64 abs_t; 11830062bd1SDavid Howells 11930062bd1SDavid Howells /* 12030062bd1SDavid Howells * Unfortunately can not use normal 64 bit division on 32 bit arch, but 12130062bd1SDavid Howells * the alternative, do_div, does not work with negative numbers so have 12230062bd1SDavid Howells * to special case them 12330062bd1SDavid Howells */ 12430062bd1SDavid Howells if (t < 0) { 12530062bd1SDavid Howells abs_t = -t; 12630062bd1SDavid Howells ts.tv_nsec = (time64_t)(do_div(abs_t, 10000000) * 100); 12730062bd1SDavid Howells ts.tv_nsec = -ts.tv_nsec; 12830062bd1SDavid Howells ts.tv_sec = -abs_t; 12930062bd1SDavid Howells } else { 13030062bd1SDavid Howells abs_t = t; 13130062bd1SDavid Howells ts.tv_nsec = (time64_t)do_div(abs_t, 10000000) * 100; 13230062bd1SDavid Howells ts.tv_sec = abs_t; 13330062bd1SDavid Howells } 13430062bd1SDavid Howells 13530062bd1SDavid Howells return ts; 13630062bd1SDavid Howells } 13730062bd1SDavid Howells 13830062bd1SDavid Howells static struct timespec64 xdr_to_time(const struct yfs_xdr_u64 xdr) 13930062bd1SDavid Howells { 14030062bd1SDavid Howells s64 t = xdr_to_u64(xdr); 14130062bd1SDavid Howells 14230062bd1SDavid Howells return yfs_time_to_linux(t); 14330062bd1SDavid Howells } 14430062bd1SDavid Howells 14530062bd1SDavid Howells static void yfs_check_req(struct afs_call *call, __be32 *bp) 14630062bd1SDavid Howells { 14730062bd1SDavid Howells size_t len = (void *)bp - call->request; 14830062bd1SDavid Howells 14930062bd1SDavid Howells if (len > call->request_size) 15030062bd1SDavid Howells pr_err("kAFS: %s: Request buffer overflow (%zu>%u)\n", 15130062bd1SDavid Howells call->type->name, len, call->request_size); 15230062bd1SDavid Howells else if (len < call->request_size) 153a4e530aeSKefeng Wang pr_warn("kAFS: %s: Request buffer underflow (%zu<%u)\n", 15430062bd1SDavid Howells call->type->name, len, call->request_size); 15530062bd1SDavid Howells } 15630062bd1SDavid Howells 15730062bd1SDavid Howells /* 15830062bd1SDavid Howells * Dump a bad file status record. 15930062bd1SDavid Howells */ 16030062bd1SDavid Howells static void xdr_dump_bad(const __be32 *bp) 16130062bd1SDavid Howells { 16230062bd1SDavid Howells __be32 x[4]; 16330062bd1SDavid Howells int i; 16430062bd1SDavid Howells 16530062bd1SDavid Howells pr_notice("YFS XDR: Bad status record\n"); 1663efe55b0SDavid Howells for (i = 0; i < 6 * 4 * 4; i += 16) { 16730062bd1SDavid Howells memcpy(x, bp, 16); 16830062bd1SDavid Howells bp += 4; 16930062bd1SDavid Howells pr_notice("%03x: %08x %08x %08x %08x\n", 17030062bd1SDavid Howells i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3])); 17130062bd1SDavid Howells } 17230062bd1SDavid Howells 1733efe55b0SDavid Howells memcpy(x, bp, 8); 1743efe55b0SDavid Howells pr_notice("0x60: %08x %08x\n", ntohl(x[0]), ntohl(x[1])); 17530062bd1SDavid Howells } 17630062bd1SDavid Howells 17730062bd1SDavid Howells /* 17830062bd1SDavid Howells * Decode a YFSFetchStatus block 17930062bd1SDavid Howells */ 18038355eecSDavid Howells static void xdr_decode_YFSFetchStatus(const __be32 **_bp, 181a58823acSDavid Howells struct afs_call *call, 182a58823acSDavid Howells struct afs_status_cb *scb) 18330062bd1SDavid Howells { 18430062bd1SDavid Howells const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp; 185a58823acSDavid Howells struct afs_file_status *status = &scb->status; 18630062bd1SDavid Howells u32 type; 18730062bd1SDavid Howells 18830062bd1SDavid Howells status->abort_code = ntohl(xdr->abort_code); 18930062bd1SDavid Howells if (status->abort_code != 0) { 190a58823acSDavid Howells if (status->abort_code == VNOVNODE) 19130062bd1SDavid Howells status->nlink = 0; 192a38a7558SDavid Howells scb->have_error = true; 19338355eecSDavid Howells goto advance; 19430062bd1SDavid Howells } 19530062bd1SDavid Howells 19630062bd1SDavid Howells type = ntohl(xdr->type); 19730062bd1SDavid Howells switch (type) { 19830062bd1SDavid Howells case AFS_FTYPE_FILE: 19930062bd1SDavid Howells case AFS_FTYPE_DIR: 20030062bd1SDavid Howells case AFS_FTYPE_SYMLINK: 20130062bd1SDavid Howells status->type = type; 20230062bd1SDavid Howells break; 20330062bd1SDavid Howells default: 20430062bd1SDavid Howells goto bad; 20530062bd1SDavid Howells } 20630062bd1SDavid Howells 207a58823acSDavid Howells status->nlink = ntohl(xdr->nlink); 208a58823acSDavid Howells status->author = xdr_to_u64(xdr->author); 209a58823acSDavid Howells status->owner = xdr_to_u64(xdr->owner); 210a58823acSDavid Howells status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */ 211a58823acSDavid Howells status->anon_access = ntohl(xdr->anon_access); 212a58823acSDavid Howells status->mode = ntohl(xdr->mode) & S_IALLUGO; 213a58823acSDavid Howells status->group = xdr_to_u64(xdr->group); 214a58823acSDavid Howells status->lock_count = ntohl(xdr->lock_count); 21530062bd1SDavid Howells 21630062bd1SDavid Howells status->mtime_client = xdr_to_time(xdr->mtime_client); 21730062bd1SDavid Howells status->mtime_server = xdr_to_time(xdr->mtime_server); 218a58823acSDavid Howells status->size = xdr_to_u64(xdr->size); 219a58823acSDavid Howells status->data_version = xdr_to_u64(xdr->data_version); 220a38a7558SDavid Howells scb->have_status = true; 221c72057b5SDavid Howells advance: 22230062bd1SDavid Howells *_bp += xdr_size(xdr); 22338355eecSDavid Howells return; 22430062bd1SDavid Howells 22530062bd1SDavid Howells bad: 22630062bd1SDavid Howells xdr_dump_bad(*_bp); 2277126ead9SDavid Howells afs_protocol_error(call, afs_eproto_bad_status); 228c72057b5SDavid Howells goto advance; 22930062bd1SDavid Howells } 23030062bd1SDavid Howells 23130062bd1SDavid Howells /* 232a58823acSDavid Howells * Decode a YFSCallBack block 23330062bd1SDavid Howells */ 234a58823acSDavid Howells static void xdr_decode_YFSCallBack(const __be32 **_bp, 235a58823acSDavid Howells struct afs_call *call, 236a58823acSDavid Howells struct afs_status_cb *scb) 23778107055SDavid Howells { 23878107055SDavid Howells struct yfs_xdr_YFSCallBack *x = (void *)*_bp; 239a58823acSDavid Howells struct afs_callback *cb = &scb->callback; 24078107055SDavid Howells ktime_t cb_expiry; 24178107055SDavid Howells 24278107055SDavid Howells cb_expiry = call->reply_time; 24378107055SDavid Howells cb_expiry = ktime_add(cb_expiry, xdr_to_u64(x->expiration_time) * 100); 24478107055SDavid Howells cb->expires_at = ktime_divns(cb_expiry, NSEC_PER_SEC); 245a58823acSDavid Howells scb->have_cb = true; 24678107055SDavid Howells *_bp += xdr_size(x); 24778107055SDavid Howells } 24878107055SDavid Howells 24930062bd1SDavid Howells /* 25030062bd1SDavid Howells * Decode a YFSVolSync block 25130062bd1SDavid Howells */ 25230062bd1SDavid Howells static void xdr_decode_YFSVolSync(const __be32 **_bp, 25330062bd1SDavid Howells struct afs_volsync *volsync) 25430062bd1SDavid Howells { 25530062bd1SDavid Howells struct yfs_xdr_YFSVolSync *x = (void *)*_bp; 25630062bd1SDavid Howells u64 creation; 25730062bd1SDavid Howells 25830062bd1SDavid Howells if (volsync) { 25930062bd1SDavid Howells creation = xdr_to_u64(x->vol_creation_date); 26030062bd1SDavid Howells do_div(creation, 10 * 1000 * 1000); 26130062bd1SDavid Howells volsync->creation = creation; 26230062bd1SDavid Howells } 26330062bd1SDavid Howells 26430062bd1SDavid Howells *_bp += xdr_size(x); 26530062bd1SDavid Howells } 26630062bd1SDavid Howells 26730062bd1SDavid Howells /* 26830062bd1SDavid Howells * Encode the requested attributes into a YFSStoreStatus block 26930062bd1SDavid Howells */ 27030062bd1SDavid Howells static __be32 *xdr_encode_YFS_StoreStatus(__be32 *bp, struct iattr *attr) 27130062bd1SDavid Howells { 27230062bd1SDavid Howells struct yfs_xdr_YFSStoreStatus *x = (void *)bp; 27330062bd1SDavid Howells s64 mtime = 0, owner = 0, group = 0; 27430062bd1SDavid Howells u32 mask = 0, mode = 0; 27530062bd1SDavid Howells 27630062bd1SDavid Howells mask = 0; 27730062bd1SDavid Howells if (attr->ia_valid & ATTR_MTIME) { 27830062bd1SDavid Howells mask |= AFS_SET_MTIME; 27930062bd1SDavid Howells mtime = linux_to_yfs_time(&attr->ia_mtime); 28030062bd1SDavid Howells } 28130062bd1SDavid Howells 28230062bd1SDavid Howells if (attr->ia_valid & ATTR_UID) { 28330062bd1SDavid Howells mask |= AFS_SET_OWNER; 28430062bd1SDavid Howells owner = from_kuid(&init_user_ns, attr->ia_uid); 28530062bd1SDavid Howells } 28630062bd1SDavid Howells 28730062bd1SDavid Howells if (attr->ia_valid & ATTR_GID) { 28830062bd1SDavid Howells mask |= AFS_SET_GROUP; 28930062bd1SDavid Howells group = from_kgid(&init_user_ns, attr->ia_gid); 29030062bd1SDavid Howells } 29130062bd1SDavid Howells 29230062bd1SDavid Howells if (attr->ia_valid & ATTR_MODE) { 29330062bd1SDavid Howells mask |= AFS_SET_MODE; 29430062bd1SDavid Howells mode = attr->ia_mode & S_IALLUGO; 29530062bd1SDavid Howells } 29630062bd1SDavid Howells 29730062bd1SDavid Howells x->mask = htonl(mask); 29830062bd1SDavid Howells x->mode = htonl(mode); 29930062bd1SDavid Howells x->mtime_client = u64_to_xdr(mtime); 30030062bd1SDavid Howells x->owner = u64_to_xdr(owner); 30130062bd1SDavid Howells x->group = u64_to_xdr(group); 30230062bd1SDavid Howells return bp + xdr_size(x); 30330062bd1SDavid Howells } 30430062bd1SDavid Howells 30530062bd1SDavid Howells /* 30630062bd1SDavid Howells * Decode a YFSFetchVolumeStatus block. 30730062bd1SDavid Howells */ 30830062bd1SDavid Howells static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp, 30930062bd1SDavid Howells struct afs_volume_status *vs) 31030062bd1SDavid Howells { 31130062bd1SDavid Howells const struct yfs_xdr_YFSFetchVolumeStatus *x = (const void *)*_bp; 31230062bd1SDavid Howells u32 flags; 31330062bd1SDavid Howells 31430062bd1SDavid Howells vs->vid = xdr_to_u64(x->vid); 31530062bd1SDavid Howells vs->parent_id = xdr_to_u64(x->parent_id); 31630062bd1SDavid Howells flags = ntohl(x->flags); 31730062bd1SDavid Howells vs->online = flags & yfs_FVSOnline; 31830062bd1SDavid Howells vs->in_service = flags & yfs_FVSInservice; 31930062bd1SDavid Howells vs->blessed = flags & yfs_FVSBlessed; 32030062bd1SDavid Howells vs->needs_salvage = flags & yfs_FVSNeedsSalvage; 32130062bd1SDavid Howells vs->type = ntohl(x->type); 32230062bd1SDavid Howells vs->min_quota = 0; 32330062bd1SDavid Howells vs->max_quota = xdr_to_u64(x->max_quota); 32430062bd1SDavid Howells vs->blocks_in_use = xdr_to_u64(x->blocks_in_use); 32530062bd1SDavid Howells vs->part_blocks_avail = xdr_to_u64(x->part_blocks_avail); 32630062bd1SDavid Howells vs->part_max_blocks = xdr_to_u64(x->part_max_blocks); 32730062bd1SDavid Howells vs->vol_copy_date = xdr_to_u64(x->vol_copy_date); 32830062bd1SDavid Howells vs->vol_backup_date = xdr_to_u64(x->vol_backup_date); 32930062bd1SDavid Howells *_bp += sizeof(*x) / sizeof(__be32); 33030062bd1SDavid Howells } 33130062bd1SDavid Howells 33230062bd1SDavid Howells /* 333a58823acSDavid Howells * Deliver reply data to operations that just return a file status and a volume 334a58823acSDavid Howells * sync record. 335a58823acSDavid Howells */ 336a58823acSDavid Howells static int yfs_deliver_status_and_volsync(struct afs_call *call) 337a58823acSDavid Howells { 338e49c7b2fSDavid Howells struct afs_operation *op = call->op; 339a58823acSDavid Howells const __be32 *bp; 340a58823acSDavid Howells int ret; 341a58823acSDavid Howells 342a58823acSDavid Howells ret = afs_transfer_reply(call); 343a58823acSDavid Howells if (ret < 0) 344a58823acSDavid Howells return ret; 345a58823acSDavid Howells 346a58823acSDavid Howells bp = call->buffer; 347e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &op->file[0].scb); 348e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 34930062bd1SDavid Howells 35030062bd1SDavid Howells _leave(" = 0 [done]"); 35130062bd1SDavid Howells return 0; 35230062bd1SDavid Howells } 35330062bd1SDavid Howells 35430062bd1SDavid Howells /* 35530062bd1SDavid Howells * Deliver reply data to an YFS.FetchData64. 35630062bd1SDavid Howells */ 35730062bd1SDavid Howells static int yfs_deliver_fs_fetch_data64(struct afs_call *call) 35830062bd1SDavid Howells { 359e49c7b2fSDavid Howells struct afs_operation *op = call->op; 360e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 361e49c7b2fSDavid Howells struct afs_read *req = op->fetch.req; 36230062bd1SDavid Howells const __be32 *bp; 36330062bd1SDavid Howells unsigned int size; 36430062bd1SDavid Howells int ret; 36530062bd1SDavid Howells 36630062bd1SDavid Howells _enter("{%u,%zu/%llu}", 367fc276122SDavid Howells call->unmarshall, iov_iter_count(call->iter), req->actual_len); 36830062bd1SDavid Howells 36930062bd1SDavid Howells switch (call->unmarshall) { 37030062bd1SDavid Howells case 0: 37130062bd1SDavid Howells req->actual_len = 0; 37230062bd1SDavid Howells req->index = 0; 37330062bd1SDavid Howells req->offset = req->pos & (PAGE_SIZE - 1); 37430062bd1SDavid Howells afs_extract_to_tmp64(call); 37530062bd1SDavid Howells call->unmarshall++; 37635a3a90cSGustavo A. R. Silva /* Fall through */ 37730062bd1SDavid Howells 37835a3a90cSGustavo A. R. Silva /* extract the returned data length */ 37930062bd1SDavid Howells case 1: 38030062bd1SDavid Howells _debug("extract data length"); 38130062bd1SDavid Howells ret = afs_extract_data(call, true); 38230062bd1SDavid Howells if (ret < 0) 38330062bd1SDavid Howells return ret; 38430062bd1SDavid Howells 38530062bd1SDavid Howells req->actual_len = be64_to_cpu(call->tmp64); 38630062bd1SDavid Howells _debug("DATA length: %llu", req->actual_len); 38730062bd1SDavid Howells req->remain = min(req->len, req->actual_len); 38830062bd1SDavid Howells if (req->remain == 0) 38930062bd1SDavid Howells goto no_more_data; 39030062bd1SDavid Howells 39130062bd1SDavid Howells call->unmarshall++; 39230062bd1SDavid Howells 39330062bd1SDavid Howells begin_page: 39430062bd1SDavid Howells ASSERTCMP(req->index, <, req->nr_pages); 39530062bd1SDavid Howells if (req->remain > PAGE_SIZE - req->offset) 39630062bd1SDavid Howells size = PAGE_SIZE - req->offset; 39730062bd1SDavid Howells else 39830062bd1SDavid Howells size = req->remain; 39930062bd1SDavid Howells call->bvec[0].bv_len = size; 40030062bd1SDavid Howells call->bvec[0].bv_offset = req->offset; 40130062bd1SDavid Howells call->bvec[0].bv_page = req->pages[req->index]; 402fc276122SDavid Howells iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); 40330062bd1SDavid Howells ASSERTCMP(size, <=, PAGE_SIZE); 40435a3a90cSGustavo A. R. Silva /* Fall through */ 40530062bd1SDavid Howells 40635a3a90cSGustavo A. R. Silva /* extract the returned data */ 40730062bd1SDavid Howells case 2: 40830062bd1SDavid Howells _debug("extract data %zu/%llu", 409fc276122SDavid Howells iov_iter_count(call->iter), req->remain); 41030062bd1SDavid Howells 41130062bd1SDavid Howells ret = afs_extract_data(call, true); 41230062bd1SDavid Howells if (ret < 0) 41330062bd1SDavid Howells return ret; 41430062bd1SDavid Howells req->remain -= call->bvec[0].bv_len; 41530062bd1SDavid Howells req->offset += call->bvec[0].bv_len; 41630062bd1SDavid Howells ASSERTCMP(req->offset, <=, PAGE_SIZE); 41730062bd1SDavid Howells if (req->offset == PAGE_SIZE) { 41830062bd1SDavid Howells req->offset = 0; 41930062bd1SDavid Howells req->index++; 42030062bd1SDavid Howells if (req->remain > 0) 42130062bd1SDavid Howells goto begin_page; 42230062bd1SDavid Howells } 42330062bd1SDavid Howells 42430062bd1SDavid Howells ASSERTCMP(req->remain, ==, 0); 42530062bd1SDavid Howells if (req->actual_len <= req->len) 42630062bd1SDavid Howells goto no_more_data; 42730062bd1SDavid Howells 42830062bd1SDavid Howells /* Discard any excess data the server gave us */ 42923a28913SDavid Howells afs_extract_discard(call, req->actual_len - req->len); 43030062bd1SDavid Howells call->unmarshall = 3; 431e690c9e3SGustavo A. R. Silva /* Fall through */ 43235a3a90cSGustavo A. R. Silva 43330062bd1SDavid Howells case 3: 43430062bd1SDavid Howells _debug("extract discard %zu/%llu", 435fc276122SDavid Howells iov_iter_count(call->iter), req->actual_len - req->len); 43630062bd1SDavid Howells 43730062bd1SDavid Howells ret = afs_extract_data(call, true); 43830062bd1SDavid Howells if (ret < 0) 43930062bd1SDavid Howells return ret; 44030062bd1SDavid Howells 44130062bd1SDavid Howells no_more_data: 44230062bd1SDavid Howells call->unmarshall = 4; 44330062bd1SDavid Howells afs_extract_to_buf(call, 44430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 44530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) + 44630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 44735a3a90cSGustavo A. R. Silva /* Fall through */ 44830062bd1SDavid Howells 44935a3a90cSGustavo A. R. Silva /* extract the metadata */ 45030062bd1SDavid Howells case 4: 45130062bd1SDavid Howells ret = afs_extract_data(call, false); 45230062bd1SDavid Howells if (ret < 0) 45330062bd1SDavid Howells return ret; 45430062bd1SDavid Howells 45530062bd1SDavid Howells bp = call->buffer; 456e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb); 457e49c7b2fSDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb); 458e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 45930062bd1SDavid Howells 460e49c7b2fSDavid Howells req->data_version = vp->scb.status.data_version; 461e49c7b2fSDavid Howells req->file_size = vp->scb.status.size; 462a58823acSDavid Howells 46330062bd1SDavid Howells call->unmarshall++; 464e690c9e3SGustavo A. R. Silva /* Fall through */ 46535a3a90cSGustavo A. R. Silva 46630062bd1SDavid Howells case 5: 46730062bd1SDavid Howells break; 46830062bd1SDavid Howells } 46930062bd1SDavid Howells 47030062bd1SDavid Howells for (; req->index < req->nr_pages; req->index++) { 47130062bd1SDavid Howells if (req->offset < PAGE_SIZE) 47230062bd1SDavid Howells zero_user_segment(req->pages[req->index], 47330062bd1SDavid Howells req->offset, PAGE_SIZE); 47430062bd1SDavid Howells req->offset = 0; 47530062bd1SDavid Howells } 47630062bd1SDavid Howells 4779d1be4f4SDavid Howells if (req->page_done) 4789d1be4f4SDavid Howells for (req->index = 0; req->index < req->nr_pages; req->index++) 4799d1be4f4SDavid Howells req->page_done(req); 4809d1be4f4SDavid Howells 48130062bd1SDavid Howells _leave(" = 0 [done]"); 48230062bd1SDavid Howells return 0; 48330062bd1SDavid Howells } 48430062bd1SDavid Howells 48530062bd1SDavid Howells /* 48630062bd1SDavid Howells * YFS.FetchData64 operation type 48730062bd1SDavid Howells */ 48830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSFetchData64 = { 48930062bd1SDavid Howells .name = "YFS.FetchData64", 49030062bd1SDavid Howells .op = yfs_FS_FetchData64, 49130062bd1SDavid Howells .deliver = yfs_deliver_fs_fetch_data64, 492e49c7b2fSDavid Howells .destructor = afs_flat_call_destructor, 49330062bd1SDavid Howells }; 49430062bd1SDavid Howells 49530062bd1SDavid Howells /* 49630062bd1SDavid Howells * Fetch data from a file. 49730062bd1SDavid Howells */ 498e49c7b2fSDavid Howells void yfs_fs_fetch_data(struct afs_operation *op) 49930062bd1SDavid Howells { 500e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 501e49c7b2fSDavid Howells struct afs_read *req = op->fetch.req; 50230062bd1SDavid Howells struct afs_call *call; 50330062bd1SDavid Howells __be32 *bp; 50430062bd1SDavid Howells 50530062bd1SDavid Howells _enter(",%x,{%llx:%llu},%llx,%llx", 506e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode, 50730062bd1SDavid Howells req->pos, req->len); 50830062bd1SDavid Howells 509e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchData64, 51030062bd1SDavid Howells sizeof(__be32) * 2 + 51130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 51230062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 2, 51330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 51430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) + 51530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 51630062bd1SDavid Howells if (!call) 517e49c7b2fSDavid Howells return afs_op_nomem(op); 51830062bd1SDavid Howells 51930062bd1SDavid Howells /* marshall the parameters */ 52030062bd1SDavid Howells bp = call->request; 52130062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSFETCHDATA64); 52230062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 523e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 52430062bd1SDavid Howells bp = xdr_encode_u64(bp, req->pos); 52530062bd1SDavid Howells bp = xdr_encode_u64(bp, req->len); 52630062bd1SDavid Howells yfs_check_req(call, bp); 52730062bd1SDavid Howells 528e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 529e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 53030062bd1SDavid Howells } 53130062bd1SDavid Howells 53230062bd1SDavid Howells /* 53330062bd1SDavid Howells * Deliver reply data for YFS.CreateFile or YFS.MakeDir. 53430062bd1SDavid Howells */ 53530062bd1SDavid Howells static int yfs_deliver_fs_create_vnode(struct afs_call *call) 53630062bd1SDavid Howells { 537e49c7b2fSDavid Howells struct afs_operation *op = call->op; 538e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 539e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1]; 54030062bd1SDavid Howells const __be32 *bp; 54130062bd1SDavid Howells int ret; 54230062bd1SDavid Howells 54330062bd1SDavid Howells _enter("{%u}", call->unmarshall); 54430062bd1SDavid Howells 54530062bd1SDavid Howells ret = afs_transfer_reply(call); 54630062bd1SDavid Howells if (ret < 0) 54730062bd1SDavid Howells return ret; 54830062bd1SDavid Howells 54930062bd1SDavid Howells /* unmarshall the reply once we've received all of it */ 55030062bd1SDavid Howells bp = call->buffer; 551e49c7b2fSDavid Howells xdr_decode_YFSFid(&bp, &op->file[1].fid); 552e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb); 553e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb); 554e49c7b2fSDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb); 555e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 55630062bd1SDavid Howells 55730062bd1SDavid Howells _leave(" = 0 [done]"); 55830062bd1SDavid Howells return 0; 55930062bd1SDavid Howells } 56030062bd1SDavid Howells 56130062bd1SDavid Howells /* 56230062bd1SDavid Howells * FS.CreateFile and FS.MakeDir operation type 56330062bd1SDavid Howells */ 56430062bd1SDavid Howells static const struct afs_call_type afs_RXFSCreateFile = { 56530062bd1SDavid Howells .name = "YFS.CreateFile", 56630062bd1SDavid Howells .op = yfs_FS_CreateFile, 56730062bd1SDavid Howells .deliver = yfs_deliver_fs_create_vnode, 56830062bd1SDavid Howells .destructor = afs_flat_call_destructor, 56930062bd1SDavid Howells }; 57030062bd1SDavid Howells 57130062bd1SDavid Howells /* 57230062bd1SDavid Howells * Create a file. 57330062bd1SDavid Howells */ 574e49c7b2fSDavid Howells void yfs_fs_create_file(struct afs_operation *op) 57530062bd1SDavid Howells { 576e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name; 577e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 57830062bd1SDavid Howells struct afs_call *call; 579e49c7b2fSDavid Howells size_t reqsz, rplsz; 58030062bd1SDavid Howells __be32 *bp; 58130062bd1SDavid Howells 58230062bd1SDavid Howells _enter(""); 58330062bd1SDavid Howells 58430062bd1SDavid Howells reqsz = (sizeof(__be32) + 58530062bd1SDavid Howells sizeof(__be32) + 58630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 587e49c7b2fSDavid Howells xdr_strlen(name->len) + 58830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) + 58930062bd1SDavid Howells sizeof(__be32)); 59030062bd1SDavid Howells rplsz = (sizeof(struct yfs_xdr_YFSFid) + 59130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 59230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 59330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) + 59430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 59530062bd1SDavid Howells 596e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &afs_RXFSCreateFile, reqsz, rplsz); 59730062bd1SDavid Howells if (!call) 598e49c7b2fSDavid Howells return afs_op_nomem(op); 59930062bd1SDavid Howells 60030062bd1SDavid Howells /* marshall the parameters */ 60130062bd1SDavid Howells bp = call->request; 60230062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSCREATEFILE); 60330062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 604e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 605e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name); 606e49c7b2fSDavid Howells bp = xdr_encode_YFSStoreStatus_mode(bp, op->create.mode); 6075edc22ccSMarc Dionne bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */ 60830062bd1SDavid Howells yfs_check_req(call, bp); 60930062bd1SDavid Howells 610e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name); 611e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 61230062bd1SDavid Howells } 61330062bd1SDavid Howells 61430062bd1SDavid Howells static const struct afs_call_type yfs_RXFSMakeDir = { 61530062bd1SDavid Howells .name = "YFS.MakeDir", 61630062bd1SDavid Howells .op = yfs_FS_MakeDir, 61730062bd1SDavid Howells .deliver = yfs_deliver_fs_create_vnode, 61830062bd1SDavid Howells .destructor = afs_flat_call_destructor, 61930062bd1SDavid Howells }; 62030062bd1SDavid Howells 62130062bd1SDavid Howells /* 62230062bd1SDavid Howells * Make a directory. 62330062bd1SDavid Howells */ 624e49c7b2fSDavid Howells void yfs_fs_make_dir(struct afs_operation *op) 62530062bd1SDavid Howells { 626e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name; 627e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 62830062bd1SDavid Howells struct afs_call *call; 629e49c7b2fSDavid Howells size_t reqsz, rplsz; 63030062bd1SDavid Howells __be32 *bp; 63130062bd1SDavid Howells 63230062bd1SDavid Howells _enter(""); 63330062bd1SDavid Howells 63430062bd1SDavid Howells reqsz = (sizeof(__be32) + 63530062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) + 63630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 637e49c7b2fSDavid Howells xdr_strlen(name->len) + 63830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus)); 63930062bd1SDavid Howells rplsz = (sizeof(struct yfs_xdr_YFSFid) + 64030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 64130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 64230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) + 64330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 64430062bd1SDavid Howells 645e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXFSMakeDir, reqsz, rplsz); 64630062bd1SDavid Howells if (!call) 647e49c7b2fSDavid Howells return afs_op_nomem(op); 64830062bd1SDavid Howells 64930062bd1SDavid Howells /* marshall the parameters */ 65030062bd1SDavid Howells bp = call->request; 65130062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSMAKEDIR); 65230062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 653e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 654e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name); 655e49c7b2fSDavid Howells bp = xdr_encode_YFSStoreStatus_mode(bp, op->create.mode); 65630062bd1SDavid Howells yfs_check_req(call, bp); 65730062bd1SDavid Howells 658e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name); 659e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 66030062bd1SDavid Howells } 66130062bd1SDavid Howells 66230062bd1SDavid Howells /* 66330062bd1SDavid Howells * Deliver reply data to a YFS.RemoveFile2 operation. 66430062bd1SDavid Howells */ 66530062bd1SDavid Howells static int yfs_deliver_fs_remove_file2(struct afs_call *call) 66630062bd1SDavid Howells { 667e49c7b2fSDavid Howells struct afs_operation *op = call->op; 668e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 669e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1]; 67030062bd1SDavid Howells struct afs_fid fid; 67130062bd1SDavid Howells const __be32 *bp; 67230062bd1SDavid Howells int ret; 67330062bd1SDavid Howells 67430062bd1SDavid Howells _enter("{%u}", call->unmarshall); 67530062bd1SDavid Howells 67630062bd1SDavid Howells ret = afs_transfer_reply(call); 67730062bd1SDavid Howells if (ret < 0) 67830062bd1SDavid Howells return ret; 67930062bd1SDavid Howells 68030062bd1SDavid Howells bp = call->buffer; 681e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb); 68230062bd1SDavid Howells xdr_decode_YFSFid(&bp, &fid); 683e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb); 68430062bd1SDavid Howells /* Was deleted if vnode->status.abort_code == VNOVNODE. */ 68530062bd1SDavid Howells 686e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 68730062bd1SDavid Howells return 0; 68830062bd1SDavid Howells } 68930062bd1SDavid Howells 690e49c7b2fSDavid Howells static void yfs_done_fs_remove_file2(struct afs_call *call) 691e49c7b2fSDavid Howells { 692e49c7b2fSDavid Howells if (call->error == -ECONNABORTED && 693e49c7b2fSDavid Howells call->abort_code == RX_INVALID_OPERATION) { 694e49c7b2fSDavid Howells set_bit(AFS_SERVER_FL_NO_RM2, &call->server->flags); 695e49c7b2fSDavid Howells call->op->flags |= AFS_OPERATION_DOWNGRADE; 696e49c7b2fSDavid Howells } 697e49c7b2fSDavid Howells } 698e49c7b2fSDavid Howells 69930062bd1SDavid Howells /* 70030062bd1SDavid Howells * YFS.RemoveFile2 operation type. 70130062bd1SDavid Howells */ 70230062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveFile2 = { 70330062bd1SDavid Howells .name = "YFS.RemoveFile2", 70430062bd1SDavid Howells .op = yfs_FS_RemoveFile2, 70530062bd1SDavid Howells .deliver = yfs_deliver_fs_remove_file2, 706e49c7b2fSDavid Howells .done = yfs_done_fs_remove_file2, 70730062bd1SDavid Howells .destructor = afs_flat_call_destructor, 70830062bd1SDavid Howells }; 70930062bd1SDavid Howells 71030062bd1SDavid Howells /* 71130062bd1SDavid Howells * Remove a file and retrieve new file status. 71230062bd1SDavid Howells */ 713e49c7b2fSDavid Howells void yfs_fs_remove_file2(struct afs_operation *op) 71430062bd1SDavid Howells { 715e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 716e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name; 71730062bd1SDavid Howells struct afs_call *call; 71830062bd1SDavid Howells __be32 *bp; 71930062bd1SDavid Howells 72030062bd1SDavid Howells _enter(""); 72130062bd1SDavid Howells 722e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile2, 72330062bd1SDavid Howells sizeof(__be32) + 72430062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) + 72530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 726e49c7b2fSDavid Howells xdr_strlen(name->len), 72730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 72830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 72930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 73030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 73130062bd1SDavid Howells if (!call) 732e49c7b2fSDavid Howells return afs_op_nomem(op); 73330062bd1SDavid Howells 73430062bd1SDavid Howells /* marshall the parameters */ 73530062bd1SDavid Howells bp = call->request; 73630062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEFILE2); 73730062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 738e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 739e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name); 74030062bd1SDavid Howells yfs_check_req(call, bp); 74130062bd1SDavid Howells 742e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name); 743e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 74430062bd1SDavid Howells } 74530062bd1SDavid Howells 74630062bd1SDavid Howells /* 74730062bd1SDavid Howells * Deliver reply data to a YFS.RemoveFile or YFS.RemoveDir operation. 74830062bd1SDavid Howells */ 74930062bd1SDavid Howells static int yfs_deliver_fs_remove(struct afs_call *call) 75030062bd1SDavid Howells { 751e49c7b2fSDavid Howells struct afs_operation *op = call->op; 752e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 75330062bd1SDavid Howells const __be32 *bp; 75430062bd1SDavid Howells int ret; 75530062bd1SDavid Howells 75630062bd1SDavid Howells _enter("{%u}", call->unmarshall); 75730062bd1SDavid Howells 75830062bd1SDavid Howells ret = afs_transfer_reply(call); 75930062bd1SDavid Howells if (ret < 0) 76030062bd1SDavid Howells return ret; 76130062bd1SDavid Howells 76230062bd1SDavid Howells bp = call->buffer; 763e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb); 764e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 76530062bd1SDavid Howells return 0; 76630062bd1SDavid Howells } 76730062bd1SDavid Howells 76830062bd1SDavid Howells /* 76930062bd1SDavid Howells * FS.RemoveDir and FS.RemoveFile operation types. 77030062bd1SDavid Howells */ 77130062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveFile = { 77230062bd1SDavid Howells .name = "YFS.RemoveFile", 77330062bd1SDavid Howells .op = yfs_FS_RemoveFile, 77430062bd1SDavid Howells .deliver = yfs_deliver_fs_remove, 77530062bd1SDavid Howells .destructor = afs_flat_call_destructor, 77630062bd1SDavid Howells }; 77730062bd1SDavid Howells 778e49c7b2fSDavid Howells /* 779e49c7b2fSDavid Howells * Remove a file. 780e49c7b2fSDavid Howells */ 781e49c7b2fSDavid Howells void yfs_fs_remove_file(struct afs_operation *op) 782e49c7b2fSDavid Howells { 783e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name; 784e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 785e49c7b2fSDavid Howells struct afs_call *call; 786e49c7b2fSDavid Howells __be32 *bp; 787e49c7b2fSDavid Howells 788e49c7b2fSDavid Howells _enter(""); 789e49c7b2fSDavid Howells 79020325960SDavid Howells if (!test_bit(AFS_SERVER_FL_NO_RM2, &op->server->flags)) 791e49c7b2fSDavid Howells return yfs_fs_remove_file2(op); 792e49c7b2fSDavid Howells 793e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile, 794e49c7b2fSDavid Howells sizeof(__be32) + 795e49c7b2fSDavid Howells sizeof(struct yfs_xdr_RPCFlags) + 796e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFid) + 797e49c7b2fSDavid Howells xdr_strlen(name->len), 798e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 799e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 800e49c7b2fSDavid Howells if (!call) 801e49c7b2fSDavid Howells return afs_op_nomem(op); 802e49c7b2fSDavid Howells 803e49c7b2fSDavid Howells /* marshall the parameters */ 804e49c7b2fSDavid Howells bp = call->request; 805e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEFILE); 806e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 807e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 808e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name); 809e49c7b2fSDavid Howells yfs_check_req(call, bp); 810e49c7b2fSDavid Howells 811e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name); 812e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 813e49c7b2fSDavid Howells } 814e49c7b2fSDavid Howells 81530062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveDir = { 81630062bd1SDavid Howells .name = "YFS.RemoveDir", 81730062bd1SDavid Howells .op = yfs_FS_RemoveDir, 81830062bd1SDavid Howells .deliver = yfs_deliver_fs_remove, 81930062bd1SDavid Howells .destructor = afs_flat_call_destructor, 82030062bd1SDavid Howells }; 82130062bd1SDavid Howells 82230062bd1SDavid Howells /* 823e49c7b2fSDavid Howells * Remove a directory. 82430062bd1SDavid Howells */ 825e49c7b2fSDavid Howells void yfs_fs_remove_dir(struct afs_operation *op) 82630062bd1SDavid Howells { 827e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name; 828e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 82930062bd1SDavid Howells struct afs_call *call; 83030062bd1SDavid Howells __be32 *bp; 83130062bd1SDavid Howells 83230062bd1SDavid Howells _enter(""); 83330062bd1SDavid Howells 834e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveDir, 83530062bd1SDavid Howells sizeof(__be32) + 83630062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) + 83730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 838e49c7b2fSDavid Howells xdr_strlen(name->len), 83930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 84030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 84130062bd1SDavid Howells if (!call) 842e49c7b2fSDavid Howells return afs_op_nomem(op); 84330062bd1SDavid Howells 84430062bd1SDavid Howells /* marshall the parameters */ 84530062bd1SDavid Howells bp = call->request; 846e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEDIR); 84730062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 848e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 849e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name); 85030062bd1SDavid Howells yfs_check_req(call, bp); 85130062bd1SDavid Howells 852e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name); 853e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 85430062bd1SDavid Howells } 85530062bd1SDavid Howells 85630062bd1SDavid Howells /* 85730062bd1SDavid Howells * Deliver reply data to a YFS.Link operation. 85830062bd1SDavid Howells */ 85930062bd1SDavid Howells static int yfs_deliver_fs_link(struct afs_call *call) 86030062bd1SDavid Howells { 861e49c7b2fSDavid Howells struct afs_operation *op = call->op; 862e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 863e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1]; 86430062bd1SDavid Howells const __be32 *bp; 86530062bd1SDavid Howells int ret; 86630062bd1SDavid Howells 86730062bd1SDavid Howells _enter("{%u}", call->unmarshall); 86830062bd1SDavid Howells 86930062bd1SDavid Howells ret = afs_transfer_reply(call); 87030062bd1SDavid Howells if (ret < 0) 87130062bd1SDavid Howells return ret; 87230062bd1SDavid Howells 87330062bd1SDavid Howells bp = call->buffer; 874e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb); 875e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb); 876e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 87730062bd1SDavid Howells _leave(" = 0 [done]"); 87830062bd1SDavid Howells return 0; 87930062bd1SDavid Howells } 88030062bd1SDavid Howells 88130062bd1SDavid Howells /* 88230062bd1SDavid Howells * YFS.Link operation type. 88330062bd1SDavid Howells */ 88430062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSLink = { 88530062bd1SDavid Howells .name = "YFS.Link", 88630062bd1SDavid Howells .op = yfs_FS_Link, 88730062bd1SDavid Howells .deliver = yfs_deliver_fs_link, 88830062bd1SDavid Howells .destructor = afs_flat_call_destructor, 88930062bd1SDavid Howells }; 89030062bd1SDavid Howells 89130062bd1SDavid Howells /* 89230062bd1SDavid Howells * Make a hard link. 89330062bd1SDavid Howells */ 894e49c7b2fSDavid Howells void yfs_fs_link(struct afs_operation *op) 89530062bd1SDavid Howells { 896e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name; 897e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 898e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1]; 89930062bd1SDavid Howells struct afs_call *call; 90030062bd1SDavid Howells __be32 *bp; 90130062bd1SDavid Howells 90230062bd1SDavid Howells _enter(""); 90330062bd1SDavid Howells 904e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSLink, 90530062bd1SDavid Howells sizeof(__be32) + 90630062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) + 90730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 908e49c7b2fSDavid Howells xdr_strlen(name->len) + 90930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid), 91030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 91130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 91230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 91330062bd1SDavid Howells if (!call) 914e49c7b2fSDavid Howells return afs_op_nomem(op); 91530062bd1SDavid Howells 91630062bd1SDavid Howells /* marshall the parameters */ 91730062bd1SDavid Howells bp = call->request; 91830062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSLINK); 91930062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 920e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 921e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name); 922e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 92330062bd1SDavid Howells yfs_check_req(call, bp); 92430062bd1SDavid Howells 925e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &vp->fid, name); 926e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 92730062bd1SDavid Howells } 92830062bd1SDavid Howells 92930062bd1SDavid Howells /* 93030062bd1SDavid Howells * Deliver reply data to a YFS.Symlink operation. 93130062bd1SDavid Howells */ 93230062bd1SDavid Howells static int yfs_deliver_fs_symlink(struct afs_call *call) 93330062bd1SDavid Howells { 934e49c7b2fSDavid Howells struct afs_operation *op = call->op; 935e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 936e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1]; 93730062bd1SDavid Howells const __be32 *bp; 93830062bd1SDavid Howells int ret; 93930062bd1SDavid Howells 94030062bd1SDavid Howells _enter("{%u}", call->unmarshall); 94130062bd1SDavid Howells 94230062bd1SDavid Howells ret = afs_transfer_reply(call); 94330062bd1SDavid Howells if (ret < 0) 94430062bd1SDavid Howells return ret; 94530062bd1SDavid Howells 94630062bd1SDavid Howells /* unmarshall the reply once we've received all of it */ 94730062bd1SDavid Howells bp = call->buffer; 948e49c7b2fSDavid Howells xdr_decode_YFSFid(&bp, &vp->fid); 949e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb); 950e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb); 951e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 95230062bd1SDavid Howells 95330062bd1SDavid Howells _leave(" = 0 [done]"); 95430062bd1SDavid Howells return 0; 95530062bd1SDavid Howells } 95630062bd1SDavid Howells 95730062bd1SDavid Howells /* 95830062bd1SDavid Howells * YFS.Symlink operation type 95930062bd1SDavid Howells */ 96030062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSSymlink = { 96130062bd1SDavid Howells .name = "YFS.Symlink", 96230062bd1SDavid Howells .op = yfs_FS_Symlink, 96330062bd1SDavid Howells .deliver = yfs_deliver_fs_symlink, 96430062bd1SDavid Howells .destructor = afs_flat_call_destructor, 96530062bd1SDavid Howells }; 96630062bd1SDavid Howells 96730062bd1SDavid Howells /* 96830062bd1SDavid Howells * Create a symbolic link. 96930062bd1SDavid Howells */ 970e49c7b2fSDavid Howells void yfs_fs_symlink(struct afs_operation *op) 97130062bd1SDavid Howells { 972e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name; 973e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 97430062bd1SDavid Howells struct afs_call *call; 975e49c7b2fSDavid Howells size_t contents_sz; 97630062bd1SDavid Howells __be32 *bp; 97730062bd1SDavid Howells 97830062bd1SDavid Howells _enter(""); 97930062bd1SDavid Howells 980e49c7b2fSDavid Howells contents_sz = strlen(op->create.symlink); 981e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSSymlink, 98230062bd1SDavid Howells sizeof(__be32) + 98330062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) + 98430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 985e49c7b2fSDavid Howells xdr_strlen(name->len) + 98630062bd1SDavid Howells xdr_strlen(contents_sz) + 98730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus), 98830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 98930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 99030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 99130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 99230062bd1SDavid Howells if (!call) 993e49c7b2fSDavid Howells return afs_op_nomem(op); 99430062bd1SDavid Howells 99530062bd1SDavid Howells /* marshall the parameters */ 99630062bd1SDavid Howells bp = call->request; 99730062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSYMLINK); 99830062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 999e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 1000e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name); 1001e49c7b2fSDavid Howells bp = xdr_encode_string(bp, op->create.symlink, contents_sz); 100230062bd1SDavid Howells bp = xdr_encode_YFSStoreStatus_mode(bp, S_IRWXUGO); 100330062bd1SDavid Howells yfs_check_req(call, bp); 100430062bd1SDavid Howells 1005e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name); 1006e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 100730062bd1SDavid Howells } 100830062bd1SDavid Howells 100930062bd1SDavid Howells /* 101030062bd1SDavid Howells * Deliver reply data to a YFS.Rename operation. 101130062bd1SDavid Howells */ 101230062bd1SDavid Howells static int yfs_deliver_fs_rename(struct afs_call *call) 101330062bd1SDavid Howells { 1014e49c7b2fSDavid Howells struct afs_operation *op = call->op; 1015e49c7b2fSDavid Howells struct afs_vnode_param *orig_dvp = &op->file[0]; 1016e49c7b2fSDavid Howells struct afs_vnode_param *new_dvp = &op->file[1]; 101730062bd1SDavid Howells const __be32 *bp; 101830062bd1SDavid Howells int ret; 101930062bd1SDavid Howells 102030062bd1SDavid Howells _enter("{%u}", call->unmarshall); 102130062bd1SDavid Howells 102230062bd1SDavid Howells ret = afs_transfer_reply(call); 102330062bd1SDavid Howells if (ret < 0) 102430062bd1SDavid Howells return ret; 102530062bd1SDavid Howells 102630062bd1SDavid Howells bp = call->buffer; 102738355eecSDavid Howells /* If the two dirs are the same, we have two copies of the same status 102838355eecSDavid Howells * report, so we just decode it twice. 102938355eecSDavid Howells */ 1030e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &orig_dvp->scb); 1031e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &new_dvp->scb); 1032e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 103330062bd1SDavid Howells _leave(" = 0 [done]"); 103430062bd1SDavid Howells return 0; 103530062bd1SDavid Howells } 103630062bd1SDavid Howells 103730062bd1SDavid Howells /* 103830062bd1SDavid Howells * YFS.Rename operation type 103930062bd1SDavid Howells */ 104030062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRename = { 104130062bd1SDavid Howells .name = "FS.Rename", 104230062bd1SDavid Howells .op = yfs_FS_Rename, 104330062bd1SDavid Howells .deliver = yfs_deliver_fs_rename, 104430062bd1SDavid Howells .destructor = afs_flat_call_destructor, 104530062bd1SDavid Howells }; 104630062bd1SDavid Howells 104730062bd1SDavid Howells /* 104830062bd1SDavid Howells * Rename a file or directory. 104930062bd1SDavid Howells */ 1050e49c7b2fSDavid Howells void yfs_fs_rename(struct afs_operation *op) 105130062bd1SDavid Howells { 1052e49c7b2fSDavid Howells struct afs_vnode_param *orig_dvp = &op->file[0]; 1053e49c7b2fSDavid Howells struct afs_vnode_param *new_dvp = &op->file[1]; 1054e49c7b2fSDavid Howells const struct qstr *orig_name = &op->dentry->d_name; 1055e49c7b2fSDavid Howells const struct qstr *new_name = &op->dentry_2->d_name; 105630062bd1SDavid Howells struct afs_call *call; 105730062bd1SDavid Howells __be32 *bp; 105830062bd1SDavid Howells 105930062bd1SDavid Howells _enter(""); 106030062bd1SDavid Howells 1061e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename, 106230062bd1SDavid Howells sizeof(__be32) + 106330062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) + 106430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 1065e49c7b2fSDavid Howells xdr_strlen(orig_name->len) + 106630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 1067e49c7b2fSDavid Howells xdr_strlen(new_name->len), 106830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 106930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 107030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 107130062bd1SDavid Howells if (!call) 1072e49c7b2fSDavid Howells return afs_op_nomem(op); 107330062bd1SDavid Howells 107430062bd1SDavid Howells /* marshall the parameters */ 107530062bd1SDavid Howells bp = call->request; 107630062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSRENAME); 107730062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1078e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &orig_dvp->fid); 1079e49c7b2fSDavid Howells bp = xdr_encode_name(bp, orig_name); 1080e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &new_dvp->fid); 1081e49c7b2fSDavid Howells bp = xdr_encode_name(bp, new_name); 108230062bd1SDavid Howells yfs_check_req(call, bp); 108330062bd1SDavid Howells 1084e49c7b2fSDavid Howells trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name); 1085e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 108630062bd1SDavid Howells } 108730062bd1SDavid Howells 108830062bd1SDavid Howells /* 108930062bd1SDavid Howells * YFS.StoreData64 operation type. 109030062bd1SDavid Howells */ 109130062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreData64 = { 109230062bd1SDavid Howells .name = "YFS.StoreData64", 109330062bd1SDavid Howells .op = yfs_FS_StoreData64, 1094a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync, 109530062bd1SDavid Howells .destructor = afs_flat_call_destructor, 109630062bd1SDavid Howells }; 109730062bd1SDavid Howells 109830062bd1SDavid Howells /* 109930062bd1SDavid Howells * Store a set of pages to a large file. 110030062bd1SDavid Howells */ 1101e49c7b2fSDavid Howells void yfs_fs_store_data(struct afs_operation *op) 110230062bd1SDavid Howells { 1103e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 110430062bd1SDavid Howells struct afs_call *call; 110530062bd1SDavid Howells loff_t size, pos, i_size; 110630062bd1SDavid Howells __be32 *bp; 110730062bd1SDavid Howells 110830062bd1SDavid Howells _enter(",%x,{%llx:%llu},,", 1109e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode); 111030062bd1SDavid Howells 1111e49c7b2fSDavid Howells size = (loff_t)op->store.last_to - (loff_t)op->store.first_offset; 1112e49c7b2fSDavid Howells if (op->store.first != op->store.last) 1113e49c7b2fSDavid Howells size += (loff_t)(op->store.last - op->store.first) << PAGE_SHIFT; 1114e49c7b2fSDavid Howells pos = (loff_t)op->store.first << PAGE_SHIFT; 1115e49c7b2fSDavid Howells pos += op->store.first_offset; 111630062bd1SDavid Howells 1117e49c7b2fSDavid Howells i_size = i_size_read(&vp->vnode->vfs_inode); 111830062bd1SDavid Howells if (pos + size > i_size) 111930062bd1SDavid Howells i_size = size + pos; 112030062bd1SDavid Howells 112130062bd1SDavid Howells _debug("size %llx, at %llx, i_size %llx", 112230062bd1SDavid Howells (unsigned long long)size, (unsigned long long)pos, 112330062bd1SDavid Howells (unsigned long long)i_size); 112430062bd1SDavid Howells 1125e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64, 112630062bd1SDavid Howells sizeof(__be32) + 112730062bd1SDavid Howells sizeof(__be32) + 112830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 112930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) + 113030062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 3, 113130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 113230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 113330062bd1SDavid Howells if (!call) 1134e49c7b2fSDavid Howells return afs_op_nomem(op); 113530062bd1SDavid Howells 1136e49c7b2fSDavid Howells call->key = op->key; 113730062bd1SDavid Howells call->send_pages = true; 113830062bd1SDavid Howells 113930062bd1SDavid Howells /* marshall the parameters */ 114030062bd1SDavid Howells bp = call->request; 114130062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREDATA64); 114230062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1143e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 1144e49c7b2fSDavid Howells bp = xdr_encode_YFSStoreStatus_mtime(bp, &op->mtime); 114530062bd1SDavid Howells bp = xdr_encode_u64(bp, pos); 114630062bd1SDavid Howells bp = xdr_encode_u64(bp, size); 114730062bd1SDavid Howells bp = xdr_encode_u64(bp, i_size); 114830062bd1SDavid Howells yfs_check_req(call, bp); 114930062bd1SDavid Howells 1150e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1151e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 115230062bd1SDavid Howells } 115330062bd1SDavid Howells 115430062bd1SDavid Howells /* 115530062bd1SDavid Howells * YFS.StoreStatus operation type 115630062bd1SDavid Howells */ 115730062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreStatus = { 115830062bd1SDavid Howells .name = "YFS.StoreStatus", 115930062bd1SDavid Howells .op = yfs_FS_StoreStatus, 1160a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync, 116130062bd1SDavid Howells .destructor = afs_flat_call_destructor, 116230062bd1SDavid Howells }; 116330062bd1SDavid Howells 116430062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = { 116530062bd1SDavid Howells .name = "YFS.StoreData64", 116630062bd1SDavid Howells .op = yfs_FS_StoreData64, 1167a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync, 116830062bd1SDavid Howells .destructor = afs_flat_call_destructor, 116930062bd1SDavid Howells }; 117030062bd1SDavid Howells 117130062bd1SDavid Howells /* 117230062bd1SDavid Howells * Set the attributes on a file, using YFS.StoreData64 rather than 117330062bd1SDavid Howells * YFS.StoreStatus so as to alter the file size also. 117430062bd1SDavid Howells */ 1175e49c7b2fSDavid Howells static void yfs_fs_setattr_size(struct afs_operation *op) 117630062bd1SDavid Howells { 1177e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 117830062bd1SDavid Howells struct afs_call *call; 1179e49c7b2fSDavid Howells struct iattr *attr = op->setattr.attr; 118030062bd1SDavid Howells __be32 *bp; 118130062bd1SDavid Howells 118230062bd1SDavid Howells _enter(",%x,{%llx:%llu},,", 1183e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode); 118430062bd1SDavid Howells 1185e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64_as_Status, 118630062bd1SDavid Howells sizeof(__be32) * 2 + 118730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 118830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) + 118930062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 3, 119030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 119130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 119230062bd1SDavid Howells if (!call) 1193e49c7b2fSDavid Howells return afs_op_nomem(op); 119430062bd1SDavid Howells 119530062bd1SDavid Howells /* marshall the parameters */ 119630062bd1SDavid Howells bp = call->request; 119730062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREDATA64); 119830062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1199e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 120030062bd1SDavid Howells bp = xdr_encode_YFS_StoreStatus(bp, attr); 12018c7ae38dSDavid Howells bp = xdr_encode_u64(bp, attr->ia_size); /* position of start of write */ 120230062bd1SDavid Howells bp = xdr_encode_u64(bp, 0); /* size of write */ 120330062bd1SDavid Howells bp = xdr_encode_u64(bp, attr->ia_size); /* new file length */ 120430062bd1SDavid Howells yfs_check_req(call, bp); 120530062bd1SDavid Howells 1206e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1207e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 120830062bd1SDavid Howells } 120930062bd1SDavid Howells 121030062bd1SDavid Howells /* 121130062bd1SDavid Howells * Set the attributes on a file, using YFS.StoreData64 if there's a change in 121230062bd1SDavid Howells * file size, and YFS.StoreStatus otherwise. 121330062bd1SDavid Howells */ 1214e49c7b2fSDavid Howells void yfs_fs_setattr(struct afs_operation *op) 121530062bd1SDavid Howells { 1216e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 121730062bd1SDavid Howells struct afs_call *call; 1218e49c7b2fSDavid Howells struct iattr *attr = op->setattr.attr; 121930062bd1SDavid Howells __be32 *bp; 122030062bd1SDavid Howells 122130062bd1SDavid Howells if (attr->ia_valid & ATTR_SIZE) 1222e49c7b2fSDavid Howells return yfs_fs_setattr_size(op); 122330062bd1SDavid Howells 122430062bd1SDavid Howells _enter(",%x,{%llx:%llu},,", 1225e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode); 122630062bd1SDavid Howells 1227e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreStatus, 122830062bd1SDavid Howells sizeof(__be32) * 2 + 122930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 123030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus), 123130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 123230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 123330062bd1SDavid Howells if (!call) 1234e49c7b2fSDavid Howells return afs_op_nomem(op); 123530062bd1SDavid Howells 123630062bd1SDavid Howells /* marshall the parameters */ 123730062bd1SDavid Howells bp = call->request; 123830062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTORESTATUS); 123930062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1240e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 124130062bd1SDavid Howells bp = xdr_encode_YFS_StoreStatus(bp, attr); 124230062bd1SDavid Howells yfs_check_req(call, bp); 124330062bd1SDavid Howells 1244e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1245e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 124630062bd1SDavid Howells } 124730062bd1SDavid Howells 124830062bd1SDavid Howells /* 124930062bd1SDavid Howells * Deliver reply data to a YFS.GetVolumeStatus operation. 125030062bd1SDavid Howells */ 125130062bd1SDavid Howells static int yfs_deliver_fs_get_volume_status(struct afs_call *call) 125230062bd1SDavid Howells { 1253e49c7b2fSDavid Howells struct afs_operation *op = call->op; 125430062bd1SDavid Howells const __be32 *bp; 125530062bd1SDavid Howells char *p; 125630062bd1SDavid Howells u32 size; 125730062bd1SDavid Howells int ret; 125830062bd1SDavid Howells 125930062bd1SDavid Howells _enter("{%u}", call->unmarshall); 126030062bd1SDavid Howells 126130062bd1SDavid Howells switch (call->unmarshall) { 126230062bd1SDavid Howells case 0: 126330062bd1SDavid Howells call->unmarshall++; 126430062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus)); 126535a3a90cSGustavo A. R. Silva /* Fall through */ 126630062bd1SDavid Howells 126735a3a90cSGustavo A. R. Silva /* extract the returned status record */ 126830062bd1SDavid Howells case 1: 126930062bd1SDavid Howells _debug("extract status"); 127030062bd1SDavid Howells ret = afs_extract_data(call, true); 127130062bd1SDavid Howells if (ret < 0) 127230062bd1SDavid Howells return ret; 127330062bd1SDavid Howells 127430062bd1SDavid Howells bp = call->buffer; 1275e49c7b2fSDavid Howells xdr_decode_YFSFetchVolumeStatus(&bp, &op->volstatus.vs); 127630062bd1SDavid Howells call->unmarshall++; 127730062bd1SDavid Howells afs_extract_to_tmp(call); 127835a3a90cSGustavo A. R. Silva /* Fall through */ 127930062bd1SDavid Howells 128035a3a90cSGustavo A. R. Silva /* extract the volume name length */ 128130062bd1SDavid Howells case 2: 128230062bd1SDavid Howells ret = afs_extract_data(call, true); 128330062bd1SDavid Howells if (ret < 0) 128430062bd1SDavid Howells return ret; 128530062bd1SDavid Howells 128630062bd1SDavid Howells call->count = ntohl(call->tmp); 128730062bd1SDavid Howells _debug("volname length: %u", call->count); 128830062bd1SDavid Howells if (call->count >= AFSNAMEMAX) 12897126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_volname_len); 129030062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1291ffba718eSDavid Howells afs_extract_to_buf(call, size); 129230062bd1SDavid Howells call->unmarshall++; 129335a3a90cSGustavo A. R. Silva /* Fall through */ 129430062bd1SDavid Howells 129535a3a90cSGustavo A. R. Silva /* extract the volume name */ 129630062bd1SDavid Howells case 3: 129730062bd1SDavid Howells _debug("extract volname"); 129830062bd1SDavid Howells ret = afs_extract_data(call, true); 129930062bd1SDavid Howells if (ret < 0) 130030062bd1SDavid Howells return ret; 130130062bd1SDavid Howells 1302ffba718eSDavid Howells p = call->buffer; 130330062bd1SDavid Howells p[call->count] = 0; 130430062bd1SDavid Howells _debug("volname '%s'", p); 130530062bd1SDavid Howells afs_extract_to_tmp(call); 130630062bd1SDavid Howells call->unmarshall++; 130735a3a90cSGustavo A. R. Silva /* Fall through */ 130830062bd1SDavid Howells 130935a3a90cSGustavo A. R. Silva /* extract the offline message length */ 131030062bd1SDavid Howells case 4: 131130062bd1SDavid Howells ret = afs_extract_data(call, true); 131230062bd1SDavid Howells if (ret < 0) 131330062bd1SDavid Howells return ret; 131430062bd1SDavid Howells 131530062bd1SDavid Howells call->count = ntohl(call->tmp); 131630062bd1SDavid Howells _debug("offline msg length: %u", call->count); 131730062bd1SDavid Howells if (call->count >= AFSNAMEMAX) 13187126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_offline_msg_len); 131930062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1320ffba718eSDavid Howells afs_extract_to_buf(call, size); 132130062bd1SDavid Howells call->unmarshall++; 132235a3a90cSGustavo A. R. Silva /* Fall through */ 132330062bd1SDavid Howells 132435a3a90cSGustavo A. R. Silva /* extract the offline message */ 132530062bd1SDavid Howells case 5: 132630062bd1SDavid Howells _debug("extract offline"); 132730062bd1SDavid Howells ret = afs_extract_data(call, true); 132830062bd1SDavid Howells if (ret < 0) 132930062bd1SDavid Howells return ret; 133030062bd1SDavid Howells 1331ffba718eSDavid Howells p = call->buffer; 133230062bd1SDavid Howells p[call->count] = 0; 133330062bd1SDavid Howells _debug("offline '%s'", p); 133430062bd1SDavid Howells 133530062bd1SDavid Howells afs_extract_to_tmp(call); 133630062bd1SDavid Howells call->unmarshall++; 133735a3a90cSGustavo A. R. Silva /* Fall through */ 133830062bd1SDavid Howells 133935a3a90cSGustavo A. R. Silva /* extract the message of the day length */ 134030062bd1SDavid Howells case 6: 134130062bd1SDavid Howells ret = afs_extract_data(call, true); 134230062bd1SDavid Howells if (ret < 0) 134330062bd1SDavid Howells return ret; 134430062bd1SDavid Howells 134530062bd1SDavid Howells call->count = ntohl(call->tmp); 134630062bd1SDavid Howells _debug("motd length: %u", call->count); 134730062bd1SDavid Howells if (call->count >= AFSNAMEMAX) 13487126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_motd_len); 134930062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */ 1350ffba718eSDavid Howells afs_extract_to_buf(call, size); 135130062bd1SDavid Howells call->unmarshall++; 135235a3a90cSGustavo A. R. Silva /* Fall through */ 135330062bd1SDavid Howells 135435a3a90cSGustavo A. R. Silva /* extract the message of the day */ 135530062bd1SDavid Howells case 7: 135630062bd1SDavid Howells _debug("extract motd"); 135730062bd1SDavid Howells ret = afs_extract_data(call, false); 135830062bd1SDavid Howells if (ret < 0) 135930062bd1SDavid Howells return ret; 136030062bd1SDavid Howells 1361ffba718eSDavid Howells p = call->buffer; 136230062bd1SDavid Howells p[call->count] = 0; 136330062bd1SDavid Howells _debug("motd '%s'", p); 136430062bd1SDavid Howells 136530062bd1SDavid Howells call->unmarshall++; 1366e690c9e3SGustavo A. R. Silva /* Fall through */ 136735a3a90cSGustavo A. R. Silva 136830062bd1SDavid Howells case 8: 136930062bd1SDavid Howells break; 137030062bd1SDavid Howells } 137130062bd1SDavid Howells 137230062bd1SDavid Howells _leave(" = 0 [done]"); 137330062bd1SDavid Howells return 0; 137430062bd1SDavid Howells } 137530062bd1SDavid Howells 137630062bd1SDavid Howells /* 137730062bd1SDavid Howells * YFS.GetVolumeStatus operation type 137830062bd1SDavid Howells */ 137930062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSGetVolumeStatus = { 138030062bd1SDavid Howells .name = "YFS.GetVolumeStatus", 138130062bd1SDavid Howells .op = yfs_FS_GetVolumeStatus, 138230062bd1SDavid Howells .deliver = yfs_deliver_fs_get_volume_status, 1383ffba718eSDavid Howells .destructor = afs_flat_call_destructor, 138430062bd1SDavid Howells }; 138530062bd1SDavid Howells 138630062bd1SDavid Howells /* 138730062bd1SDavid Howells * fetch the status of a volume 138830062bd1SDavid Howells */ 1389e49c7b2fSDavid Howells void yfs_fs_get_volume_status(struct afs_operation *op) 139030062bd1SDavid Howells { 1391e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 139230062bd1SDavid Howells struct afs_call *call; 139330062bd1SDavid Howells __be32 *bp; 139430062bd1SDavid Howells 139530062bd1SDavid Howells _enter(""); 139630062bd1SDavid Howells 1397e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSGetVolumeStatus, 139830062bd1SDavid Howells sizeof(__be32) * 2 + 139930062bd1SDavid Howells sizeof(struct yfs_xdr_u64), 1400ffba718eSDavid Howells max_t(size_t, 140130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchVolumeStatus) + 1402ffba718eSDavid Howells sizeof(__be32), 1403ffba718eSDavid Howells AFSOPAQUEMAX + 1)); 1404ffba718eSDavid Howells if (!call) 1405e49c7b2fSDavid Howells return afs_op_nomem(op); 140630062bd1SDavid Howells 140730062bd1SDavid Howells /* marshall the parameters */ 140830062bd1SDavid Howells bp = call->request; 140930062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSGETVOLUMESTATUS); 141030062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1411e49c7b2fSDavid Howells bp = xdr_encode_u64(bp, vp->fid.vid); 141230062bd1SDavid Howells yfs_check_req(call, bp); 141330062bd1SDavid Howells 1414e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1415e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 141630062bd1SDavid Howells } 141730062bd1SDavid Howells 141830062bd1SDavid Howells /* 141930062bd1SDavid Howells * YFS.SetLock operation type 142030062bd1SDavid Howells */ 142130062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSSetLock = { 142230062bd1SDavid Howells .name = "YFS.SetLock", 142330062bd1SDavid Howells .op = yfs_FS_SetLock, 1424f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync, 1425a690f60aSDavid Howells .done = afs_lock_op_done, 142630062bd1SDavid Howells .destructor = afs_flat_call_destructor, 142730062bd1SDavid Howells }; 142830062bd1SDavid Howells 142930062bd1SDavid Howells /* 143030062bd1SDavid Howells * YFS.ExtendLock operation type 143130062bd1SDavid Howells */ 143230062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSExtendLock = { 143330062bd1SDavid Howells .name = "YFS.ExtendLock", 143430062bd1SDavid Howells .op = yfs_FS_ExtendLock, 1435f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync, 1436a690f60aSDavid Howells .done = afs_lock_op_done, 143730062bd1SDavid Howells .destructor = afs_flat_call_destructor, 143830062bd1SDavid Howells }; 143930062bd1SDavid Howells 144030062bd1SDavid Howells /* 144130062bd1SDavid Howells * YFS.ReleaseLock operation type 144230062bd1SDavid Howells */ 144330062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSReleaseLock = { 144430062bd1SDavid Howells .name = "YFS.ReleaseLock", 144530062bd1SDavid Howells .op = yfs_FS_ReleaseLock, 1446f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync, 144730062bd1SDavid Howells .destructor = afs_flat_call_destructor, 144830062bd1SDavid Howells }; 144930062bd1SDavid Howells 145030062bd1SDavid Howells /* 145130062bd1SDavid Howells * Set a lock on a file 145230062bd1SDavid Howells */ 1453e49c7b2fSDavid Howells void yfs_fs_set_lock(struct afs_operation *op) 145430062bd1SDavid Howells { 1455e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 145630062bd1SDavid Howells struct afs_call *call; 145730062bd1SDavid Howells __be32 *bp; 145830062bd1SDavid Howells 145930062bd1SDavid Howells _enter(""); 146030062bd1SDavid Howells 1461e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSSetLock, 146230062bd1SDavid Howells sizeof(__be32) * 2 + 146330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 146430062bd1SDavid Howells sizeof(__be32), 146530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 146630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 146730062bd1SDavid Howells if (!call) 1468e49c7b2fSDavid Howells return afs_op_nomem(op); 146930062bd1SDavid Howells 147030062bd1SDavid Howells /* marshall the parameters */ 147130062bd1SDavid Howells bp = call->request; 147230062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSETLOCK); 147330062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1474e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 1475e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, op->lock.type); 147630062bd1SDavid Howells yfs_check_req(call, bp); 147730062bd1SDavid Howells 1478e49c7b2fSDavid Howells trace_afs_make_fs_calli(call, &vp->fid, op->lock.type); 1479e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 148030062bd1SDavid Howells } 148130062bd1SDavid Howells 148230062bd1SDavid Howells /* 148330062bd1SDavid Howells * extend a lock on a file 148430062bd1SDavid Howells */ 1485e49c7b2fSDavid Howells void yfs_fs_extend_lock(struct afs_operation *op) 148630062bd1SDavid Howells { 1487e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 148830062bd1SDavid Howells struct afs_call *call; 148930062bd1SDavid Howells __be32 *bp; 149030062bd1SDavid Howells 149130062bd1SDavid Howells _enter(""); 149230062bd1SDavid Howells 1493e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSExtendLock, 149430062bd1SDavid Howells sizeof(__be32) * 2 + 149530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid), 149630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 149730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 149830062bd1SDavid Howells if (!call) 1499e49c7b2fSDavid Howells return afs_op_nomem(op); 150030062bd1SDavid Howells 150130062bd1SDavid Howells /* marshall the parameters */ 150230062bd1SDavid Howells bp = call->request; 150330062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSEXTENDLOCK); 150430062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1505e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 150630062bd1SDavid Howells yfs_check_req(call, bp); 150730062bd1SDavid Howells 1508e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1509e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 151030062bd1SDavid Howells } 151130062bd1SDavid Howells 151230062bd1SDavid Howells /* 151330062bd1SDavid Howells * release a lock on a file 151430062bd1SDavid Howells */ 1515e49c7b2fSDavid Howells void yfs_fs_release_lock(struct afs_operation *op) 151630062bd1SDavid Howells { 1517e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 151830062bd1SDavid Howells struct afs_call *call; 151930062bd1SDavid Howells __be32 *bp; 152030062bd1SDavid Howells 152130062bd1SDavid Howells _enter(""); 152230062bd1SDavid Howells 1523e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSReleaseLock, 152430062bd1SDavid Howells sizeof(__be32) * 2 + 152530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid), 152630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 152730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 152830062bd1SDavid Howells if (!call) 1529e49c7b2fSDavid Howells return afs_op_nomem(op); 153030062bd1SDavid Howells 153130062bd1SDavid Howells /* marshall the parameters */ 153230062bd1SDavid Howells bp = call->request; 153330062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSRELEASELOCK); 153430062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1535e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 153630062bd1SDavid Howells yfs_check_req(call, bp); 153730062bd1SDavid Howells 1538e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1539e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 154030062bd1SDavid Howells } 154130062bd1SDavid Howells 154230062bd1SDavid Howells /* 1543*9bd87ec6SDavid Howells * Deliver a reply to YFS.FetchStatus 1544*9bd87ec6SDavid Howells */ 1545*9bd87ec6SDavid Howells static int yfs_deliver_fs_fetch_status(struct afs_call *call) 1546*9bd87ec6SDavid Howells { 1547*9bd87ec6SDavid Howells struct afs_operation *op = call->op; 1548*9bd87ec6SDavid Howells struct afs_vnode_param *vp = &op->file[op->fetch_status.which]; 1549*9bd87ec6SDavid Howells const __be32 *bp; 1550*9bd87ec6SDavid Howells int ret; 1551*9bd87ec6SDavid Howells 1552*9bd87ec6SDavid Howells ret = afs_transfer_reply(call); 1553*9bd87ec6SDavid Howells if (ret < 0) 1554*9bd87ec6SDavid Howells return ret; 1555*9bd87ec6SDavid Howells 1556*9bd87ec6SDavid Howells /* unmarshall the reply once we've received all of it */ 1557*9bd87ec6SDavid Howells bp = call->buffer; 1558*9bd87ec6SDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb); 1559*9bd87ec6SDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb); 1560*9bd87ec6SDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 1561*9bd87ec6SDavid Howells 1562*9bd87ec6SDavid Howells _leave(" = 0 [done]"); 1563*9bd87ec6SDavid Howells return 0; 1564*9bd87ec6SDavid Howells } 1565*9bd87ec6SDavid Howells 1566*9bd87ec6SDavid Howells /* 156730062bd1SDavid Howells * YFS.FetchStatus operation type 156830062bd1SDavid Howells */ 156930062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSFetchStatus = { 157030062bd1SDavid Howells .name = "YFS.FetchStatus", 157130062bd1SDavid Howells .op = yfs_FS_FetchStatus, 1572*9bd87ec6SDavid Howells .deliver = yfs_deliver_fs_fetch_status, 157330062bd1SDavid Howells .destructor = afs_flat_call_destructor, 157430062bd1SDavid Howells }; 157530062bd1SDavid Howells 157630062bd1SDavid Howells /* 157730062bd1SDavid Howells * Fetch the status information for a fid without needing a vnode handle. 157830062bd1SDavid Howells */ 1579e49c7b2fSDavid Howells void yfs_fs_fetch_status(struct afs_operation *op) 158030062bd1SDavid Howells { 1581*9bd87ec6SDavid Howells struct afs_vnode_param *vp = &op->file[op->fetch_status.which]; 158230062bd1SDavid Howells struct afs_call *call; 158330062bd1SDavid Howells __be32 *bp; 158430062bd1SDavid Howells 158530062bd1SDavid Howells _enter(",%x,{%llx:%llu},,", 1586e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode); 158730062bd1SDavid Howells 1588e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchStatus, 158930062bd1SDavid Howells sizeof(__be32) * 2 + 159030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid), 159130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 159230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) + 159330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 1594e49c7b2fSDavid Howells if (!call) 1595e49c7b2fSDavid Howells return afs_op_nomem(op); 159630062bd1SDavid Howells 159730062bd1SDavid Howells /* marshall the parameters */ 159830062bd1SDavid Howells bp = call->request; 159930062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSFETCHSTATUS); 160030062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1601e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 160230062bd1SDavid Howells yfs_check_req(call, bp); 160330062bd1SDavid Howells 1604e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1605e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 160630062bd1SDavid Howells } 160730062bd1SDavid Howells 160830062bd1SDavid Howells /* 160930062bd1SDavid Howells * Deliver reply data to an YFS.InlineBulkStatus call 161030062bd1SDavid Howells */ 161130062bd1SDavid Howells static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) 161230062bd1SDavid Howells { 1613e49c7b2fSDavid Howells struct afs_operation *op = call->op; 161487182759SDavid Howells struct afs_status_cb *scb; 161530062bd1SDavid Howells const __be32 *bp; 161630062bd1SDavid Howells u32 tmp; 161730062bd1SDavid Howells int ret; 161830062bd1SDavid Howells 161930062bd1SDavid Howells _enter("{%u}", call->unmarshall); 162030062bd1SDavid Howells 162130062bd1SDavid Howells switch (call->unmarshall) { 162230062bd1SDavid Howells case 0: 162330062bd1SDavid Howells afs_extract_to_tmp(call); 162430062bd1SDavid Howells call->unmarshall++; 162535a3a90cSGustavo A. R. Silva /* Fall through */ 162630062bd1SDavid Howells 162730062bd1SDavid Howells /* Extract the file status count and array in two steps */ 162830062bd1SDavid Howells case 1: 162930062bd1SDavid Howells _debug("extract status count"); 163030062bd1SDavid Howells ret = afs_extract_data(call, true); 163130062bd1SDavid Howells if (ret < 0) 163230062bd1SDavid Howells return ret; 163330062bd1SDavid Howells 163430062bd1SDavid Howells tmp = ntohl(call->tmp); 1635e49c7b2fSDavid Howells _debug("status count: %u/%u", tmp, op->nr_files); 1636e49c7b2fSDavid Howells if (tmp != op->nr_files) 16377126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_ibulkst_count); 163830062bd1SDavid Howells 163930062bd1SDavid Howells call->count = 0; 164030062bd1SDavid Howells call->unmarshall++; 164130062bd1SDavid Howells more_counts: 164230062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus)); 1643e690c9e3SGustavo A. R. Silva /* Fall through */ 164435a3a90cSGustavo A. R. Silva 164530062bd1SDavid Howells case 2: 164630062bd1SDavid Howells _debug("extract status array %u", call->count); 164730062bd1SDavid Howells ret = afs_extract_data(call, true); 164830062bd1SDavid Howells if (ret < 0) 164930062bd1SDavid Howells return ret; 165030062bd1SDavid Howells 1651e49c7b2fSDavid Howells switch (call->count) { 1652e49c7b2fSDavid Howells case 0: 1653e49c7b2fSDavid Howells scb = &op->file[0].scb; 1654e49c7b2fSDavid Howells break; 1655e49c7b2fSDavid Howells case 1: 1656e49c7b2fSDavid Howells scb = &op->file[1].scb; 1657e49c7b2fSDavid Howells break; 1658e49c7b2fSDavid Howells default: 1659e49c7b2fSDavid Howells scb = &op->more_files[call->count - 2].scb; 1660e49c7b2fSDavid Howells break; 1661e49c7b2fSDavid Howells } 1662e49c7b2fSDavid Howells 166330062bd1SDavid Howells bp = call->buffer; 166438355eecSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, scb); 166530062bd1SDavid Howells 166630062bd1SDavid Howells call->count++; 1667e49c7b2fSDavid Howells if (call->count < op->nr_files) 166830062bd1SDavid Howells goto more_counts; 166930062bd1SDavid Howells 167030062bd1SDavid Howells call->count = 0; 167130062bd1SDavid Howells call->unmarshall++; 167230062bd1SDavid Howells afs_extract_to_tmp(call); 167335a3a90cSGustavo A. R. Silva /* Fall through */ 167430062bd1SDavid Howells 167530062bd1SDavid Howells /* Extract the callback count and array in two steps */ 167630062bd1SDavid Howells case 3: 167730062bd1SDavid Howells _debug("extract CB count"); 167830062bd1SDavid Howells ret = afs_extract_data(call, true); 167930062bd1SDavid Howells if (ret < 0) 168030062bd1SDavid Howells return ret; 168130062bd1SDavid Howells 168230062bd1SDavid Howells tmp = ntohl(call->tmp); 168330062bd1SDavid Howells _debug("CB count: %u", tmp); 1684e49c7b2fSDavid Howells if (tmp != op->nr_files) 16857126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_ibulkst_cb_count); 168630062bd1SDavid Howells call->count = 0; 168730062bd1SDavid Howells call->unmarshall++; 168830062bd1SDavid Howells more_cbs: 168930062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack)); 1690e690c9e3SGustavo A. R. Silva /* Fall through */ 169135a3a90cSGustavo A. R. Silva 169230062bd1SDavid Howells case 4: 169330062bd1SDavid Howells _debug("extract CB array"); 169430062bd1SDavid Howells ret = afs_extract_data(call, true); 169530062bd1SDavid Howells if (ret < 0) 169630062bd1SDavid Howells return ret; 169730062bd1SDavid Howells 169830062bd1SDavid Howells _debug("unmarshall CB array"); 1699e49c7b2fSDavid Howells switch (call->count) { 1700e49c7b2fSDavid Howells case 0: 1701e49c7b2fSDavid Howells scb = &op->file[0].scb; 1702e49c7b2fSDavid Howells break; 1703e49c7b2fSDavid Howells case 1: 1704e49c7b2fSDavid Howells scb = &op->file[1].scb; 1705e49c7b2fSDavid Howells break; 1706e49c7b2fSDavid Howells default: 1707e49c7b2fSDavid Howells scb = &op->more_files[call->count - 2].scb; 1708e49c7b2fSDavid Howells break; 1709e49c7b2fSDavid Howells } 1710e49c7b2fSDavid Howells 171130062bd1SDavid Howells bp = call->buffer; 1712a58823acSDavid Howells xdr_decode_YFSCallBack(&bp, call, scb); 171330062bd1SDavid Howells call->count++; 1714e49c7b2fSDavid Howells if (call->count < op->nr_files) 171530062bd1SDavid Howells goto more_cbs; 171630062bd1SDavid Howells 171730062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync)); 171830062bd1SDavid Howells call->unmarshall++; 1719e690c9e3SGustavo A. R. Silva /* Fall through */ 172035a3a90cSGustavo A. R. Silva 172130062bd1SDavid Howells case 5: 172230062bd1SDavid Howells ret = afs_extract_data(call, false); 172330062bd1SDavid Howells if (ret < 0) 172430062bd1SDavid Howells return ret; 172530062bd1SDavid Howells 172630062bd1SDavid Howells bp = call->buffer; 1727e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 172830062bd1SDavid Howells 172930062bd1SDavid Howells call->unmarshall++; 1730e690c9e3SGustavo A. R. Silva /* Fall through */ 173135a3a90cSGustavo A. R. Silva 173230062bd1SDavid Howells case 6: 173330062bd1SDavid Howells break; 173430062bd1SDavid Howells } 173530062bd1SDavid Howells 173630062bd1SDavid Howells _leave(" = 0 [done]"); 173730062bd1SDavid Howells return 0; 173830062bd1SDavid Howells } 173930062bd1SDavid Howells 174030062bd1SDavid Howells /* 174130062bd1SDavid Howells * FS.InlineBulkStatus operation type 174230062bd1SDavid Howells */ 174330062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSInlineBulkStatus = { 174430062bd1SDavid Howells .name = "YFS.InlineBulkStatus", 174530062bd1SDavid Howells .op = yfs_FS_InlineBulkStatus, 174630062bd1SDavid Howells .deliver = yfs_deliver_fs_inline_bulk_status, 174730062bd1SDavid Howells .destructor = afs_flat_call_destructor, 174830062bd1SDavid Howells }; 174930062bd1SDavid Howells 175030062bd1SDavid Howells /* 175130062bd1SDavid Howells * Fetch the status information for up to 1024 files 175230062bd1SDavid Howells */ 1753e49c7b2fSDavid Howells void yfs_fs_inline_bulk_status(struct afs_operation *op) 175430062bd1SDavid Howells { 1755e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0]; 1756e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1]; 175730062bd1SDavid Howells struct afs_call *call; 175830062bd1SDavid Howells __be32 *bp; 175930062bd1SDavid Howells int i; 176030062bd1SDavid Howells 176130062bd1SDavid Howells _enter(",%x,{%llx:%llu},%u", 1762e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode, op->nr_files); 176330062bd1SDavid Howells 1764e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSInlineBulkStatus, 176530062bd1SDavid Howells sizeof(__be32) + 176630062bd1SDavid Howells sizeof(__be32) + 176730062bd1SDavid Howells sizeof(__be32) + 1768e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFid) * op->nr_files, 176930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus)); 1770e49c7b2fSDavid Howells if (!call) 1771e49c7b2fSDavid Howells return afs_op_nomem(op); 177230062bd1SDavid Howells 177330062bd1SDavid Howells /* marshall the parameters */ 177430062bd1SDavid Howells bp = call->request; 177530062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSINLINEBULKSTATUS); 177630062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPCFlags */ 1777e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, op->nr_files); 1778e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid); 1779e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 1780e49c7b2fSDavid Howells for (i = 0; i < op->nr_files - 2; i++) 1781e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &op->more_files[i].fid); 178230062bd1SDavid Howells yfs_check_req(call, bp); 178330062bd1SDavid Howells 1784e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1785e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS); 178630062bd1SDavid Howells } 1787ae46578bSDavid Howells 1788ae46578bSDavid Howells /* 1789ae46578bSDavid Howells * Deliver reply data to an YFS.FetchOpaqueACL. 1790ae46578bSDavid Howells */ 1791ae46578bSDavid Howells static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) 1792ae46578bSDavid Howells { 1793e49c7b2fSDavid Howells struct afs_operation *op = call->op; 1794e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 1795e49c7b2fSDavid Howells struct yfs_acl *yacl = op->yacl; 1796ae46578bSDavid Howells struct afs_acl *acl; 1797ae46578bSDavid Howells const __be32 *bp; 1798ae46578bSDavid Howells unsigned int size; 1799ae46578bSDavid Howells int ret; 1800ae46578bSDavid Howells 1801ae46578bSDavid Howells _enter("{%u}", call->unmarshall); 1802ae46578bSDavid Howells 1803ae46578bSDavid Howells switch (call->unmarshall) { 1804ae46578bSDavid Howells case 0: 1805ae46578bSDavid Howells afs_extract_to_tmp(call); 1806ae46578bSDavid Howells call->unmarshall++; 180735a3a90cSGustavo A. R. Silva /* Fall through */ 1808ae46578bSDavid Howells 1809ae46578bSDavid Howells /* Extract the file ACL length */ 1810ae46578bSDavid Howells case 1: 1811ae46578bSDavid Howells ret = afs_extract_data(call, true); 1812ae46578bSDavid Howells if (ret < 0) 1813ae46578bSDavid Howells return ret; 1814ae46578bSDavid Howells 1815ae46578bSDavid Howells size = call->count2 = ntohl(call->tmp); 1816ae46578bSDavid Howells size = round_up(size, 4); 1817ae46578bSDavid Howells 1818ae46578bSDavid Howells if (yacl->flags & YFS_ACL_WANT_ACL) { 1819ae46578bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); 1820ae46578bSDavid Howells if (!acl) 1821ae46578bSDavid Howells return -ENOMEM; 1822ae46578bSDavid Howells yacl->acl = acl; 1823ae46578bSDavid Howells acl->size = call->count2; 1824ae46578bSDavid Howells afs_extract_begin(call, acl->data, size); 1825ae46578bSDavid Howells } else { 182623a28913SDavid Howells afs_extract_discard(call, size); 1827ae46578bSDavid Howells } 1828ae46578bSDavid Howells call->unmarshall++; 182935a3a90cSGustavo A. R. Silva /* Fall through */ 1830ae46578bSDavid Howells 1831ae46578bSDavid Howells /* Extract the file ACL */ 1832ae46578bSDavid Howells case 2: 1833ae46578bSDavid Howells ret = afs_extract_data(call, true); 1834ae46578bSDavid Howells if (ret < 0) 1835ae46578bSDavid Howells return ret; 1836ae46578bSDavid Howells 1837ae46578bSDavid Howells afs_extract_to_tmp(call); 1838ae46578bSDavid Howells call->unmarshall++; 183935a3a90cSGustavo A. R. Silva /* Fall through */ 1840ae46578bSDavid Howells 1841ae46578bSDavid Howells /* Extract the volume ACL length */ 1842ae46578bSDavid Howells case 3: 1843ae46578bSDavid Howells ret = afs_extract_data(call, true); 1844ae46578bSDavid Howells if (ret < 0) 1845ae46578bSDavid Howells return ret; 1846ae46578bSDavid Howells 1847ae46578bSDavid Howells size = call->count2 = ntohl(call->tmp); 1848ae46578bSDavid Howells size = round_up(size, 4); 1849ae46578bSDavid Howells 1850ae46578bSDavid Howells if (yacl->flags & YFS_ACL_WANT_VOL_ACL) { 1851ae46578bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); 1852ae46578bSDavid Howells if (!acl) 1853ae46578bSDavid Howells return -ENOMEM; 1854ae46578bSDavid Howells yacl->vol_acl = acl; 1855ae46578bSDavid Howells acl->size = call->count2; 1856ae46578bSDavid Howells afs_extract_begin(call, acl->data, size); 1857ae46578bSDavid Howells } else { 185823a28913SDavid Howells afs_extract_discard(call, size); 1859ae46578bSDavid Howells } 1860ae46578bSDavid Howells call->unmarshall++; 186135a3a90cSGustavo A. R. Silva /* Fall through */ 1862ae46578bSDavid Howells 1863ae46578bSDavid Howells /* Extract the volume ACL */ 1864ae46578bSDavid Howells case 4: 1865ae46578bSDavid Howells ret = afs_extract_data(call, true); 1866ae46578bSDavid Howells if (ret < 0) 1867ae46578bSDavid Howells return ret; 1868ae46578bSDavid Howells 1869ae46578bSDavid Howells afs_extract_to_buf(call, 1870ae46578bSDavid Howells sizeof(__be32) * 2 + 1871ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 1872ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 1873ae46578bSDavid Howells call->unmarshall++; 187435a3a90cSGustavo A. R. Silva /* Fall through */ 1875ae46578bSDavid Howells 1876ae46578bSDavid Howells /* extract the metadata */ 1877ae46578bSDavid Howells case 5: 1878ae46578bSDavid Howells ret = afs_extract_data(call, false); 1879ae46578bSDavid Howells if (ret < 0) 1880ae46578bSDavid Howells return ret; 1881ae46578bSDavid Howells 1882ae46578bSDavid Howells bp = call->buffer; 1883ae46578bSDavid Howells yacl->inherit_flag = ntohl(*bp++); 1884ae46578bSDavid Howells yacl->num_cleaned = ntohl(*bp++); 1885e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb); 1886e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync); 1887ae46578bSDavid Howells 1888ae46578bSDavid Howells call->unmarshall++; 188935a3a90cSGustavo A. R. Silva /* Fall through */ 1890ae46578bSDavid Howells 1891ae46578bSDavid Howells case 6: 1892ae46578bSDavid Howells break; 1893ae46578bSDavid Howells } 1894ae46578bSDavid Howells 1895ae46578bSDavid Howells _leave(" = 0 [done]"); 1896ae46578bSDavid Howells return 0; 1897ae46578bSDavid Howells } 1898ae46578bSDavid Howells 1899ae46578bSDavid Howells void yfs_free_opaque_acl(struct yfs_acl *yacl) 1900ae46578bSDavid Howells { 1901ae46578bSDavid Howells if (yacl) { 1902ae46578bSDavid Howells kfree(yacl->acl); 1903ae46578bSDavid Howells kfree(yacl->vol_acl); 1904ae46578bSDavid Howells kfree(yacl); 1905ae46578bSDavid Howells } 1906ae46578bSDavid Howells } 1907ae46578bSDavid Howells 1908ae46578bSDavid Howells /* 1909ae46578bSDavid Howells * YFS.FetchOpaqueACL operation type 1910ae46578bSDavid Howells */ 1911ae46578bSDavid Howells static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = { 1912ae46578bSDavid Howells .name = "YFS.FetchOpaqueACL", 1913ae46578bSDavid Howells .op = yfs_FS_FetchOpaqueACL, 1914ae46578bSDavid Howells .deliver = yfs_deliver_fs_fetch_opaque_acl, 1915773e0c40SDavid Howells .destructor = afs_flat_call_destructor, 1916ae46578bSDavid Howells }; 1917ae46578bSDavid Howells 1918ae46578bSDavid Howells /* 1919ae46578bSDavid Howells * Fetch the YFS advanced ACLs for a file. 1920ae46578bSDavid Howells */ 1921e49c7b2fSDavid Howells void yfs_fs_fetch_opaque_acl(struct afs_operation *op) 1922ae46578bSDavid Howells { 1923e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 1924ae46578bSDavid Howells struct afs_call *call; 1925ae46578bSDavid Howells __be32 *bp; 1926ae46578bSDavid Howells 1927ae46578bSDavid Howells _enter(",%x,{%llx:%llu},,", 1928e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode); 1929ae46578bSDavid Howells 1930e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchOpaqueACL, 1931ae46578bSDavid Howells sizeof(__be32) * 2 + 1932ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFid), 1933ae46578bSDavid Howells sizeof(__be32) * 2 + 1934ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 1935ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 1936e49c7b2fSDavid Howells if (!call) 1937e49c7b2fSDavid Howells return afs_op_nomem(op); 1938ae46578bSDavid Howells 1939ae46578bSDavid Howells /* marshall the parameters */ 1940ae46578bSDavid Howells bp = call->request; 1941ae46578bSDavid Howells bp = xdr_encode_u32(bp, YFSFETCHOPAQUEACL); 1942ae46578bSDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1943e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 1944ae46578bSDavid Howells yfs_check_req(call, bp); 1945ae46578bSDavid Howells 1946e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1947e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_KERNEL); 1948ae46578bSDavid Howells } 1949f5e45463SDavid Howells 1950f5e45463SDavid Howells /* 1951f5e45463SDavid Howells * YFS.StoreOpaqueACL2 operation type 1952f5e45463SDavid Howells */ 1953f5e45463SDavid Howells static const struct afs_call_type yfs_RXYFSStoreOpaqueACL2 = { 1954f5e45463SDavid Howells .name = "YFS.StoreOpaqueACL2", 1955f5e45463SDavid Howells .op = yfs_FS_StoreOpaqueACL2, 1956f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync, 1957f5e45463SDavid Howells .destructor = afs_flat_call_destructor, 1958f5e45463SDavid Howells }; 1959f5e45463SDavid Howells 1960f5e45463SDavid Howells /* 1961f5e45463SDavid Howells * Fetch the YFS ACL for a file. 1962f5e45463SDavid Howells */ 1963e49c7b2fSDavid Howells void yfs_fs_store_opaque_acl2(struct afs_operation *op) 1964f5e45463SDavid Howells { 1965e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0]; 1966f5e45463SDavid Howells struct afs_call *call; 1967e49c7b2fSDavid Howells struct afs_acl *acl = op->acl; 1968f5e45463SDavid Howells size_t size; 1969f5e45463SDavid Howells __be32 *bp; 1970f5e45463SDavid Howells 1971f5e45463SDavid Howells _enter(",%x,{%llx:%llu},,", 1972e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode); 1973f5e45463SDavid Howells 1974f5e45463SDavid Howells size = round_up(acl->size, 4); 1975e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreOpaqueACL2, 1976f5e45463SDavid Howells sizeof(__be32) * 2 + 1977f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSFid) + 1978f5e45463SDavid Howells sizeof(__be32) + size, 1979f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) + 1980f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSVolSync)); 1981e49c7b2fSDavid Howells if (!call) 1982e49c7b2fSDavid Howells return afs_op_nomem(op); 1983f5e45463SDavid Howells 1984f5e45463SDavid Howells /* marshall the parameters */ 1985f5e45463SDavid Howells bp = call->request; 1986f5e45463SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREOPAQUEACL2); 1987f5e45463SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1988e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid); 1989f5e45463SDavid Howells bp = xdr_encode_u32(bp, acl->size); 1990f5e45463SDavid Howells memcpy(bp, acl->data, acl->size); 1991f5e45463SDavid Howells if (acl->size != size) 1992f5e45463SDavid Howells memset((void *)bp + acl->size, 0, size - acl->size); 1993f5e45463SDavid Howells yfs_check_req(call, bp); 1994f5e45463SDavid Howells 1995e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid); 1996e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_KERNEL); 199730062bd1SDavid Howells } 1998