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
xdr_decode_YFSFid(const __be32 ** _bp,struct afs_fid * fid)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
xdr_encode_u32(__be32 * bp,u32 n)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
xdr_encode_u64(__be32 * bp,u64 n)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
xdr_encode_YFSFid(__be32 * bp,struct afs_fid * fid)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
xdr_strlen(unsigned int len)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
xdr_encode_string(__be32 * bp,const char * p,unsigned int len)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
xdr_encode_name(__be32 * bp,const struct qstr * p)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
linux_to_yfs_time(const struct timespec64 * t)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
xdr_encode_YFSStoreStatus(__be32 * bp,mode_t * mode,const struct timespec64 * t)8652af7105SMarc Dionne static __be32 *xdr_encode_YFSStoreStatus(__be32 *bp, mode_t *mode,
8752af7105SMarc Dionne const struct timespec64 *t)
8830062bd1SDavid Howells {
8930062bd1SDavid Howells struct yfs_xdr_YFSStoreStatus *x = (void *)bp;
9052af7105SMarc Dionne mode_t masked_mode = mode ? *mode & S_IALLUGO : 0;
9130062bd1SDavid Howells s64 mtime = linux_to_yfs_time(t);
9252af7105SMarc Dionne u32 mask = AFS_SET_MTIME;
9330062bd1SDavid Howells
9452af7105SMarc Dionne mask |= mode ? AFS_SET_MODE : 0;
9552af7105SMarc Dionne
9652af7105SMarc Dionne x->mask = htonl(mask);
9752af7105SMarc Dionne x->mode = htonl(masked_mode);
9830062bd1SDavid Howells x->mtime_client = u64_to_xdr(mtime);
9930062bd1SDavid Howells x->owner = u64_to_xdr(0);
10030062bd1SDavid Howells x->group = u64_to_xdr(0);
10130062bd1SDavid Howells return bp + xdr_size(x);
10230062bd1SDavid Howells }
10330062bd1SDavid Howells
10430062bd1SDavid Howells /*
10530062bd1SDavid Howells * Convert a signed 100ns-resolution 64-bit time into a timespec.
10630062bd1SDavid Howells */
yfs_time_to_linux(s64 t)10730062bd1SDavid Howells static struct timespec64 yfs_time_to_linux(s64 t)
10830062bd1SDavid Howells {
10930062bd1SDavid Howells struct timespec64 ts;
11030062bd1SDavid Howells u64 abs_t;
11130062bd1SDavid Howells
11230062bd1SDavid Howells /*
11330062bd1SDavid Howells * Unfortunately can not use normal 64 bit division on 32 bit arch, but
11430062bd1SDavid Howells * the alternative, do_div, does not work with negative numbers so have
11530062bd1SDavid Howells * to special case them
11630062bd1SDavid Howells */
11730062bd1SDavid Howells if (t < 0) {
11830062bd1SDavid Howells abs_t = -t;
11930062bd1SDavid Howells ts.tv_nsec = (time64_t)(do_div(abs_t, 10000000) * 100);
12030062bd1SDavid Howells ts.tv_nsec = -ts.tv_nsec;
12130062bd1SDavid Howells ts.tv_sec = -abs_t;
12230062bd1SDavid Howells } else {
12330062bd1SDavid Howells abs_t = t;
12430062bd1SDavid Howells ts.tv_nsec = (time64_t)do_div(abs_t, 10000000) * 100;
12530062bd1SDavid Howells ts.tv_sec = abs_t;
12630062bd1SDavid Howells }
12730062bd1SDavid Howells
12830062bd1SDavid Howells return ts;
12930062bd1SDavid Howells }
13030062bd1SDavid Howells
xdr_to_time(const struct yfs_xdr_u64 xdr)13130062bd1SDavid Howells static struct timespec64 xdr_to_time(const struct yfs_xdr_u64 xdr)
13230062bd1SDavid Howells {
13330062bd1SDavid Howells s64 t = xdr_to_u64(xdr);
13430062bd1SDavid Howells
13530062bd1SDavid Howells return yfs_time_to_linux(t);
13630062bd1SDavid Howells }
13730062bd1SDavid Howells
yfs_check_req(struct afs_call * call,__be32 * bp)13830062bd1SDavid Howells static void yfs_check_req(struct afs_call *call, __be32 *bp)
13930062bd1SDavid Howells {
14030062bd1SDavid Howells size_t len = (void *)bp - call->request;
14130062bd1SDavid Howells
14230062bd1SDavid Howells if (len > call->request_size)
14330062bd1SDavid Howells pr_err("kAFS: %s: Request buffer overflow (%zu>%u)\n",
14430062bd1SDavid Howells call->type->name, len, call->request_size);
14530062bd1SDavid Howells else if (len < call->request_size)
146a4e530aeSKefeng Wang pr_warn("kAFS: %s: Request buffer underflow (%zu<%u)\n",
14730062bd1SDavid Howells call->type->name, len, call->request_size);
14830062bd1SDavid Howells }
14930062bd1SDavid Howells
15030062bd1SDavid Howells /*
15130062bd1SDavid Howells * Dump a bad file status record.
15230062bd1SDavid Howells */
xdr_dump_bad(const __be32 * bp)15330062bd1SDavid Howells static void xdr_dump_bad(const __be32 *bp)
15430062bd1SDavid Howells {
15530062bd1SDavid Howells __be32 x[4];
15630062bd1SDavid Howells int i;
15730062bd1SDavid Howells
15830062bd1SDavid Howells pr_notice("YFS XDR: Bad status record\n");
1593efe55b0SDavid Howells for (i = 0; i < 6 * 4 * 4; i += 16) {
16030062bd1SDavid Howells memcpy(x, bp, 16);
16130062bd1SDavid Howells bp += 4;
16230062bd1SDavid Howells pr_notice("%03x: %08x %08x %08x %08x\n",
16330062bd1SDavid Howells i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
16430062bd1SDavid Howells }
16530062bd1SDavid Howells
1663efe55b0SDavid Howells memcpy(x, bp, 8);
1673efe55b0SDavid Howells pr_notice("0x60: %08x %08x\n", ntohl(x[0]), ntohl(x[1]));
16830062bd1SDavid Howells }
16930062bd1SDavid Howells
17030062bd1SDavid Howells /*
17130062bd1SDavid Howells * Decode a YFSFetchStatus block
17230062bd1SDavid Howells */
xdr_decode_YFSFetchStatus(const __be32 ** _bp,struct afs_call * call,struct afs_status_cb * scb)17338355eecSDavid Howells static void xdr_decode_YFSFetchStatus(const __be32 **_bp,
174a58823acSDavid Howells struct afs_call *call,
175a58823acSDavid Howells struct afs_status_cb *scb)
17630062bd1SDavid Howells {
17730062bd1SDavid Howells const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;
178a58823acSDavid Howells struct afs_file_status *status = &scb->status;
17930062bd1SDavid Howells u32 type;
18030062bd1SDavid Howells
18130062bd1SDavid Howells status->abort_code = ntohl(xdr->abort_code);
18230062bd1SDavid Howells if (status->abort_code != 0) {
183a58823acSDavid Howells if (status->abort_code == VNOVNODE)
18430062bd1SDavid Howells status->nlink = 0;
185a38a7558SDavid Howells scb->have_error = true;
18638355eecSDavid Howells goto advance;
18730062bd1SDavid Howells }
18830062bd1SDavid Howells
18930062bd1SDavid Howells type = ntohl(xdr->type);
19030062bd1SDavid Howells switch (type) {
19130062bd1SDavid Howells case AFS_FTYPE_FILE:
19230062bd1SDavid Howells case AFS_FTYPE_DIR:
19330062bd1SDavid Howells case AFS_FTYPE_SYMLINK:
19430062bd1SDavid Howells status->type = type;
19530062bd1SDavid Howells break;
19630062bd1SDavid Howells default:
19730062bd1SDavid Howells goto bad;
19830062bd1SDavid Howells }
19930062bd1SDavid Howells
200a58823acSDavid Howells status->nlink = ntohl(xdr->nlink);
201a58823acSDavid Howells status->author = xdr_to_u64(xdr->author);
202a58823acSDavid Howells status->owner = xdr_to_u64(xdr->owner);
203a58823acSDavid Howells status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */
204a58823acSDavid Howells status->anon_access = ntohl(xdr->anon_access);
205a58823acSDavid Howells status->mode = ntohl(xdr->mode) & S_IALLUGO;
206a58823acSDavid Howells status->group = xdr_to_u64(xdr->group);
207a58823acSDavid Howells status->lock_count = ntohl(xdr->lock_count);
20830062bd1SDavid Howells
20930062bd1SDavid Howells status->mtime_client = xdr_to_time(xdr->mtime_client);
21030062bd1SDavid Howells status->mtime_server = xdr_to_time(xdr->mtime_server);
211a58823acSDavid Howells status->size = xdr_to_u64(xdr->size);
212a58823acSDavid Howells status->data_version = xdr_to_u64(xdr->data_version);
213a38a7558SDavid Howells scb->have_status = true;
214c72057b5SDavid Howells advance:
21530062bd1SDavid Howells *_bp += xdr_size(xdr);
21638355eecSDavid Howells return;
21730062bd1SDavid Howells
21830062bd1SDavid Howells bad:
21930062bd1SDavid Howells xdr_dump_bad(*_bp);
2207126ead9SDavid Howells afs_protocol_error(call, afs_eproto_bad_status);
221c72057b5SDavid Howells goto advance;
22230062bd1SDavid Howells }
22330062bd1SDavid Howells
22430062bd1SDavid Howells /*
225a58823acSDavid Howells * Decode a YFSCallBack block
22630062bd1SDavid Howells */
xdr_decode_YFSCallBack(const __be32 ** _bp,struct afs_call * call,struct afs_status_cb * scb)227a58823acSDavid Howells static void xdr_decode_YFSCallBack(const __be32 **_bp,
228a58823acSDavid Howells struct afs_call *call,
229a58823acSDavid Howells struct afs_status_cb *scb)
23078107055SDavid Howells {
23178107055SDavid Howells struct yfs_xdr_YFSCallBack *x = (void *)*_bp;
232a58823acSDavid Howells struct afs_callback *cb = &scb->callback;
23378107055SDavid Howells ktime_t cb_expiry;
23478107055SDavid Howells
2357903192cSDavid Howells cb_expiry = ktime_add(call->issue_time, xdr_to_u64(x->expiration_time) * 100);
23678107055SDavid Howells cb->expires_at = ktime_divns(cb_expiry, NSEC_PER_SEC);
237a58823acSDavid Howells scb->have_cb = true;
23878107055SDavid Howells *_bp += xdr_size(x);
23978107055SDavid Howells }
24078107055SDavid Howells
24130062bd1SDavid Howells /*
24230062bd1SDavid Howells * Decode a YFSVolSync block
24330062bd1SDavid Howells */
xdr_decode_YFSVolSync(const __be32 ** _bp,struct afs_volsync * volsync)24430062bd1SDavid Howells static void xdr_decode_YFSVolSync(const __be32 **_bp,
24530062bd1SDavid Howells struct afs_volsync *volsync)
24630062bd1SDavid Howells {
24730062bd1SDavid Howells struct yfs_xdr_YFSVolSync *x = (void *)*_bp;
24830062bd1SDavid Howells u64 creation;
24930062bd1SDavid Howells
25030062bd1SDavid Howells if (volsync) {
25130062bd1SDavid Howells creation = xdr_to_u64(x->vol_creation_date);
25230062bd1SDavid Howells do_div(creation, 10 * 1000 * 1000);
25330062bd1SDavid Howells volsync->creation = creation;
25430062bd1SDavid Howells }
25530062bd1SDavid Howells
25630062bd1SDavid Howells *_bp += xdr_size(x);
25730062bd1SDavid Howells }
25830062bd1SDavid Howells
25930062bd1SDavid Howells /*
26030062bd1SDavid Howells * Encode the requested attributes into a YFSStoreStatus block
26130062bd1SDavid Howells */
xdr_encode_YFS_StoreStatus(__be32 * bp,struct iattr * attr)26230062bd1SDavid Howells static __be32 *xdr_encode_YFS_StoreStatus(__be32 *bp, struct iattr *attr)
26330062bd1SDavid Howells {
26430062bd1SDavid Howells struct yfs_xdr_YFSStoreStatus *x = (void *)bp;
26530062bd1SDavid Howells s64 mtime = 0, owner = 0, group = 0;
26630062bd1SDavid Howells u32 mask = 0, mode = 0;
26730062bd1SDavid Howells
26830062bd1SDavid Howells mask = 0;
26930062bd1SDavid Howells if (attr->ia_valid & ATTR_MTIME) {
27030062bd1SDavid Howells mask |= AFS_SET_MTIME;
27130062bd1SDavid Howells mtime = linux_to_yfs_time(&attr->ia_mtime);
27230062bd1SDavid Howells }
27330062bd1SDavid Howells
27430062bd1SDavid Howells if (attr->ia_valid & ATTR_UID) {
27530062bd1SDavid Howells mask |= AFS_SET_OWNER;
27630062bd1SDavid Howells owner = from_kuid(&init_user_ns, attr->ia_uid);
27730062bd1SDavid Howells }
27830062bd1SDavid Howells
27930062bd1SDavid Howells if (attr->ia_valid & ATTR_GID) {
28030062bd1SDavid Howells mask |= AFS_SET_GROUP;
28130062bd1SDavid Howells group = from_kgid(&init_user_ns, attr->ia_gid);
28230062bd1SDavid Howells }
28330062bd1SDavid Howells
28430062bd1SDavid Howells if (attr->ia_valid & ATTR_MODE) {
28530062bd1SDavid Howells mask |= AFS_SET_MODE;
28630062bd1SDavid Howells mode = attr->ia_mode & S_IALLUGO;
28730062bd1SDavid Howells }
28830062bd1SDavid Howells
28930062bd1SDavid Howells x->mask = htonl(mask);
29030062bd1SDavid Howells x->mode = htonl(mode);
29130062bd1SDavid Howells x->mtime_client = u64_to_xdr(mtime);
29230062bd1SDavid Howells x->owner = u64_to_xdr(owner);
29330062bd1SDavid Howells x->group = u64_to_xdr(group);
29430062bd1SDavid Howells return bp + xdr_size(x);
29530062bd1SDavid Howells }
29630062bd1SDavid Howells
29730062bd1SDavid Howells /*
29830062bd1SDavid Howells * Decode a YFSFetchVolumeStatus block.
29930062bd1SDavid Howells */
xdr_decode_YFSFetchVolumeStatus(const __be32 ** _bp,struct afs_volume_status * vs)30030062bd1SDavid Howells static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp,
30130062bd1SDavid Howells struct afs_volume_status *vs)
30230062bd1SDavid Howells {
30330062bd1SDavid Howells const struct yfs_xdr_YFSFetchVolumeStatus *x = (const void *)*_bp;
30430062bd1SDavid Howells u32 flags;
30530062bd1SDavid Howells
30630062bd1SDavid Howells vs->vid = xdr_to_u64(x->vid);
30730062bd1SDavid Howells vs->parent_id = xdr_to_u64(x->parent_id);
30830062bd1SDavid Howells flags = ntohl(x->flags);
30930062bd1SDavid Howells vs->online = flags & yfs_FVSOnline;
31030062bd1SDavid Howells vs->in_service = flags & yfs_FVSInservice;
31130062bd1SDavid Howells vs->blessed = flags & yfs_FVSBlessed;
31230062bd1SDavid Howells vs->needs_salvage = flags & yfs_FVSNeedsSalvage;
31330062bd1SDavid Howells vs->type = ntohl(x->type);
31430062bd1SDavid Howells vs->min_quota = 0;
31530062bd1SDavid Howells vs->max_quota = xdr_to_u64(x->max_quota);
31630062bd1SDavid Howells vs->blocks_in_use = xdr_to_u64(x->blocks_in_use);
31730062bd1SDavid Howells vs->part_blocks_avail = xdr_to_u64(x->part_blocks_avail);
31830062bd1SDavid Howells vs->part_max_blocks = xdr_to_u64(x->part_max_blocks);
31930062bd1SDavid Howells vs->vol_copy_date = xdr_to_u64(x->vol_copy_date);
32030062bd1SDavid Howells vs->vol_backup_date = xdr_to_u64(x->vol_backup_date);
32130062bd1SDavid Howells *_bp += sizeof(*x) / sizeof(__be32);
32230062bd1SDavid Howells }
32330062bd1SDavid Howells
32430062bd1SDavid Howells /*
325a58823acSDavid Howells * Deliver reply data to operations that just return a file status and a volume
326a58823acSDavid Howells * sync record.
327a58823acSDavid Howells */
yfs_deliver_status_and_volsync(struct afs_call * call)328a58823acSDavid Howells static int yfs_deliver_status_and_volsync(struct afs_call *call)
329a58823acSDavid Howells {
330e49c7b2fSDavid Howells struct afs_operation *op = call->op;
331a58823acSDavid Howells const __be32 *bp;
332a58823acSDavid Howells int ret;
333a58823acSDavid Howells
334a58823acSDavid Howells ret = afs_transfer_reply(call);
335a58823acSDavid Howells if (ret < 0)
336a58823acSDavid Howells return ret;
337a58823acSDavid Howells
338a58823acSDavid Howells bp = call->buffer;
339e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &op->file[0].scb);
340e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
34130062bd1SDavid Howells
34230062bd1SDavid Howells _leave(" = 0 [done]");
34330062bd1SDavid Howells return 0;
34430062bd1SDavid Howells }
34530062bd1SDavid Howells
34630062bd1SDavid Howells /*
34730062bd1SDavid Howells * Deliver reply data to an YFS.FetchData64.
34830062bd1SDavid Howells */
yfs_deliver_fs_fetch_data64(struct afs_call * call)34930062bd1SDavid Howells static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
35030062bd1SDavid Howells {
351e49c7b2fSDavid Howells struct afs_operation *op = call->op;
352e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
353e49c7b2fSDavid Howells struct afs_read *req = op->fetch.req;
35430062bd1SDavid Howells const __be32 *bp;
35530062bd1SDavid Howells int ret;
35630062bd1SDavid Howells
357f105da1aSDavid Howells _enter("{%u,%zu, %zu/%llu}",
358f105da1aSDavid Howells call->unmarshall, call->iov_len, iov_iter_count(call->iter),
359f105da1aSDavid Howells req->actual_len);
36030062bd1SDavid Howells
36130062bd1SDavid Howells switch (call->unmarshall) {
36230062bd1SDavid Howells case 0:
36330062bd1SDavid Howells req->actual_len = 0;
36430062bd1SDavid Howells afs_extract_to_tmp64(call);
36530062bd1SDavid Howells call->unmarshall++;
366df561f66SGustavo A. R. Silva fallthrough;
36730062bd1SDavid Howells
368c4508464SDavid Howells /* Extract the returned data length into ->actual_len. This
369c4508464SDavid Howells * may indicate more or less data than was requested will be
370c4508464SDavid Howells * returned.
371c4508464SDavid Howells */
37230062bd1SDavid Howells case 1:
37330062bd1SDavid Howells _debug("extract data length");
37430062bd1SDavid Howells ret = afs_extract_data(call, true);
37530062bd1SDavid Howells if (ret < 0)
37630062bd1SDavid Howells return ret;
37730062bd1SDavid Howells
37830062bd1SDavid Howells req->actual_len = be64_to_cpu(call->tmp64);
37930062bd1SDavid Howells _debug("DATA length: %llu", req->actual_len);
380c4508464SDavid Howells
381c4508464SDavid Howells if (req->actual_len == 0)
38230062bd1SDavid Howells goto no_more_data;
38330062bd1SDavid Howells
384c4508464SDavid Howells call->iter = req->iter;
385c4508464SDavid Howells call->iov_len = min(req->actual_len, req->len);
38630062bd1SDavid Howells call->unmarshall++;
387df561f66SGustavo A. R. Silva fallthrough;
38830062bd1SDavid Howells
38935a3a90cSGustavo A. R. Silva /* extract the returned data */
39030062bd1SDavid Howells case 2:
39130062bd1SDavid Howells _debug("extract data %zu/%llu",
392c4508464SDavid Howells iov_iter_count(call->iter), req->actual_len);
39330062bd1SDavid Howells
39430062bd1SDavid Howells ret = afs_extract_data(call, true);
39530062bd1SDavid Howells if (ret < 0)
39630062bd1SDavid Howells return ret;
39730062bd1SDavid Howells
398c4508464SDavid Howells call->iter = &call->def_iter;
39930062bd1SDavid Howells if (req->actual_len <= req->len)
40030062bd1SDavid Howells goto no_more_data;
40130062bd1SDavid Howells
40230062bd1SDavid Howells /* Discard any excess data the server gave us */
40323a28913SDavid Howells afs_extract_discard(call, req->actual_len - req->len);
40430062bd1SDavid Howells call->unmarshall = 3;
405df561f66SGustavo A. R. Silva fallthrough;
40635a3a90cSGustavo A. R. Silva
40730062bd1SDavid Howells case 3:
40830062bd1SDavid Howells _debug("extract discard %zu/%llu",
409fc276122SDavid Howells iov_iter_count(call->iter), req->actual_len - req->len);
41030062bd1SDavid Howells
41130062bd1SDavid Howells ret = afs_extract_data(call, true);
41230062bd1SDavid Howells if (ret < 0)
41330062bd1SDavid Howells return ret;
41430062bd1SDavid Howells
41530062bd1SDavid Howells no_more_data:
41630062bd1SDavid Howells call->unmarshall = 4;
41730062bd1SDavid Howells afs_extract_to_buf(call,
41830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
41930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
42030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
421df561f66SGustavo A. R. Silva fallthrough;
42230062bd1SDavid Howells
42335a3a90cSGustavo A. R. Silva /* extract the metadata */
42430062bd1SDavid Howells case 4:
42530062bd1SDavid Howells ret = afs_extract_data(call, false);
42630062bd1SDavid Howells if (ret < 0)
42730062bd1SDavid Howells return ret;
42830062bd1SDavid Howells
42930062bd1SDavid Howells bp = call->buffer;
430e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
431e49c7b2fSDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb);
432e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
43330062bd1SDavid Howells
434e49c7b2fSDavid Howells req->data_version = vp->scb.status.data_version;
435e49c7b2fSDavid Howells req->file_size = vp->scb.status.size;
436a58823acSDavid Howells
43730062bd1SDavid Howells call->unmarshall++;
438df561f66SGustavo A. R. Silva fallthrough;
43935a3a90cSGustavo A. R. Silva
44030062bd1SDavid Howells case 5:
44130062bd1SDavid Howells break;
44230062bd1SDavid Howells }
44330062bd1SDavid Howells
44430062bd1SDavid Howells _leave(" = 0 [done]");
44530062bd1SDavid Howells return 0;
44630062bd1SDavid Howells }
44730062bd1SDavid Howells
44830062bd1SDavid Howells /*
44930062bd1SDavid Howells * YFS.FetchData64 operation type
45030062bd1SDavid Howells */
45130062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSFetchData64 = {
45230062bd1SDavid Howells .name = "YFS.FetchData64",
45330062bd1SDavid Howells .op = yfs_FS_FetchData64,
45430062bd1SDavid Howells .deliver = yfs_deliver_fs_fetch_data64,
455e49c7b2fSDavid Howells .destructor = afs_flat_call_destructor,
45630062bd1SDavid Howells };
45730062bd1SDavid Howells
45830062bd1SDavid Howells /*
45930062bd1SDavid Howells * Fetch data from a file.
46030062bd1SDavid Howells */
yfs_fs_fetch_data(struct afs_operation * op)461e49c7b2fSDavid Howells void yfs_fs_fetch_data(struct afs_operation *op)
46230062bd1SDavid Howells {
463e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
464e49c7b2fSDavid Howells struct afs_read *req = op->fetch.req;
46530062bd1SDavid Howells struct afs_call *call;
46630062bd1SDavid Howells __be32 *bp;
46730062bd1SDavid Howells
46830062bd1SDavid Howells _enter(",%x,{%llx:%llu},%llx,%llx",
469e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode,
47030062bd1SDavid Howells req->pos, req->len);
47130062bd1SDavid Howells
472e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchData64,
47330062bd1SDavid Howells sizeof(__be32) * 2 +
47430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
47530062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 2,
47630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
47730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
47830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
47930062bd1SDavid Howells if (!call)
480e49c7b2fSDavid Howells return afs_op_nomem(op);
48130062bd1SDavid Howells
482c4508464SDavid Howells req->call_debug_id = call->debug_id;
483c4508464SDavid Howells
48430062bd1SDavid Howells /* marshall the parameters */
48530062bd1SDavid Howells bp = call->request;
48630062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSFETCHDATA64);
48730062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
488e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
48930062bd1SDavid Howells bp = xdr_encode_u64(bp, req->pos);
49030062bd1SDavid Howells bp = xdr_encode_u64(bp, req->len);
49130062bd1SDavid Howells yfs_check_req(call, bp);
49230062bd1SDavid Howells
493e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
494e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
49530062bd1SDavid Howells }
49630062bd1SDavid Howells
49730062bd1SDavid Howells /*
49830062bd1SDavid Howells * Deliver reply data for YFS.CreateFile or YFS.MakeDir.
49930062bd1SDavid Howells */
yfs_deliver_fs_create_vnode(struct afs_call * call)50030062bd1SDavid Howells static int yfs_deliver_fs_create_vnode(struct afs_call *call)
50130062bd1SDavid Howells {
502e49c7b2fSDavid Howells struct afs_operation *op = call->op;
503e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
504e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
50530062bd1SDavid Howells const __be32 *bp;
50630062bd1SDavid Howells int ret;
50730062bd1SDavid Howells
50830062bd1SDavid Howells _enter("{%u}", call->unmarshall);
50930062bd1SDavid Howells
51030062bd1SDavid Howells ret = afs_transfer_reply(call);
51130062bd1SDavid Howells if (ret < 0)
51230062bd1SDavid Howells return ret;
51330062bd1SDavid Howells
51430062bd1SDavid Howells /* unmarshall the reply once we've received all of it */
51530062bd1SDavid Howells bp = call->buffer;
516e49c7b2fSDavid Howells xdr_decode_YFSFid(&bp, &op->file[1].fid);
517e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
518e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
519e49c7b2fSDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb);
520e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
52130062bd1SDavid Howells
52230062bd1SDavid Howells _leave(" = 0 [done]");
52330062bd1SDavid Howells return 0;
52430062bd1SDavid Howells }
52530062bd1SDavid Howells
52630062bd1SDavid Howells /*
52730062bd1SDavid Howells * FS.CreateFile and FS.MakeDir operation type
52830062bd1SDavid Howells */
52930062bd1SDavid Howells static const struct afs_call_type afs_RXFSCreateFile = {
53030062bd1SDavid Howells .name = "YFS.CreateFile",
53130062bd1SDavid Howells .op = yfs_FS_CreateFile,
53230062bd1SDavid Howells .deliver = yfs_deliver_fs_create_vnode,
53330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
53430062bd1SDavid Howells };
53530062bd1SDavid Howells
53630062bd1SDavid Howells /*
53730062bd1SDavid Howells * Create a file.
53830062bd1SDavid Howells */
yfs_fs_create_file(struct afs_operation * op)539e49c7b2fSDavid Howells void yfs_fs_create_file(struct afs_operation *op)
54030062bd1SDavid Howells {
541e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
542e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
54330062bd1SDavid Howells struct afs_call *call;
544e49c7b2fSDavid Howells size_t reqsz, rplsz;
54530062bd1SDavid Howells __be32 *bp;
54630062bd1SDavid Howells
54730062bd1SDavid Howells _enter("");
54830062bd1SDavid Howells
54930062bd1SDavid Howells reqsz = (sizeof(__be32) +
55030062bd1SDavid Howells sizeof(__be32) +
55130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
552e49c7b2fSDavid Howells xdr_strlen(name->len) +
55330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) +
55430062bd1SDavid Howells sizeof(__be32));
55530062bd1SDavid Howells rplsz = (sizeof(struct yfs_xdr_YFSFid) +
55630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
55730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
55830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
55930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
56030062bd1SDavid Howells
561e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &afs_RXFSCreateFile, reqsz, rplsz);
56230062bd1SDavid Howells if (!call)
563e49c7b2fSDavid Howells return afs_op_nomem(op);
56430062bd1SDavid Howells
56530062bd1SDavid Howells /* marshall the parameters */
56630062bd1SDavid Howells bp = call->request;
56730062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSCREATEFILE);
56830062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
569e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
570e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
57152af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, &op->create.mode, &op->mtime);
5725edc22ccSMarc Dionne bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */
57330062bd1SDavid Howells yfs_check_req(call, bp);
57430062bd1SDavid Howells
575e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
576e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
57730062bd1SDavid Howells }
57830062bd1SDavid Howells
57930062bd1SDavid Howells static const struct afs_call_type yfs_RXFSMakeDir = {
58030062bd1SDavid Howells .name = "YFS.MakeDir",
58130062bd1SDavid Howells .op = yfs_FS_MakeDir,
58230062bd1SDavid Howells .deliver = yfs_deliver_fs_create_vnode,
58330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
58430062bd1SDavid Howells };
58530062bd1SDavid Howells
58630062bd1SDavid Howells /*
58730062bd1SDavid Howells * Make a directory.
58830062bd1SDavid Howells */
yfs_fs_make_dir(struct afs_operation * op)589e49c7b2fSDavid Howells void yfs_fs_make_dir(struct afs_operation *op)
59030062bd1SDavid Howells {
591e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
592e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
59330062bd1SDavid Howells struct afs_call *call;
594e49c7b2fSDavid Howells size_t reqsz, rplsz;
59530062bd1SDavid Howells __be32 *bp;
59630062bd1SDavid Howells
59730062bd1SDavid Howells _enter("");
59830062bd1SDavid Howells
59930062bd1SDavid Howells reqsz = (sizeof(__be32) +
60030062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
60130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
602e49c7b2fSDavid Howells xdr_strlen(name->len) +
60330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus));
60430062bd1SDavid Howells rplsz = (sizeof(struct yfs_xdr_YFSFid) +
60530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
60630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
60730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
60830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
60930062bd1SDavid Howells
610e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXFSMakeDir, reqsz, rplsz);
61130062bd1SDavid Howells if (!call)
612e49c7b2fSDavid Howells return afs_op_nomem(op);
61330062bd1SDavid Howells
61430062bd1SDavid Howells /* marshall the parameters */
61530062bd1SDavid Howells bp = call->request;
61630062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSMAKEDIR);
61730062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
618e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
619e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
62052af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, &op->create.mode, &op->mtime);
62130062bd1SDavid Howells yfs_check_req(call, bp);
62230062bd1SDavid Howells
623e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
624e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
62530062bd1SDavid Howells }
62630062bd1SDavid Howells
62730062bd1SDavid Howells /*
62830062bd1SDavid Howells * Deliver reply data to a YFS.RemoveFile2 operation.
62930062bd1SDavid Howells */
yfs_deliver_fs_remove_file2(struct afs_call * call)63030062bd1SDavid Howells static int yfs_deliver_fs_remove_file2(struct afs_call *call)
63130062bd1SDavid Howells {
632e49c7b2fSDavid Howells struct afs_operation *op = call->op;
633e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
634e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
63530062bd1SDavid Howells struct afs_fid fid;
63630062bd1SDavid Howells const __be32 *bp;
63730062bd1SDavid Howells int ret;
63830062bd1SDavid Howells
63930062bd1SDavid Howells _enter("{%u}", call->unmarshall);
64030062bd1SDavid Howells
64130062bd1SDavid Howells ret = afs_transfer_reply(call);
64230062bd1SDavid Howells if (ret < 0)
64330062bd1SDavid Howells return ret;
64430062bd1SDavid Howells
64530062bd1SDavid Howells bp = call->buffer;
646e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
64730062bd1SDavid Howells xdr_decode_YFSFid(&bp, &fid);
648e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
64930062bd1SDavid Howells /* Was deleted if vnode->status.abort_code == VNOVNODE. */
65030062bd1SDavid Howells
651e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
65230062bd1SDavid Howells return 0;
65330062bd1SDavid Howells }
65430062bd1SDavid Howells
yfs_done_fs_remove_file2(struct afs_call * call)655e49c7b2fSDavid Howells static void yfs_done_fs_remove_file2(struct afs_call *call)
656e49c7b2fSDavid Howells {
657e49c7b2fSDavid Howells if (call->error == -ECONNABORTED &&
658*c89b19e9SDavid Howells (call->abort_code == RX_INVALID_OPERATION ||
659*c89b19e9SDavid Howells call->abort_code == RXGEN_OPCODE)) {
660*c89b19e9SDavid Howells set_bit(AFS_SERVER_FL_NO_RM2, &call->op->server->flags);
661e49c7b2fSDavid Howells call->op->flags |= AFS_OPERATION_DOWNGRADE;
662e49c7b2fSDavid Howells }
663e49c7b2fSDavid Howells }
664e49c7b2fSDavid Howells
66530062bd1SDavid Howells /*
66630062bd1SDavid Howells * YFS.RemoveFile2 operation type.
66730062bd1SDavid Howells */
66830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveFile2 = {
66930062bd1SDavid Howells .name = "YFS.RemoveFile2",
67030062bd1SDavid Howells .op = yfs_FS_RemoveFile2,
67130062bd1SDavid Howells .deliver = yfs_deliver_fs_remove_file2,
672e49c7b2fSDavid Howells .done = yfs_done_fs_remove_file2,
67330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
67430062bd1SDavid Howells };
67530062bd1SDavid Howells
67630062bd1SDavid Howells /*
67730062bd1SDavid Howells * Remove a file and retrieve new file status.
67830062bd1SDavid Howells */
yfs_fs_remove_file2(struct afs_operation * op)679e49c7b2fSDavid Howells void yfs_fs_remove_file2(struct afs_operation *op)
68030062bd1SDavid Howells {
681e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
682e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
68330062bd1SDavid Howells struct afs_call *call;
68430062bd1SDavid Howells __be32 *bp;
68530062bd1SDavid Howells
68630062bd1SDavid Howells _enter("");
68730062bd1SDavid Howells
688e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile2,
68930062bd1SDavid Howells sizeof(__be32) +
69030062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
69130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
692e49c7b2fSDavid Howells xdr_strlen(name->len),
69330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
69430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
69530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
69630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
69730062bd1SDavid Howells if (!call)
698e49c7b2fSDavid Howells return afs_op_nomem(op);
69930062bd1SDavid Howells
70030062bd1SDavid Howells /* marshall the parameters */
70130062bd1SDavid Howells bp = call->request;
70230062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEFILE2);
70330062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
704e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
705e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
70630062bd1SDavid Howells yfs_check_req(call, bp);
70730062bd1SDavid Howells
708e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
709e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
71030062bd1SDavid Howells }
71130062bd1SDavid Howells
71230062bd1SDavid Howells /*
71330062bd1SDavid Howells * Deliver reply data to a YFS.RemoveFile or YFS.RemoveDir operation.
71430062bd1SDavid Howells */
yfs_deliver_fs_remove(struct afs_call * call)71530062bd1SDavid Howells static int yfs_deliver_fs_remove(struct afs_call *call)
71630062bd1SDavid Howells {
717e49c7b2fSDavid Howells struct afs_operation *op = call->op;
718e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
71930062bd1SDavid Howells const __be32 *bp;
72030062bd1SDavid Howells int ret;
72130062bd1SDavid Howells
72230062bd1SDavid Howells _enter("{%u}", call->unmarshall);
72330062bd1SDavid Howells
72430062bd1SDavid Howells ret = afs_transfer_reply(call);
72530062bd1SDavid Howells if (ret < 0)
72630062bd1SDavid Howells return ret;
72730062bd1SDavid Howells
72830062bd1SDavid Howells bp = call->buffer;
729e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
730e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
73130062bd1SDavid Howells return 0;
73230062bd1SDavid Howells }
73330062bd1SDavid Howells
73430062bd1SDavid Howells /*
73530062bd1SDavid Howells * FS.RemoveDir and FS.RemoveFile operation types.
73630062bd1SDavid Howells */
73730062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveFile = {
73830062bd1SDavid Howells .name = "YFS.RemoveFile",
73930062bd1SDavid Howells .op = yfs_FS_RemoveFile,
74030062bd1SDavid Howells .deliver = yfs_deliver_fs_remove,
74130062bd1SDavid Howells .destructor = afs_flat_call_destructor,
74230062bd1SDavid Howells };
74330062bd1SDavid Howells
744e49c7b2fSDavid Howells /*
745e49c7b2fSDavid Howells * Remove a file.
746e49c7b2fSDavid Howells */
yfs_fs_remove_file(struct afs_operation * op)747e49c7b2fSDavid Howells void yfs_fs_remove_file(struct afs_operation *op)
748e49c7b2fSDavid Howells {
749e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
750e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
751e49c7b2fSDavid Howells struct afs_call *call;
752e49c7b2fSDavid Howells __be32 *bp;
753e49c7b2fSDavid Howells
754e49c7b2fSDavid Howells _enter("");
755e49c7b2fSDavid Howells
75620325960SDavid Howells if (!test_bit(AFS_SERVER_FL_NO_RM2, &op->server->flags))
757e49c7b2fSDavid Howells return yfs_fs_remove_file2(op);
758e49c7b2fSDavid Howells
759e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile,
760e49c7b2fSDavid Howells sizeof(__be32) +
761e49c7b2fSDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
762e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFid) +
763e49c7b2fSDavid Howells xdr_strlen(name->len),
764e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
765e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
766e49c7b2fSDavid Howells if (!call)
767e49c7b2fSDavid Howells return afs_op_nomem(op);
768e49c7b2fSDavid Howells
769e49c7b2fSDavid Howells /* marshall the parameters */
770e49c7b2fSDavid Howells bp = call->request;
771e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEFILE);
772e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
773e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
774e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
775e49c7b2fSDavid Howells yfs_check_req(call, bp);
776e49c7b2fSDavid Howells
777e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
778e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
779e49c7b2fSDavid Howells }
780e49c7b2fSDavid Howells
78130062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveDir = {
78230062bd1SDavid Howells .name = "YFS.RemoveDir",
78330062bd1SDavid Howells .op = yfs_FS_RemoveDir,
78430062bd1SDavid Howells .deliver = yfs_deliver_fs_remove,
78530062bd1SDavid Howells .destructor = afs_flat_call_destructor,
78630062bd1SDavid Howells };
78730062bd1SDavid Howells
78830062bd1SDavid Howells /*
789e49c7b2fSDavid Howells * Remove a directory.
79030062bd1SDavid Howells */
yfs_fs_remove_dir(struct afs_operation * op)791e49c7b2fSDavid Howells void yfs_fs_remove_dir(struct afs_operation *op)
79230062bd1SDavid Howells {
793e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
794e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
79530062bd1SDavid Howells struct afs_call *call;
79630062bd1SDavid Howells __be32 *bp;
79730062bd1SDavid Howells
79830062bd1SDavid Howells _enter("");
79930062bd1SDavid Howells
800e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveDir,
80130062bd1SDavid Howells sizeof(__be32) +
80230062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
80330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
804e49c7b2fSDavid Howells xdr_strlen(name->len),
80530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
80630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
80730062bd1SDavid Howells if (!call)
808e49c7b2fSDavid Howells return afs_op_nomem(op);
80930062bd1SDavid Howells
81030062bd1SDavid Howells /* marshall the parameters */
81130062bd1SDavid Howells bp = call->request;
812e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEDIR);
81330062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
814e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
815e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
81630062bd1SDavid Howells yfs_check_req(call, bp);
81730062bd1SDavid Howells
818e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
819e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
82030062bd1SDavid Howells }
82130062bd1SDavid Howells
82230062bd1SDavid Howells /*
82330062bd1SDavid Howells * Deliver reply data to a YFS.Link operation.
82430062bd1SDavid Howells */
yfs_deliver_fs_link(struct afs_call * call)82530062bd1SDavid Howells static int yfs_deliver_fs_link(struct afs_call *call)
82630062bd1SDavid Howells {
827e49c7b2fSDavid Howells struct afs_operation *op = call->op;
828e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
829e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
83030062bd1SDavid Howells const __be32 *bp;
83130062bd1SDavid Howells int ret;
83230062bd1SDavid Howells
83330062bd1SDavid Howells _enter("{%u}", call->unmarshall);
83430062bd1SDavid Howells
83530062bd1SDavid Howells ret = afs_transfer_reply(call);
83630062bd1SDavid Howells if (ret < 0)
83730062bd1SDavid Howells return ret;
83830062bd1SDavid Howells
83930062bd1SDavid Howells bp = call->buffer;
840e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
841e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
842e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
84330062bd1SDavid Howells _leave(" = 0 [done]");
84430062bd1SDavid Howells return 0;
84530062bd1SDavid Howells }
84630062bd1SDavid Howells
84730062bd1SDavid Howells /*
84830062bd1SDavid Howells * YFS.Link operation type.
84930062bd1SDavid Howells */
85030062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSLink = {
85130062bd1SDavid Howells .name = "YFS.Link",
85230062bd1SDavid Howells .op = yfs_FS_Link,
85330062bd1SDavid Howells .deliver = yfs_deliver_fs_link,
85430062bd1SDavid Howells .destructor = afs_flat_call_destructor,
85530062bd1SDavid Howells };
85630062bd1SDavid Howells
85730062bd1SDavid Howells /*
85830062bd1SDavid Howells * Make a hard link.
85930062bd1SDavid Howells */
yfs_fs_link(struct afs_operation * op)860e49c7b2fSDavid Howells void yfs_fs_link(struct afs_operation *op)
86130062bd1SDavid Howells {
862e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
863e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
864e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
86530062bd1SDavid Howells struct afs_call *call;
86630062bd1SDavid Howells __be32 *bp;
86730062bd1SDavid Howells
86830062bd1SDavid Howells _enter("");
86930062bd1SDavid Howells
870e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSLink,
87130062bd1SDavid Howells sizeof(__be32) +
87230062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
87330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
874e49c7b2fSDavid Howells xdr_strlen(name->len) +
87530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
87630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
87730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
87830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
87930062bd1SDavid Howells if (!call)
880e49c7b2fSDavid Howells return afs_op_nomem(op);
88130062bd1SDavid Howells
88230062bd1SDavid Howells /* marshall the parameters */
88330062bd1SDavid Howells bp = call->request;
88430062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSLINK);
88530062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
886e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
887e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
888e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
88930062bd1SDavid Howells yfs_check_req(call, bp);
89030062bd1SDavid Howells
891e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &vp->fid, name);
892e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
89330062bd1SDavid Howells }
89430062bd1SDavid Howells
89530062bd1SDavid Howells /*
89630062bd1SDavid Howells * Deliver reply data to a YFS.Symlink operation.
89730062bd1SDavid Howells */
yfs_deliver_fs_symlink(struct afs_call * call)89830062bd1SDavid Howells static int yfs_deliver_fs_symlink(struct afs_call *call)
89930062bd1SDavid Howells {
900e49c7b2fSDavid Howells struct afs_operation *op = call->op;
901e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
902e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
90330062bd1SDavid Howells const __be32 *bp;
90430062bd1SDavid Howells int ret;
90530062bd1SDavid Howells
90630062bd1SDavid Howells _enter("{%u}", call->unmarshall);
90730062bd1SDavid Howells
90830062bd1SDavid Howells ret = afs_transfer_reply(call);
90930062bd1SDavid Howells if (ret < 0)
91030062bd1SDavid Howells return ret;
91130062bd1SDavid Howells
91230062bd1SDavid Howells /* unmarshall the reply once we've received all of it */
91330062bd1SDavid Howells bp = call->buffer;
914e49c7b2fSDavid Howells xdr_decode_YFSFid(&bp, &vp->fid);
915e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
916e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
917e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
91830062bd1SDavid Howells
91930062bd1SDavid Howells _leave(" = 0 [done]");
92030062bd1SDavid Howells return 0;
92130062bd1SDavid Howells }
92230062bd1SDavid Howells
92330062bd1SDavid Howells /*
92430062bd1SDavid Howells * YFS.Symlink operation type
92530062bd1SDavid Howells */
92630062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSSymlink = {
92730062bd1SDavid Howells .name = "YFS.Symlink",
92830062bd1SDavid Howells .op = yfs_FS_Symlink,
92930062bd1SDavid Howells .deliver = yfs_deliver_fs_symlink,
93030062bd1SDavid Howells .destructor = afs_flat_call_destructor,
93130062bd1SDavid Howells };
93230062bd1SDavid Howells
93330062bd1SDavid Howells /*
93430062bd1SDavid Howells * Create a symbolic link.
93530062bd1SDavid Howells */
yfs_fs_symlink(struct afs_operation * op)936e49c7b2fSDavid Howells void yfs_fs_symlink(struct afs_operation *op)
93730062bd1SDavid Howells {
938e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
939e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
94030062bd1SDavid Howells struct afs_call *call;
941e49c7b2fSDavid Howells size_t contents_sz;
94252af7105SMarc Dionne mode_t mode = 0777;
94330062bd1SDavid Howells __be32 *bp;
94430062bd1SDavid Howells
94530062bd1SDavid Howells _enter("");
94630062bd1SDavid Howells
947e49c7b2fSDavid Howells contents_sz = strlen(op->create.symlink);
948e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSSymlink,
94930062bd1SDavid Howells sizeof(__be32) +
95030062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
95130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
952e49c7b2fSDavid Howells xdr_strlen(name->len) +
95330062bd1SDavid Howells xdr_strlen(contents_sz) +
95430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus),
95530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
95630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
95730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
95830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
95930062bd1SDavid Howells if (!call)
960e49c7b2fSDavid Howells return afs_op_nomem(op);
96130062bd1SDavid Howells
96230062bd1SDavid Howells /* marshall the parameters */
96330062bd1SDavid Howells bp = call->request;
96430062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSYMLINK);
96530062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
966e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
967e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
968e49c7b2fSDavid Howells bp = xdr_encode_string(bp, op->create.symlink, contents_sz);
96952af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, &mode, &op->mtime);
97030062bd1SDavid Howells yfs_check_req(call, bp);
97130062bd1SDavid Howells
972e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
973e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
97430062bd1SDavid Howells }
97530062bd1SDavid Howells
97630062bd1SDavid Howells /*
97730062bd1SDavid Howells * Deliver reply data to a YFS.Rename operation.
97830062bd1SDavid Howells */
yfs_deliver_fs_rename(struct afs_call * call)97930062bd1SDavid Howells static int yfs_deliver_fs_rename(struct afs_call *call)
98030062bd1SDavid Howells {
981e49c7b2fSDavid Howells struct afs_operation *op = call->op;
982e49c7b2fSDavid Howells struct afs_vnode_param *orig_dvp = &op->file[0];
983e49c7b2fSDavid Howells struct afs_vnode_param *new_dvp = &op->file[1];
98430062bd1SDavid Howells const __be32 *bp;
98530062bd1SDavid Howells int ret;
98630062bd1SDavid Howells
98730062bd1SDavid Howells _enter("{%u}", call->unmarshall);
98830062bd1SDavid Howells
98930062bd1SDavid Howells ret = afs_transfer_reply(call);
99030062bd1SDavid Howells if (ret < 0)
99130062bd1SDavid Howells return ret;
99230062bd1SDavid Howells
99330062bd1SDavid Howells bp = call->buffer;
99438355eecSDavid Howells /* If the two dirs are the same, we have two copies of the same status
99538355eecSDavid Howells * report, so we just decode it twice.
99638355eecSDavid Howells */
997e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &orig_dvp->scb);
998e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &new_dvp->scb);
999e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
100030062bd1SDavid Howells _leave(" = 0 [done]");
100130062bd1SDavid Howells return 0;
100230062bd1SDavid Howells }
100330062bd1SDavid Howells
100430062bd1SDavid Howells /*
100530062bd1SDavid Howells * YFS.Rename operation type
100630062bd1SDavid Howells */
100730062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRename = {
100830062bd1SDavid Howells .name = "FS.Rename",
100930062bd1SDavid Howells .op = yfs_FS_Rename,
101030062bd1SDavid Howells .deliver = yfs_deliver_fs_rename,
101130062bd1SDavid Howells .destructor = afs_flat_call_destructor,
101230062bd1SDavid Howells };
101330062bd1SDavid Howells
101430062bd1SDavid Howells /*
101530062bd1SDavid Howells * Rename a file or directory.
101630062bd1SDavid Howells */
yfs_fs_rename(struct afs_operation * op)1017e49c7b2fSDavid Howells void yfs_fs_rename(struct afs_operation *op)
101830062bd1SDavid Howells {
1019e49c7b2fSDavid Howells struct afs_vnode_param *orig_dvp = &op->file[0];
1020e49c7b2fSDavid Howells struct afs_vnode_param *new_dvp = &op->file[1];
1021e49c7b2fSDavid Howells const struct qstr *orig_name = &op->dentry->d_name;
1022e49c7b2fSDavid Howells const struct qstr *new_name = &op->dentry_2->d_name;
102330062bd1SDavid Howells struct afs_call *call;
102430062bd1SDavid Howells __be32 *bp;
102530062bd1SDavid Howells
102630062bd1SDavid Howells _enter("");
102730062bd1SDavid Howells
1028e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename,
102930062bd1SDavid Howells sizeof(__be32) +
103030062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
103130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
1032e49c7b2fSDavid Howells xdr_strlen(orig_name->len) +
103330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
1034e49c7b2fSDavid Howells xdr_strlen(new_name->len),
103530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
103630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
103730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
103830062bd1SDavid Howells if (!call)
1039e49c7b2fSDavid Howells return afs_op_nomem(op);
104030062bd1SDavid Howells
104130062bd1SDavid Howells /* marshall the parameters */
104230062bd1SDavid Howells bp = call->request;
104330062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSRENAME);
104430062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1045e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &orig_dvp->fid);
1046e49c7b2fSDavid Howells bp = xdr_encode_name(bp, orig_name);
1047e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &new_dvp->fid);
1048e49c7b2fSDavid Howells bp = xdr_encode_name(bp, new_name);
104930062bd1SDavid Howells yfs_check_req(call, bp);
105030062bd1SDavid Howells
1051e49c7b2fSDavid Howells trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name);
1052e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
105330062bd1SDavid Howells }
105430062bd1SDavid Howells
105530062bd1SDavid Howells /*
105630062bd1SDavid Howells * YFS.StoreData64 operation type.
105730062bd1SDavid Howells */
105830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreData64 = {
105930062bd1SDavid Howells .name = "YFS.StoreData64",
106030062bd1SDavid Howells .op = yfs_FS_StoreData64,
1061a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync,
106230062bd1SDavid Howells .destructor = afs_flat_call_destructor,
106330062bd1SDavid Howells };
106430062bd1SDavid Howells
106530062bd1SDavid Howells /*
106630062bd1SDavid Howells * Store a set of pages to a large file.
106730062bd1SDavid Howells */
yfs_fs_store_data(struct afs_operation * op)1068e49c7b2fSDavid Howells void yfs_fs_store_data(struct afs_operation *op)
106930062bd1SDavid Howells {
1070e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
107130062bd1SDavid Howells struct afs_call *call;
107230062bd1SDavid Howells __be32 *bp;
107330062bd1SDavid Howells
107430062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1075e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
107630062bd1SDavid Howells
107730062bd1SDavid Howells _debug("size %llx, at %llx, i_size %llx",
1078bd80d8a8SDavid Howells (unsigned long long)op->store.size,
1079bd80d8a8SDavid Howells (unsigned long long)op->store.pos,
1080bd80d8a8SDavid Howells (unsigned long long)op->store.i_size);
108130062bd1SDavid Howells
1082e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64,
108330062bd1SDavid Howells sizeof(__be32) +
108430062bd1SDavid Howells sizeof(__be32) +
108530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
108630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) +
108730062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 3,
108830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
108930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
109030062bd1SDavid Howells if (!call)
1091e49c7b2fSDavid Howells return afs_op_nomem(op);
109230062bd1SDavid Howells
1093bd80d8a8SDavid Howells call->write_iter = op->store.write_iter;
109430062bd1SDavid Howells
109530062bd1SDavid Howells /* marshall the parameters */
109630062bd1SDavid Howells bp = call->request;
109730062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREDATA64);
109830062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1099e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
110052af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, NULL, &op->mtime);
1101bd80d8a8SDavid Howells bp = xdr_encode_u64(bp, op->store.pos);
1102bd80d8a8SDavid Howells bp = xdr_encode_u64(bp, op->store.size);
1103bd80d8a8SDavid Howells bp = xdr_encode_u64(bp, op->store.i_size);
110430062bd1SDavid Howells yfs_check_req(call, bp);
110530062bd1SDavid Howells
1106e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1107e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
110830062bd1SDavid Howells }
110930062bd1SDavid Howells
111030062bd1SDavid Howells /*
111130062bd1SDavid Howells * YFS.StoreStatus operation type
111230062bd1SDavid Howells */
111330062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreStatus = {
111430062bd1SDavid Howells .name = "YFS.StoreStatus",
111530062bd1SDavid Howells .op = yfs_FS_StoreStatus,
1116a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync,
111730062bd1SDavid Howells .destructor = afs_flat_call_destructor,
111830062bd1SDavid Howells };
111930062bd1SDavid Howells
112030062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = {
112130062bd1SDavid Howells .name = "YFS.StoreData64",
112230062bd1SDavid Howells .op = yfs_FS_StoreData64,
1123a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync,
112430062bd1SDavid Howells .destructor = afs_flat_call_destructor,
112530062bd1SDavid Howells };
112630062bd1SDavid Howells
112730062bd1SDavid Howells /*
112830062bd1SDavid Howells * Set the attributes on a file, using YFS.StoreData64 rather than
112930062bd1SDavid Howells * YFS.StoreStatus so as to alter the file size also.
113030062bd1SDavid Howells */
yfs_fs_setattr_size(struct afs_operation * op)1131e49c7b2fSDavid Howells static void yfs_fs_setattr_size(struct afs_operation *op)
113230062bd1SDavid Howells {
1133e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
113430062bd1SDavid Howells struct afs_call *call;
1135e49c7b2fSDavid Howells struct iattr *attr = op->setattr.attr;
113630062bd1SDavid Howells __be32 *bp;
113730062bd1SDavid Howells
113830062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1139e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
114030062bd1SDavid Howells
1141e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64_as_Status,
114230062bd1SDavid Howells sizeof(__be32) * 2 +
114330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
114430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) +
114530062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 3,
114630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
114730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
114830062bd1SDavid Howells if (!call)
1149e49c7b2fSDavid Howells return afs_op_nomem(op);
115030062bd1SDavid Howells
115130062bd1SDavid Howells /* marshall the parameters */
115230062bd1SDavid Howells bp = call->request;
115330062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREDATA64);
115430062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1155e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
115630062bd1SDavid Howells bp = xdr_encode_YFS_StoreStatus(bp, attr);
11578c7ae38dSDavid Howells bp = xdr_encode_u64(bp, attr->ia_size); /* position of start of write */
115830062bd1SDavid Howells bp = xdr_encode_u64(bp, 0); /* size of write */
115930062bd1SDavid Howells bp = xdr_encode_u64(bp, attr->ia_size); /* new file length */
116030062bd1SDavid Howells yfs_check_req(call, bp);
116130062bd1SDavid Howells
1162e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1163e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
116430062bd1SDavid Howells }
116530062bd1SDavid Howells
116630062bd1SDavid Howells /*
116730062bd1SDavid Howells * Set the attributes on a file, using YFS.StoreData64 if there's a change in
116830062bd1SDavid Howells * file size, and YFS.StoreStatus otherwise.
116930062bd1SDavid Howells */
yfs_fs_setattr(struct afs_operation * op)1170e49c7b2fSDavid Howells void yfs_fs_setattr(struct afs_operation *op)
117130062bd1SDavid Howells {
1172e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
117330062bd1SDavid Howells struct afs_call *call;
1174e49c7b2fSDavid Howells struct iattr *attr = op->setattr.attr;
117530062bd1SDavid Howells __be32 *bp;
117630062bd1SDavid Howells
117730062bd1SDavid Howells if (attr->ia_valid & ATTR_SIZE)
1178e49c7b2fSDavid Howells return yfs_fs_setattr_size(op);
117930062bd1SDavid Howells
118030062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1181e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
118230062bd1SDavid Howells
1183e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreStatus,
118430062bd1SDavid Howells sizeof(__be32) * 2 +
118530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
118630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus),
118730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
118830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
118930062bd1SDavid Howells if (!call)
1190e49c7b2fSDavid Howells return afs_op_nomem(op);
119130062bd1SDavid Howells
119230062bd1SDavid Howells /* marshall the parameters */
119330062bd1SDavid Howells bp = call->request;
119430062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTORESTATUS);
119530062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1196e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
119730062bd1SDavid Howells bp = xdr_encode_YFS_StoreStatus(bp, attr);
119830062bd1SDavid Howells yfs_check_req(call, bp);
119930062bd1SDavid Howells
1200e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1201e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
120230062bd1SDavid Howells }
120330062bd1SDavid Howells
120430062bd1SDavid Howells /*
120530062bd1SDavid Howells * Deliver reply data to a YFS.GetVolumeStatus operation.
120630062bd1SDavid Howells */
yfs_deliver_fs_get_volume_status(struct afs_call * call)120730062bd1SDavid Howells static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
120830062bd1SDavid Howells {
1209e49c7b2fSDavid Howells struct afs_operation *op = call->op;
121030062bd1SDavid Howells const __be32 *bp;
121130062bd1SDavid Howells char *p;
121230062bd1SDavid Howells u32 size;
121330062bd1SDavid Howells int ret;
121430062bd1SDavid Howells
121530062bd1SDavid Howells _enter("{%u}", call->unmarshall);
121630062bd1SDavid Howells
121730062bd1SDavid Howells switch (call->unmarshall) {
121830062bd1SDavid Howells case 0:
121930062bd1SDavid Howells call->unmarshall++;
122030062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus));
1221df561f66SGustavo A. R. Silva fallthrough;
122230062bd1SDavid Howells
122335a3a90cSGustavo A. R. Silva /* extract the returned status record */
122430062bd1SDavid Howells case 1:
122530062bd1SDavid Howells _debug("extract status");
122630062bd1SDavid Howells ret = afs_extract_data(call, true);
122730062bd1SDavid Howells if (ret < 0)
122830062bd1SDavid Howells return ret;
122930062bd1SDavid Howells
123030062bd1SDavid Howells bp = call->buffer;
1231e49c7b2fSDavid Howells xdr_decode_YFSFetchVolumeStatus(&bp, &op->volstatus.vs);
123230062bd1SDavid Howells call->unmarshall++;
123330062bd1SDavid Howells afs_extract_to_tmp(call);
1234df561f66SGustavo A. R. Silva fallthrough;
123530062bd1SDavid Howells
123635a3a90cSGustavo A. R. Silva /* extract the volume name length */
123730062bd1SDavid Howells case 2:
123830062bd1SDavid Howells ret = afs_extract_data(call, true);
123930062bd1SDavid Howells if (ret < 0)
124030062bd1SDavid Howells return ret;
124130062bd1SDavid Howells
124230062bd1SDavid Howells call->count = ntohl(call->tmp);
124330062bd1SDavid Howells _debug("volname length: %u", call->count);
124430062bd1SDavid Howells if (call->count >= AFSNAMEMAX)
12457126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_volname_len);
124630062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */
1247ffba718eSDavid Howells afs_extract_to_buf(call, size);
124830062bd1SDavid Howells call->unmarshall++;
1249df561f66SGustavo A. R. Silva fallthrough;
125030062bd1SDavid Howells
125135a3a90cSGustavo A. R. Silva /* extract the volume name */
125230062bd1SDavid Howells case 3:
125330062bd1SDavid Howells _debug("extract volname");
125430062bd1SDavid Howells ret = afs_extract_data(call, true);
125530062bd1SDavid Howells if (ret < 0)
125630062bd1SDavid Howells return ret;
125730062bd1SDavid Howells
1258ffba718eSDavid Howells p = call->buffer;
125930062bd1SDavid Howells p[call->count] = 0;
126030062bd1SDavid Howells _debug("volname '%s'", p);
126130062bd1SDavid Howells afs_extract_to_tmp(call);
126230062bd1SDavid Howells call->unmarshall++;
1263df561f66SGustavo A. R. Silva fallthrough;
126430062bd1SDavid Howells
126535a3a90cSGustavo A. R. Silva /* extract the offline message length */
126630062bd1SDavid Howells case 4:
126730062bd1SDavid Howells ret = afs_extract_data(call, true);
126830062bd1SDavid Howells if (ret < 0)
126930062bd1SDavid Howells return ret;
127030062bd1SDavid Howells
127130062bd1SDavid Howells call->count = ntohl(call->tmp);
127230062bd1SDavid Howells _debug("offline msg length: %u", call->count);
127330062bd1SDavid Howells if (call->count >= AFSNAMEMAX)
12747126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_offline_msg_len);
127530062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */
1276ffba718eSDavid Howells afs_extract_to_buf(call, size);
127730062bd1SDavid Howells call->unmarshall++;
1278df561f66SGustavo A. R. Silva fallthrough;
127930062bd1SDavid Howells
128035a3a90cSGustavo A. R. Silva /* extract the offline message */
128130062bd1SDavid Howells case 5:
128230062bd1SDavid Howells _debug("extract offline");
128330062bd1SDavid Howells ret = afs_extract_data(call, true);
128430062bd1SDavid Howells if (ret < 0)
128530062bd1SDavid Howells return ret;
128630062bd1SDavid Howells
1287ffba718eSDavid Howells p = call->buffer;
128830062bd1SDavid Howells p[call->count] = 0;
128930062bd1SDavid Howells _debug("offline '%s'", p);
129030062bd1SDavid Howells
129130062bd1SDavid Howells afs_extract_to_tmp(call);
129230062bd1SDavid Howells call->unmarshall++;
1293df561f66SGustavo A. R. Silva fallthrough;
129430062bd1SDavid Howells
129535a3a90cSGustavo A. R. Silva /* extract the message of the day length */
129630062bd1SDavid Howells case 6:
129730062bd1SDavid Howells ret = afs_extract_data(call, true);
129830062bd1SDavid Howells if (ret < 0)
129930062bd1SDavid Howells return ret;
130030062bd1SDavid Howells
130130062bd1SDavid Howells call->count = ntohl(call->tmp);
130230062bd1SDavid Howells _debug("motd length: %u", call->count);
130330062bd1SDavid Howells if (call->count >= AFSNAMEMAX)
13047126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_motd_len);
130530062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */
1306ffba718eSDavid Howells afs_extract_to_buf(call, size);
130730062bd1SDavid Howells call->unmarshall++;
1308df561f66SGustavo A. R. Silva fallthrough;
130930062bd1SDavid Howells
131035a3a90cSGustavo A. R. Silva /* extract the message of the day */
131130062bd1SDavid Howells case 7:
131230062bd1SDavid Howells _debug("extract motd");
131330062bd1SDavid Howells ret = afs_extract_data(call, false);
131430062bd1SDavid Howells if (ret < 0)
131530062bd1SDavid Howells return ret;
131630062bd1SDavid Howells
1317ffba718eSDavid Howells p = call->buffer;
131830062bd1SDavid Howells p[call->count] = 0;
131930062bd1SDavid Howells _debug("motd '%s'", p);
132030062bd1SDavid Howells
132130062bd1SDavid Howells call->unmarshall++;
1322df561f66SGustavo A. R. Silva fallthrough;
132335a3a90cSGustavo A. R. Silva
132430062bd1SDavid Howells case 8:
132530062bd1SDavid Howells break;
132630062bd1SDavid Howells }
132730062bd1SDavid Howells
132830062bd1SDavid Howells _leave(" = 0 [done]");
132930062bd1SDavid Howells return 0;
133030062bd1SDavid Howells }
133130062bd1SDavid Howells
133230062bd1SDavid Howells /*
133330062bd1SDavid Howells * YFS.GetVolumeStatus operation type
133430062bd1SDavid Howells */
133530062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSGetVolumeStatus = {
133630062bd1SDavid Howells .name = "YFS.GetVolumeStatus",
133730062bd1SDavid Howells .op = yfs_FS_GetVolumeStatus,
133830062bd1SDavid Howells .deliver = yfs_deliver_fs_get_volume_status,
1339ffba718eSDavid Howells .destructor = afs_flat_call_destructor,
134030062bd1SDavid Howells };
134130062bd1SDavid Howells
134230062bd1SDavid Howells /*
134330062bd1SDavid Howells * fetch the status of a volume
134430062bd1SDavid Howells */
yfs_fs_get_volume_status(struct afs_operation * op)1345e49c7b2fSDavid Howells void yfs_fs_get_volume_status(struct afs_operation *op)
134630062bd1SDavid Howells {
1347e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
134830062bd1SDavid Howells struct afs_call *call;
134930062bd1SDavid Howells __be32 *bp;
135030062bd1SDavid Howells
135130062bd1SDavid Howells _enter("");
135230062bd1SDavid Howells
1353e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSGetVolumeStatus,
135430062bd1SDavid Howells sizeof(__be32) * 2 +
135530062bd1SDavid Howells sizeof(struct yfs_xdr_u64),
1356ffba718eSDavid Howells max_t(size_t,
135730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchVolumeStatus) +
1358ffba718eSDavid Howells sizeof(__be32),
1359ffba718eSDavid Howells AFSOPAQUEMAX + 1));
1360ffba718eSDavid Howells if (!call)
1361e49c7b2fSDavid Howells return afs_op_nomem(op);
136230062bd1SDavid Howells
136330062bd1SDavid Howells /* marshall the parameters */
136430062bd1SDavid Howells bp = call->request;
136530062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSGETVOLUMESTATUS);
136630062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1367e49c7b2fSDavid Howells bp = xdr_encode_u64(bp, vp->fid.vid);
136830062bd1SDavid Howells yfs_check_req(call, bp);
136930062bd1SDavid Howells
1370e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1371e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
137230062bd1SDavid Howells }
137330062bd1SDavid Howells
137430062bd1SDavid Howells /*
137530062bd1SDavid Howells * YFS.SetLock operation type
137630062bd1SDavid Howells */
137730062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSSetLock = {
137830062bd1SDavid Howells .name = "YFS.SetLock",
137930062bd1SDavid Howells .op = yfs_FS_SetLock,
1380f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
1381a690f60aSDavid Howells .done = afs_lock_op_done,
138230062bd1SDavid Howells .destructor = afs_flat_call_destructor,
138330062bd1SDavid Howells };
138430062bd1SDavid Howells
138530062bd1SDavid Howells /*
138630062bd1SDavid Howells * YFS.ExtendLock operation type
138730062bd1SDavid Howells */
138830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSExtendLock = {
138930062bd1SDavid Howells .name = "YFS.ExtendLock",
139030062bd1SDavid Howells .op = yfs_FS_ExtendLock,
1391f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
1392a690f60aSDavid Howells .done = afs_lock_op_done,
139330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
139430062bd1SDavid Howells };
139530062bd1SDavid Howells
139630062bd1SDavid Howells /*
139730062bd1SDavid Howells * YFS.ReleaseLock operation type
139830062bd1SDavid Howells */
139930062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSReleaseLock = {
140030062bd1SDavid Howells .name = "YFS.ReleaseLock",
140130062bd1SDavid Howells .op = yfs_FS_ReleaseLock,
1402f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
140330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
140430062bd1SDavid Howells };
140530062bd1SDavid Howells
140630062bd1SDavid Howells /*
140730062bd1SDavid Howells * Set a lock on a file
140830062bd1SDavid Howells */
yfs_fs_set_lock(struct afs_operation * op)1409e49c7b2fSDavid Howells void yfs_fs_set_lock(struct afs_operation *op)
141030062bd1SDavid Howells {
1411e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
141230062bd1SDavid Howells struct afs_call *call;
141330062bd1SDavid Howells __be32 *bp;
141430062bd1SDavid Howells
141530062bd1SDavid Howells _enter("");
141630062bd1SDavid Howells
1417e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSSetLock,
141830062bd1SDavid Howells sizeof(__be32) * 2 +
141930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
142030062bd1SDavid Howells sizeof(__be32),
142130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
142230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
142330062bd1SDavid Howells if (!call)
1424e49c7b2fSDavid Howells return afs_op_nomem(op);
142530062bd1SDavid Howells
142630062bd1SDavid Howells /* marshall the parameters */
142730062bd1SDavid Howells bp = call->request;
142830062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSETLOCK);
142930062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1430e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1431e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, op->lock.type);
143230062bd1SDavid Howells yfs_check_req(call, bp);
143330062bd1SDavid Howells
1434e49c7b2fSDavid Howells trace_afs_make_fs_calli(call, &vp->fid, op->lock.type);
1435e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
143630062bd1SDavid Howells }
143730062bd1SDavid Howells
143830062bd1SDavid Howells /*
143930062bd1SDavid Howells * extend a lock on a file
144030062bd1SDavid Howells */
yfs_fs_extend_lock(struct afs_operation * op)1441e49c7b2fSDavid Howells void yfs_fs_extend_lock(struct afs_operation *op)
144230062bd1SDavid Howells {
1443e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
144430062bd1SDavid Howells struct afs_call *call;
144530062bd1SDavid Howells __be32 *bp;
144630062bd1SDavid Howells
144730062bd1SDavid Howells _enter("");
144830062bd1SDavid Howells
1449e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSExtendLock,
145030062bd1SDavid Howells sizeof(__be32) * 2 +
145130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
145230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
145330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
145430062bd1SDavid Howells if (!call)
1455e49c7b2fSDavid Howells return afs_op_nomem(op);
145630062bd1SDavid Howells
145730062bd1SDavid Howells /* marshall the parameters */
145830062bd1SDavid Howells bp = call->request;
145930062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSEXTENDLOCK);
146030062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1461e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
146230062bd1SDavid Howells yfs_check_req(call, bp);
146330062bd1SDavid Howells
1464e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1465e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
146630062bd1SDavid Howells }
146730062bd1SDavid Howells
146830062bd1SDavid Howells /*
146930062bd1SDavid Howells * release a lock on a file
147030062bd1SDavid Howells */
yfs_fs_release_lock(struct afs_operation * op)1471e49c7b2fSDavid Howells void yfs_fs_release_lock(struct afs_operation *op)
147230062bd1SDavid Howells {
1473e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
147430062bd1SDavid Howells struct afs_call *call;
147530062bd1SDavid Howells __be32 *bp;
147630062bd1SDavid Howells
147730062bd1SDavid Howells _enter("");
147830062bd1SDavid Howells
1479e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSReleaseLock,
148030062bd1SDavid Howells sizeof(__be32) * 2 +
148130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
148230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
148330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
148430062bd1SDavid Howells if (!call)
1485e49c7b2fSDavid Howells return afs_op_nomem(op);
148630062bd1SDavid Howells
148730062bd1SDavid Howells /* marshall the parameters */
148830062bd1SDavid Howells bp = call->request;
148930062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSRELEASELOCK);
149030062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1491e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
149230062bd1SDavid Howells yfs_check_req(call, bp);
149330062bd1SDavid Howells
1494e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1495e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
149630062bd1SDavid Howells }
149730062bd1SDavid Howells
149830062bd1SDavid Howells /*
14999bd87ec6SDavid Howells * Deliver a reply to YFS.FetchStatus
15009bd87ec6SDavid Howells */
yfs_deliver_fs_fetch_status(struct afs_call * call)15019bd87ec6SDavid Howells static int yfs_deliver_fs_fetch_status(struct afs_call *call)
15029bd87ec6SDavid Howells {
15039bd87ec6SDavid Howells struct afs_operation *op = call->op;
15049bd87ec6SDavid Howells struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
15059bd87ec6SDavid Howells const __be32 *bp;
15069bd87ec6SDavid Howells int ret;
15079bd87ec6SDavid Howells
15089bd87ec6SDavid Howells ret = afs_transfer_reply(call);
15099bd87ec6SDavid Howells if (ret < 0)
15109bd87ec6SDavid Howells return ret;
15119bd87ec6SDavid Howells
15129bd87ec6SDavid Howells /* unmarshall the reply once we've received all of it */
15139bd87ec6SDavid Howells bp = call->buffer;
15149bd87ec6SDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
15159bd87ec6SDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb);
15169bd87ec6SDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
15179bd87ec6SDavid Howells
15189bd87ec6SDavid Howells _leave(" = 0 [done]");
15199bd87ec6SDavid Howells return 0;
15209bd87ec6SDavid Howells }
15219bd87ec6SDavid Howells
15229bd87ec6SDavid Howells /*
152330062bd1SDavid Howells * YFS.FetchStatus operation type
152430062bd1SDavid Howells */
152530062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSFetchStatus = {
152630062bd1SDavid Howells .name = "YFS.FetchStatus",
152730062bd1SDavid Howells .op = yfs_FS_FetchStatus,
15289bd87ec6SDavid Howells .deliver = yfs_deliver_fs_fetch_status,
152930062bd1SDavid Howells .destructor = afs_flat_call_destructor,
153030062bd1SDavid Howells };
153130062bd1SDavid Howells
153230062bd1SDavid Howells /*
153330062bd1SDavid Howells * Fetch the status information for a fid without needing a vnode handle.
153430062bd1SDavid Howells */
yfs_fs_fetch_status(struct afs_operation * op)1535e49c7b2fSDavid Howells void yfs_fs_fetch_status(struct afs_operation *op)
153630062bd1SDavid Howells {
15379bd87ec6SDavid Howells struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
153830062bd1SDavid Howells struct afs_call *call;
153930062bd1SDavid Howells __be32 *bp;
154030062bd1SDavid Howells
154130062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1542e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
154330062bd1SDavid Howells
1544e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchStatus,
154530062bd1SDavid Howells sizeof(__be32) * 2 +
154630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
154730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
154830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
154930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1550e49c7b2fSDavid Howells if (!call)
1551e49c7b2fSDavid Howells return afs_op_nomem(op);
155230062bd1SDavid Howells
155330062bd1SDavid Howells /* marshall the parameters */
155430062bd1SDavid Howells bp = call->request;
155530062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSFETCHSTATUS);
155630062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1557e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
155830062bd1SDavid Howells yfs_check_req(call, bp);
155930062bd1SDavid Howells
1560e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1561e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
156230062bd1SDavid Howells }
156330062bd1SDavid Howells
156430062bd1SDavid Howells /*
156530062bd1SDavid Howells * Deliver reply data to an YFS.InlineBulkStatus call
156630062bd1SDavid Howells */
yfs_deliver_fs_inline_bulk_status(struct afs_call * call)156730062bd1SDavid Howells static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
156830062bd1SDavid Howells {
1569e49c7b2fSDavid Howells struct afs_operation *op = call->op;
157087182759SDavid Howells struct afs_status_cb *scb;
157130062bd1SDavid Howells const __be32 *bp;
157230062bd1SDavid Howells u32 tmp;
157330062bd1SDavid Howells int ret;
157430062bd1SDavid Howells
157530062bd1SDavid Howells _enter("{%u}", call->unmarshall);
157630062bd1SDavid Howells
157730062bd1SDavid Howells switch (call->unmarshall) {
157830062bd1SDavid Howells case 0:
157930062bd1SDavid Howells afs_extract_to_tmp(call);
158030062bd1SDavid Howells call->unmarshall++;
1581df561f66SGustavo A. R. Silva fallthrough;
158230062bd1SDavid Howells
158330062bd1SDavid Howells /* Extract the file status count and array in two steps */
158430062bd1SDavid Howells case 1:
158530062bd1SDavid Howells _debug("extract status count");
158630062bd1SDavid Howells ret = afs_extract_data(call, true);
158730062bd1SDavid Howells if (ret < 0)
158830062bd1SDavid Howells return ret;
158930062bd1SDavid Howells
159030062bd1SDavid Howells tmp = ntohl(call->tmp);
1591e49c7b2fSDavid Howells _debug("status count: %u/%u", tmp, op->nr_files);
1592e49c7b2fSDavid Howells if (tmp != op->nr_files)
15937126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_ibulkst_count);
159430062bd1SDavid Howells
159530062bd1SDavid Howells call->count = 0;
159630062bd1SDavid Howells call->unmarshall++;
159730062bd1SDavid Howells more_counts:
159830062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus));
1599df561f66SGustavo A. R. Silva fallthrough;
160035a3a90cSGustavo A. R. Silva
160130062bd1SDavid Howells case 2:
160230062bd1SDavid Howells _debug("extract status array %u", call->count);
160330062bd1SDavid Howells ret = afs_extract_data(call, true);
160430062bd1SDavid Howells if (ret < 0)
160530062bd1SDavid Howells return ret;
160630062bd1SDavid Howells
1607e49c7b2fSDavid Howells switch (call->count) {
1608e49c7b2fSDavid Howells case 0:
1609e49c7b2fSDavid Howells scb = &op->file[0].scb;
1610e49c7b2fSDavid Howells break;
1611e49c7b2fSDavid Howells case 1:
1612e49c7b2fSDavid Howells scb = &op->file[1].scb;
1613e49c7b2fSDavid Howells break;
1614e49c7b2fSDavid Howells default:
1615e49c7b2fSDavid Howells scb = &op->more_files[call->count - 2].scb;
1616e49c7b2fSDavid Howells break;
1617e49c7b2fSDavid Howells }
1618e49c7b2fSDavid Howells
161930062bd1SDavid Howells bp = call->buffer;
162038355eecSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, scb);
162130062bd1SDavid Howells
162230062bd1SDavid Howells call->count++;
1623e49c7b2fSDavid Howells if (call->count < op->nr_files)
162430062bd1SDavid Howells goto more_counts;
162530062bd1SDavid Howells
162630062bd1SDavid Howells call->count = 0;
162730062bd1SDavid Howells call->unmarshall++;
162830062bd1SDavid Howells afs_extract_to_tmp(call);
1629df561f66SGustavo A. R. Silva fallthrough;
163030062bd1SDavid Howells
163130062bd1SDavid Howells /* Extract the callback count and array in two steps */
163230062bd1SDavid Howells case 3:
163330062bd1SDavid Howells _debug("extract CB count");
163430062bd1SDavid Howells ret = afs_extract_data(call, true);
163530062bd1SDavid Howells if (ret < 0)
163630062bd1SDavid Howells return ret;
163730062bd1SDavid Howells
163830062bd1SDavid Howells tmp = ntohl(call->tmp);
163930062bd1SDavid Howells _debug("CB count: %u", tmp);
1640e49c7b2fSDavid Howells if (tmp != op->nr_files)
16417126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_ibulkst_cb_count);
164230062bd1SDavid Howells call->count = 0;
164330062bd1SDavid Howells call->unmarshall++;
164430062bd1SDavid Howells more_cbs:
164530062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack));
1646df561f66SGustavo A. R. Silva fallthrough;
164735a3a90cSGustavo A. R. Silva
164830062bd1SDavid Howells case 4:
164930062bd1SDavid Howells _debug("extract CB array");
165030062bd1SDavid Howells ret = afs_extract_data(call, true);
165130062bd1SDavid Howells if (ret < 0)
165230062bd1SDavid Howells return ret;
165330062bd1SDavid Howells
165430062bd1SDavid Howells _debug("unmarshall CB array");
1655e49c7b2fSDavid Howells switch (call->count) {
1656e49c7b2fSDavid Howells case 0:
1657e49c7b2fSDavid Howells scb = &op->file[0].scb;
1658e49c7b2fSDavid Howells break;
1659e49c7b2fSDavid Howells case 1:
1660e49c7b2fSDavid Howells scb = &op->file[1].scb;
1661e49c7b2fSDavid Howells break;
1662e49c7b2fSDavid Howells default:
1663e49c7b2fSDavid Howells scb = &op->more_files[call->count - 2].scb;
1664e49c7b2fSDavid Howells break;
1665e49c7b2fSDavid Howells }
1666e49c7b2fSDavid Howells
166730062bd1SDavid Howells bp = call->buffer;
1668a58823acSDavid Howells xdr_decode_YFSCallBack(&bp, call, scb);
166930062bd1SDavid Howells call->count++;
1670e49c7b2fSDavid Howells if (call->count < op->nr_files)
167130062bd1SDavid Howells goto more_cbs;
167230062bd1SDavid Howells
167330062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync));
167430062bd1SDavid Howells call->unmarshall++;
1675df561f66SGustavo A. R. Silva fallthrough;
167635a3a90cSGustavo A. R. Silva
167730062bd1SDavid Howells case 5:
167830062bd1SDavid Howells ret = afs_extract_data(call, false);
167930062bd1SDavid Howells if (ret < 0)
168030062bd1SDavid Howells return ret;
168130062bd1SDavid Howells
168230062bd1SDavid Howells bp = call->buffer;
1683e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
168430062bd1SDavid Howells
168530062bd1SDavid Howells call->unmarshall++;
1686df561f66SGustavo A. R. Silva fallthrough;
168735a3a90cSGustavo A. R. Silva
168830062bd1SDavid Howells case 6:
168930062bd1SDavid Howells break;
169030062bd1SDavid Howells }
169130062bd1SDavid Howells
169230062bd1SDavid Howells _leave(" = 0 [done]");
169330062bd1SDavid Howells return 0;
169430062bd1SDavid Howells }
169530062bd1SDavid Howells
169630062bd1SDavid Howells /*
169730062bd1SDavid Howells * FS.InlineBulkStatus operation type
169830062bd1SDavid Howells */
169930062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSInlineBulkStatus = {
170030062bd1SDavid Howells .name = "YFS.InlineBulkStatus",
170130062bd1SDavid Howells .op = yfs_FS_InlineBulkStatus,
170230062bd1SDavid Howells .deliver = yfs_deliver_fs_inline_bulk_status,
170330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
170430062bd1SDavid Howells };
170530062bd1SDavid Howells
170630062bd1SDavid Howells /*
170730062bd1SDavid Howells * Fetch the status information for up to 1024 files
170830062bd1SDavid Howells */
yfs_fs_inline_bulk_status(struct afs_operation * op)1709e49c7b2fSDavid Howells void yfs_fs_inline_bulk_status(struct afs_operation *op)
171030062bd1SDavid Howells {
1711e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
1712e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
171330062bd1SDavid Howells struct afs_call *call;
171430062bd1SDavid Howells __be32 *bp;
171530062bd1SDavid Howells int i;
171630062bd1SDavid Howells
171730062bd1SDavid Howells _enter(",%x,{%llx:%llu},%u",
1718e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode, op->nr_files);
171930062bd1SDavid Howells
1720e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSInlineBulkStatus,
172130062bd1SDavid Howells sizeof(__be32) +
172230062bd1SDavid Howells sizeof(__be32) +
172330062bd1SDavid Howells sizeof(__be32) +
1724e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFid) * op->nr_files,
172530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus));
1726e49c7b2fSDavid Howells if (!call)
1727e49c7b2fSDavid Howells return afs_op_nomem(op);
172830062bd1SDavid Howells
172930062bd1SDavid Howells /* marshall the parameters */
173030062bd1SDavid Howells bp = call->request;
173130062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSINLINEBULKSTATUS);
173230062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPCFlags */
1733e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, op->nr_files);
1734e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
1735e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1736e49c7b2fSDavid Howells for (i = 0; i < op->nr_files - 2; i++)
1737e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &op->more_files[i].fid);
173830062bd1SDavid Howells yfs_check_req(call, bp);
173930062bd1SDavid Howells
1740e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1741e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
174230062bd1SDavid Howells }
1743ae46578bSDavid Howells
1744ae46578bSDavid Howells /*
1745ae46578bSDavid Howells * Deliver reply data to an YFS.FetchOpaqueACL.
1746ae46578bSDavid Howells */
yfs_deliver_fs_fetch_opaque_acl(struct afs_call * call)1747ae46578bSDavid Howells static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
1748ae46578bSDavid Howells {
1749e49c7b2fSDavid Howells struct afs_operation *op = call->op;
1750e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
1751e49c7b2fSDavid Howells struct yfs_acl *yacl = op->yacl;
1752ae46578bSDavid Howells struct afs_acl *acl;
1753ae46578bSDavid Howells const __be32 *bp;
1754ae46578bSDavid Howells unsigned int size;
1755ae46578bSDavid Howells int ret;
1756ae46578bSDavid Howells
1757ae46578bSDavid Howells _enter("{%u}", call->unmarshall);
1758ae46578bSDavid Howells
1759ae46578bSDavid Howells switch (call->unmarshall) {
1760ae46578bSDavid Howells case 0:
1761ae46578bSDavid Howells afs_extract_to_tmp(call);
1762ae46578bSDavid Howells call->unmarshall++;
1763df561f66SGustavo A. R. Silva fallthrough;
1764ae46578bSDavid Howells
1765ae46578bSDavid Howells /* Extract the file ACL length */
1766ae46578bSDavid Howells case 1:
1767ae46578bSDavid Howells ret = afs_extract_data(call, true);
1768ae46578bSDavid Howells if (ret < 0)
1769ae46578bSDavid Howells return ret;
1770ae46578bSDavid Howells
1771ae46578bSDavid Howells size = call->count2 = ntohl(call->tmp);
1772ae46578bSDavid Howells size = round_up(size, 4);
1773ae46578bSDavid Howells
1774ae46578bSDavid Howells if (yacl->flags & YFS_ACL_WANT_ACL) {
1775ae46578bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
1776ae46578bSDavid Howells if (!acl)
1777ae46578bSDavid Howells return -ENOMEM;
1778ae46578bSDavid Howells yacl->acl = acl;
1779ae46578bSDavid Howells acl->size = call->count2;
1780ae46578bSDavid Howells afs_extract_begin(call, acl->data, size);
1781ae46578bSDavid Howells } else {
178223a28913SDavid Howells afs_extract_discard(call, size);
1783ae46578bSDavid Howells }
1784ae46578bSDavid Howells call->unmarshall++;
1785df561f66SGustavo A. R. Silva fallthrough;
1786ae46578bSDavid Howells
1787ae46578bSDavid Howells /* Extract the file ACL */
1788ae46578bSDavid Howells case 2:
1789ae46578bSDavid Howells ret = afs_extract_data(call, true);
1790ae46578bSDavid Howells if (ret < 0)
1791ae46578bSDavid Howells return ret;
1792ae46578bSDavid Howells
1793ae46578bSDavid Howells afs_extract_to_tmp(call);
1794ae46578bSDavid Howells call->unmarshall++;
1795df561f66SGustavo A. R. Silva fallthrough;
1796ae46578bSDavid Howells
1797ae46578bSDavid Howells /* Extract the volume ACL length */
1798ae46578bSDavid Howells case 3:
1799ae46578bSDavid Howells ret = afs_extract_data(call, true);
1800ae46578bSDavid Howells if (ret < 0)
1801ae46578bSDavid Howells return ret;
1802ae46578bSDavid Howells
1803ae46578bSDavid Howells size = call->count2 = ntohl(call->tmp);
1804ae46578bSDavid Howells size = round_up(size, 4);
1805ae46578bSDavid Howells
1806ae46578bSDavid Howells if (yacl->flags & YFS_ACL_WANT_VOL_ACL) {
1807ae46578bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
1808ae46578bSDavid Howells if (!acl)
1809ae46578bSDavid Howells return -ENOMEM;
1810ae46578bSDavid Howells yacl->vol_acl = acl;
1811ae46578bSDavid Howells acl->size = call->count2;
1812ae46578bSDavid Howells afs_extract_begin(call, acl->data, size);
1813ae46578bSDavid Howells } else {
181423a28913SDavid Howells afs_extract_discard(call, size);
1815ae46578bSDavid Howells }
1816ae46578bSDavid Howells call->unmarshall++;
1817df561f66SGustavo A. R. Silva fallthrough;
1818ae46578bSDavid Howells
1819ae46578bSDavid Howells /* Extract the volume ACL */
1820ae46578bSDavid Howells case 4:
1821ae46578bSDavid Howells ret = afs_extract_data(call, true);
1822ae46578bSDavid Howells if (ret < 0)
1823ae46578bSDavid Howells return ret;
1824ae46578bSDavid Howells
1825ae46578bSDavid Howells afs_extract_to_buf(call,
1826ae46578bSDavid Howells sizeof(__be32) * 2 +
1827ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
1828ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1829ae46578bSDavid Howells call->unmarshall++;
1830df561f66SGustavo A. R. Silva fallthrough;
1831ae46578bSDavid Howells
1832ae46578bSDavid Howells /* extract the metadata */
1833ae46578bSDavid Howells case 5:
1834ae46578bSDavid Howells ret = afs_extract_data(call, false);
1835ae46578bSDavid Howells if (ret < 0)
1836ae46578bSDavid Howells return ret;
1837ae46578bSDavid Howells
1838ae46578bSDavid Howells bp = call->buffer;
1839ae46578bSDavid Howells yacl->inherit_flag = ntohl(*bp++);
1840ae46578bSDavid Howells yacl->num_cleaned = ntohl(*bp++);
1841e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
1842e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
1843ae46578bSDavid Howells
1844ae46578bSDavid Howells call->unmarshall++;
1845df561f66SGustavo A. R. Silva fallthrough;
1846ae46578bSDavid Howells
1847ae46578bSDavid Howells case 6:
1848ae46578bSDavid Howells break;
1849ae46578bSDavid Howells }
1850ae46578bSDavid Howells
1851ae46578bSDavid Howells _leave(" = 0 [done]");
1852ae46578bSDavid Howells return 0;
1853ae46578bSDavid Howells }
1854ae46578bSDavid Howells
yfs_free_opaque_acl(struct yfs_acl * yacl)1855ae46578bSDavid Howells void yfs_free_opaque_acl(struct yfs_acl *yacl)
1856ae46578bSDavid Howells {
1857ae46578bSDavid Howells if (yacl) {
1858ae46578bSDavid Howells kfree(yacl->acl);
1859ae46578bSDavid Howells kfree(yacl->vol_acl);
1860ae46578bSDavid Howells kfree(yacl);
1861ae46578bSDavid Howells }
1862ae46578bSDavid Howells }
1863ae46578bSDavid Howells
1864ae46578bSDavid Howells /*
1865ae46578bSDavid Howells * YFS.FetchOpaqueACL operation type
1866ae46578bSDavid Howells */
1867ae46578bSDavid Howells static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = {
1868ae46578bSDavid Howells .name = "YFS.FetchOpaqueACL",
1869ae46578bSDavid Howells .op = yfs_FS_FetchOpaqueACL,
1870ae46578bSDavid Howells .deliver = yfs_deliver_fs_fetch_opaque_acl,
1871773e0c40SDavid Howells .destructor = afs_flat_call_destructor,
1872ae46578bSDavid Howells };
1873ae46578bSDavid Howells
1874ae46578bSDavid Howells /*
1875ae46578bSDavid Howells * Fetch the YFS advanced ACLs for a file.
1876ae46578bSDavid Howells */
yfs_fs_fetch_opaque_acl(struct afs_operation * op)1877e49c7b2fSDavid Howells void yfs_fs_fetch_opaque_acl(struct afs_operation *op)
1878ae46578bSDavid Howells {
1879e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
1880ae46578bSDavid Howells struct afs_call *call;
1881ae46578bSDavid Howells __be32 *bp;
1882ae46578bSDavid Howells
1883ae46578bSDavid Howells _enter(",%x,{%llx:%llu},,",
1884e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
1885ae46578bSDavid Howells
1886e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchOpaqueACL,
1887ae46578bSDavid Howells sizeof(__be32) * 2 +
1888ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFid),
1889ae46578bSDavid Howells sizeof(__be32) * 2 +
1890ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
1891ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1892e49c7b2fSDavid Howells if (!call)
1893e49c7b2fSDavid Howells return afs_op_nomem(op);
1894ae46578bSDavid Howells
1895ae46578bSDavid Howells /* marshall the parameters */
1896ae46578bSDavid Howells bp = call->request;
1897ae46578bSDavid Howells bp = xdr_encode_u32(bp, YFSFETCHOPAQUEACL);
1898ae46578bSDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1899e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1900ae46578bSDavid Howells yfs_check_req(call, bp);
1901ae46578bSDavid Howells
1902e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1903e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_KERNEL);
1904ae46578bSDavid Howells }
1905f5e45463SDavid Howells
1906f5e45463SDavid Howells /*
1907f5e45463SDavid Howells * YFS.StoreOpaqueACL2 operation type
1908f5e45463SDavid Howells */
1909f5e45463SDavid Howells static const struct afs_call_type yfs_RXYFSStoreOpaqueACL2 = {
1910f5e45463SDavid Howells .name = "YFS.StoreOpaqueACL2",
1911f5e45463SDavid Howells .op = yfs_FS_StoreOpaqueACL2,
1912f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
1913f5e45463SDavid Howells .destructor = afs_flat_call_destructor,
1914f5e45463SDavid Howells };
1915f5e45463SDavid Howells
1916f5e45463SDavid Howells /*
1917f5e45463SDavid Howells * Fetch the YFS ACL for a file.
1918f5e45463SDavid Howells */
yfs_fs_store_opaque_acl2(struct afs_operation * op)1919e49c7b2fSDavid Howells void yfs_fs_store_opaque_acl2(struct afs_operation *op)
1920f5e45463SDavid Howells {
1921e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
1922f5e45463SDavid Howells struct afs_call *call;
1923e49c7b2fSDavid Howells struct afs_acl *acl = op->acl;
1924f5e45463SDavid Howells size_t size;
1925f5e45463SDavid Howells __be32 *bp;
1926f5e45463SDavid Howells
1927f5e45463SDavid Howells _enter(",%x,{%llx:%llu},,",
1928e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
1929f5e45463SDavid Howells
1930f5e45463SDavid Howells size = round_up(acl->size, 4);
1931e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreOpaqueACL2,
1932f5e45463SDavid Howells sizeof(__be32) * 2 +
1933f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
1934f5e45463SDavid Howells sizeof(__be32) + size,
1935f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
1936f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1937e49c7b2fSDavid Howells if (!call)
1938e49c7b2fSDavid Howells return afs_op_nomem(op);
1939f5e45463SDavid Howells
1940f5e45463SDavid Howells /* marshall the parameters */
1941f5e45463SDavid Howells bp = call->request;
1942f5e45463SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREOPAQUEACL2);
1943f5e45463SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1944e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1945f5e45463SDavid Howells bp = xdr_encode_u32(bp, acl->size);
1946f5e45463SDavid Howells memcpy(bp, acl->data, acl->size);
1947f5e45463SDavid Howells if (acl->size != size)
1948f5e45463SDavid Howells memset((void *)bp + acl->size, 0, size - acl->size);
1949c80afa1dSDavid Howells bp += size / sizeof(__be32);
1950f5e45463SDavid Howells yfs_check_req(call, bp);
1951f5e45463SDavid Howells
1952e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1953e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_KERNEL);
195430062bd1SDavid Howells }
1955