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;
24816069e13SDavid Howells u64 creation, update;
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;
25416069e13SDavid Howells update = xdr_to_u64(x->vol_update_date);
25516069e13SDavid Howells do_div(update, 10 * 1000 * 1000);
25616069e13SDavid Howells volsync->update = update;
25730062bd1SDavid Howells }
25830062bd1SDavid Howells
25930062bd1SDavid Howells *_bp += xdr_size(x);
26030062bd1SDavid Howells }
26130062bd1SDavid Howells
26230062bd1SDavid Howells /*
26330062bd1SDavid Howells * Encode the requested attributes into a YFSStoreStatus block
26430062bd1SDavid Howells */
xdr_encode_YFS_StoreStatus(__be32 * bp,struct iattr * attr)26530062bd1SDavid Howells static __be32 *xdr_encode_YFS_StoreStatus(__be32 *bp, struct iattr *attr)
26630062bd1SDavid Howells {
26730062bd1SDavid Howells struct yfs_xdr_YFSStoreStatus *x = (void *)bp;
26830062bd1SDavid Howells s64 mtime = 0, owner = 0, group = 0;
26930062bd1SDavid Howells u32 mask = 0, mode = 0;
27030062bd1SDavid Howells
27130062bd1SDavid Howells mask = 0;
27230062bd1SDavid Howells if (attr->ia_valid & ATTR_MTIME) {
27330062bd1SDavid Howells mask |= AFS_SET_MTIME;
27430062bd1SDavid Howells mtime = linux_to_yfs_time(&attr->ia_mtime);
27530062bd1SDavid Howells }
27630062bd1SDavid Howells
27730062bd1SDavid Howells if (attr->ia_valid & ATTR_UID) {
27830062bd1SDavid Howells mask |= AFS_SET_OWNER;
27930062bd1SDavid Howells owner = from_kuid(&init_user_ns, attr->ia_uid);
28030062bd1SDavid Howells }
28130062bd1SDavid Howells
28230062bd1SDavid Howells if (attr->ia_valid & ATTR_GID) {
28330062bd1SDavid Howells mask |= AFS_SET_GROUP;
28430062bd1SDavid Howells group = from_kgid(&init_user_ns, attr->ia_gid);
28530062bd1SDavid Howells }
28630062bd1SDavid Howells
28730062bd1SDavid Howells if (attr->ia_valid & ATTR_MODE) {
28830062bd1SDavid Howells mask |= AFS_SET_MODE;
28930062bd1SDavid Howells mode = attr->ia_mode & S_IALLUGO;
29030062bd1SDavid Howells }
29130062bd1SDavid Howells
29230062bd1SDavid Howells x->mask = htonl(mask);
29330062bd1SDavid Howells x->mode = htonl(mode);
29430062bd1SDavid Howells x->mtime_client = u64_to_xdr(mtime);
29530062bd1SDavid Howells x->owner = u64_to_xdr(owner);
29630062bd1SDavid Howells x->group = u64_to_xdr(group);
29730062bd1SDavid Howells return bp + xdr_size(x);
29830062bd1SDavid Howells }
29930062bd1SDavid Howells
30030062bd1SDavid Howells /*
30130062bd1SDavid Howells * Decode a YFSFetchVolumeStatus block.
30230062bd1SDavid Howells */
xdr_decode_YFSFetchVolumeStatus(const __be32 ** _bp,struct afs_volume_status * vs)30330062bd1SDavid Howells static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp,
30430062bd1SDavid Howells struct afs_volume_status *vs)
30530062bd1SDavid Howells {
30630062bd1SDavid Howells const struct yfs_xdr_YFSFetchVolumeStatus *x = (const void *)*_bp;
30730062bd1SDavid Howells u32 flags;
30830062bd1SDavid Howells
30930062bd1SDavid Howells vs->vid = xdr_to_u64(x->vid);
31030062bd1SDavid Howells vs->parent_id = xdr_to_u64(x->parent_id);
31130062bd1SDavid Howells flags = ntohl(x->flags);
31230062bd1SDavid Howells vs->online = flags & yfs_FVSOnline;
31330062bd1SDavid Howells vs->in_service = flags & yfs_FVSInservice;
31430062bd1SDavid Howells vs->blessed = flags & yfs_FVSBlessed;
31530062bd1SDavid Howells vs->needs_salvage = flags & yfs_FVSNeedsSalvage;
31630062bd1SDavid Howells vs->type = ntohl(x->type);
31730062bd1SDavid Howells vs->min_quota = 0;
31830062bd1SDavid Howells vs->max_quota = xdr_to_u64(x->max_quota);
31930062bd1SDavid Howells vs->blocks_in_use = xdr_to_u64(x->blocks_in_use);
32030062bd1SDavid Howells vs->part_blocks_avail = xdr_to_u64(x->part_blocks_avail);
32130062bd1SDavid Howells vs->part_max_blocks = xdr_to_u64(x->part_max_blocks);
32230062bd1SDavid Howells vs->vol_copy_date = xdr_to_u64(x->vol_copy_date);
32330062bd1SDavid Howells vs->vol_backup_date = xdr_to_u64(x->vol_backup_date);
32430062bd1SDavid Howells *_bp += sizeof(*x) / sizeof(__be32);
32530062bd1SDavid Howells }
32630062bd1SDavid Howells
32730062bd1SDavid Howells /*
328a58823acSDavid Howells * Deliver reply data to operations that just return a file status and a volume
329a58823acSDavid Howells * sync record.
330a58823acSDavid Howells */
yfs_deliver_status_and_volsync(struct afs_call * call)331a58823acSDavid Howells static int yfs_deliver_status_and_volsync(struct afs_call *call)
332a58823acSDavid Howells {
333e49c7b2fSDavid Howells struct afs_operation *op = call->op;
334a58823acSDavid Howells const __be32 *bp;
335a58823acSDavid Howells int ret;
336a58823acSDavid Howells
337a58823acSDavid Howells ret = afs_transfer_reply(call);
338a58823acSDavid Howells if (ret < 0)
339a58823acSDavid Howells return ret;
340a58823acSDavid Howells
341a58823acSDavid Howells bp = call->buffer;
342e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &op->file[0].scb);
343e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
34430062bd1SDavid Howells
34530062bd1SDavid Howells _leave(" = 0 [done]");
34630062bd1SDavid Howells return 0;
34730062bd1SDavid Howells }
34830062bd1SDavid Howells
34930062bd1SDavid Howells /*
35030062bd1SDavid Howells * Deliver reply data to an YFS.FetchData64.
35130062bd1SDavid Howells */
yfs_deliver_fs_fetch_data64(struct afs_call * call)35230062bd1SDavid Howells static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
35330062bd1SDavid Howells {
354e49c7b2fSDavid Howells struct afs_operation *op = call->op;
355e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
356e49c7b2fSDavid Howells struct afs_read *req = op->fetch.req;
35730062bd1SDavid Howells const __be32 *bp;
358*ee4cdf7bSDavid Howells size_t count_before;
35930062bd1SDavid Howells int ret;
36030062bd1SDavid Howells
361f105da1aSDavid Howells _enter("{%u,%zu, %zu/%llu}",
362f105da1aSDavid Howells call->unmarshall, call->iov_len, iov_iter_count(call->iter),
363f105da1aSDavid Howells req->actual_len);
36430062bd1SDavid Howells
36530062bd1SDavid Howells switch (call->unmarshall) {
36630062bd1SDavid Howells case 0:
36730062bd1SDavid Howells req->actual_len = 0;
36830062bd1SDavid Howells afs_extract_to_tmp64(call);
36930062bd1SDavid Howells call->unmarshall++;
370df561f66SGustavo A. R. Silva fallthrough;
37130062bd1SDavid Howells
372c4508464SDavid Howells /* Extract the returned data length into ->actual_len. This
373c4508464SDavid Howells * may indicate more or less data than was requested will be
374c4508464SDavid Howells * returned.
375c4508464SDavid Howells */
37630062bd1SDavid Howells case 1:
37730062bd1SDavid Howells _debug("extract data length");
37830062bd1SDavid Howells ret = afs_extract_data(call, true);
37930062bd1SDavid Howells if (ret < 0)
38030062bd1SDavid Howells return ret;
38130062bd1SDavid Howells
38230062bd1SDavid Howells req->actual_len = be64_to_cpu(call->tmp64);
38330062bd1SDavid Howells _debug("DATA length: %llu", req->actual_len);
384c4508464SDavid Howells
385c4508464SDavid Howells if (req->actual_len == 0)
38630062bd1SDavid Howells goto no_more_data;
38730062bd1SDavid Howells
388c4508464SDavid Howells call->iter = req->iter;
389c4508464SDavid Howells call->iov_len = min(req->actual_len, req->len);
39030062bd1SDavid Howells call->unmarshall++;
391df561f66SGustavo A. R. Silva fallthrough;
39230062bd1SDavid Howells
39335a3a90cSGustavo A. R. Silva /* extract the returned data */
39430062bd1SDavid Howells case 2:
395*ee4cdf7bSDavid Howells count_before = call->iov_len;
396*ee4cdf7bSDavid Howells _debug("extract data %zu/%llu", count_before, req->actual_len);
39730062bd1SDavid Howells
39830062bd1SDavid Howells ret = afs_extract_data(call, true);
399*ee4cdf7bSDavid Howells if (req->subreq) {
400*ee4cdf7bSDavid Howells req->subreq->transferred += count_before - call->iov_len;
401*ee4cdf7bSDavid Howells netfs_read_subreq_progress(req->subreq, false);
402*ee4cdf7bSDavid Howells }
40330062bd1SDavid Howells if (ret < 0)
40430062bd1SDavid Howells return ret;
40530062bd1SDavid Howells
406c4508464SDavid Howells call->iter = &call->def_iter;
40730062bd1SDavid Howells if (req->actual_len <= req->len)
40830062bd1SDavid Howells goto no_more_data;
40930062bd1SDavid Howells
41030062bd1SDavid Howells /* Discard any excess data the server gave us */
41123a28913SDavid Howells afs_extract_discard(call, req->actual_len - req->len);
41230062bd1SDavid Howells call->unmarshall = 3;
413df561f66SGustavo A. R. Silva fallthrough;
41435a3a90cSGustavo A. R. Silva
41530062bd1SDavid Howells case 3:
41630062bd1SDavid Howells _debug("extract discard %zu/%llu",
417fc276122SDavid Howells iov_iter_count(call->iter), req->actual_len - req->len);
41830062bd1SDavid Howells
41930062bd1SDavid Howells ret = afs_extract_data(call, true);
42030062bd1SDavid Howells if (ret < 0)
42130062bd1SDavid Howells return ret;
42230062bd1SDavid Howells
42330062bd1SDavid Howells no_more_data:
42430062bd1SDavid Howells call->unmarshall = 4;
42530062bd1SDavid Howells afs_extract_to_buf(call,
42630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
42730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
42830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
429df561f66SGustavo A. R. Silva fallthrough;
43030062bd1SDavid Howells
43135a3a90cSGustavo A. R. Silva /* extract the metadata */
43230062bd1SDavid Howells case 4:
43330062bd1SDavid Howells ret = afs_extract_data(call, false);
43430062bd1SDavid Howells if (ret < 0)
43530062bd1SDavid Howells return ret;
43630062bd1SDavid Howells
43730062bd1SDavid Howells bp = call->buffer;
438e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
439e49c7b2fSDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb);
440e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
44130062bd1SDavid Howells
442e49c7b2fSDavid Howells req->data_version = vp->scb.status.data_version;
443e49c7b2fSDavid Howells req->file_size = vp->scb.status.size;
444a58823acSDavid Howells
44530062bd1SDavid Howells call->unmarshall++;
446df561f66SGustavo A. R. Silva fallthrough;
44735a3a90cSGustavo A. R. Silva
44830062bd1SDavid Howells case 5:
44930062bd1SDavid Howells break;
45030062bd1SDavid Howells }
45130062bd1SDavid Howells
45230062bd1SDavid Howells _leave(" = 0 [done]");
45330062bd1SDavid Howells return 0;
45430062bd1SDavid Howells }
45530062bd1SDavid Howells
45630062bd1SDavid Howells /*
45730062bd1SDavid Howells * YFS.FetchData64 operation type
45830062bd1SDavid Howells */
45930062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSFetchData64 = {
46030062bd1SDavid Howells .name = "YFS.FetchData64",
46130062bd1SDavid Howells .op = yfs_FS_FetchData64,
46230062bd1SDavid Howells .deliver = yfs_deliver_fs_fetch_data64,
463e49c7b2fSDavid Howells .destructor = afs_flat_call_destructor,
46430062bd1SDavid Howells };
46530062bd1SDavid Howells
46630062bd1SDavid Howells /*
46730062bd1SDavid Howells * Fetch data from a file.
46830062bd1SDavid Howells */
yfs_fs_fetch_data(struct afs_operation * op)469e49c7b2fSDavid Howells void yfs_fs_fetch_data(struct afs_operation *op)
47030062bd1SDavid Howells {
471e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
472e49c7b2fSDavid Howells struct afs_read *req = op->fetch.req;
47330062bd1SDavid Howells struct afs_call *call;
47430062bd1SDavid Howells __be32 *bp;
47530062bd1SDavid Howells
47630062bd1SDavid Howells _enter(",%x,{%llx:%llu},%llx,%llx",
477e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode,
47830062bd1SDavid Howells req->pos, req->len);
47930062bd1SDavid Howells
480e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchData64,
48130062bd1SDavid Howells sizeof(__be32) * 2 +
48230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
48330062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 2,
48430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
48530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
48630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
48730062bd1SDavid Howells if (!call)
488e49c7b2fSDavid Howells return afs_op_nomem(op);
48930062bd1SDavid Howells
490c4508464SDavid Howells req->call_debug_id = call->debug_id;
491c4508464SDavid Howells
49230062bd1SDavid Howells /* marshall the parameters */
49330062bd1SDavid Howells bp = call->request;
49430062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSFETCHDATA64);
49530062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
496e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
49730062bd1SDavid Howells bp = xdr_encode_u64(bp, req->pos);
49830062bd1SDavid Howells bp = xdr_encode_u64(bp, req->len);
49930062bd1SDavid Howells yfs_check_req(call, bp);
50030062bd1SDavid Howells
501abcbd3bfSDavid Howells call->fid = vp->fid;
502e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
503e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
50430062bd1SDavid Howells }
50530062bd1SDavid Howells
50630062bd1SDavid Howells /*
50730062bd1SDavid Howells * Deliver reply data for YFS.CreateFile or YFS.MakeDir.
50830062bd1SDavid Howells */
yfs_deliver_fs_create_vnode(struct afs_call * call)50930062bd1SDavid Howells static int yfs_deliver_fs_create_vnode(struct afs_call *call)
51030062bd1SDavid Howells {
511e49c7b2fSDavid Howells struct afs_operation *op = call->op;
512e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
513e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
51430062bd1SDavid Howells const __be32 *bp;
51530062bd1SDavid Howells int ret;
51630062bd1SDavid Howells
51730062bd1SDavid Howells _enter("{%u}", call->unmarshall);
51830062bd1SDavid Howells
51930062bd1SDavid Howells ret = afs_transfer_reply(call);
52030062bd1SDavid Howells if (ret < 0)
52130062bd1SDavid Howells return ret;
52230062bd1SDavid Howells
52330062bd1SDavid Howells /* unmarshall the reply once we've received all of it */
52430062bd1SDavid Howells bp = call->buffer;
525e49c7b2fSDavid Howells xdr_decode_YFSFid(&bp, &op->file[1].fid);
526e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
527e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
528e49c7b2fSDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb);
529e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
53030062bd1SDavid Howells
53130062bd1SDavid Howells _leave(" = 0 [done]");
53230062bd1SDavid Howells return 0;
53330062bd1SDavid Howells }
53430062bd1SDavid Howells
53530062bd1SDavid Howells /*
53630062bd1SDavid Howells * FS.CreateFile and FS.MakeDir operation type
53730062bd1SDavid Howells */
53830062bd1SDavid Howells static const struct afs_call_type afs_RXFSCreateFile = {
53930062bd1SDavid Howells .name = "YFS.CreateFile",
54030062bd1SDavid Howells .op = yfs_FS_CreateFile,
54130062bd1SDavid Howells .deliver = yfs_deliver_fs_create_vnode,
54230062bd1SDavid Howells .destructor = afs_flat_call_destructor,
54330062bd1SDavid Howells };
54430062bd1SDavid Howells
54530062bd1SDavid Howells /*
54630062bd1SDavid Howells * Create a file.
54730062bd1SDavid Howells */
yfs_fs_create_file(struct afs_operation * op)548e49c7b2fSDavid Howells void yfs_fs_create_file(struct afs_operation *op)
54930062bd1SDavid Howells {
550e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
551e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
55230062bd1SDavid Howells struct afs_call *call;
553e49c7b2fSDavid Howells size_t reqsz, rplsz;
55430062bd1SDavid Howells __be32 *bp;
55530062bd1SDavid Howells
55630062bd1SDavid Howells _enter("");
55730062bd1SDavid Howells
55830062bd1SDavid Howells reqsz = (sizeof(__be32) +
55930062bd1SDavid Howells sizeof(__be32) +
56030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
561e49c7b2fSDavid Howells xdr_strlen(name->len) +
56230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) +
56330062bd1SDavid Howells sizeof(__be32));
56430062bd1SDavid Howells rplsz = (sizeof(struct yfs_xdr_YFSFid) +
56530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
56630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
56730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
56830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
56930062bd1SDavid Howells
570e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &afs_RXFSCreateFile, reqsz, rplsz);
57130062bd1SDavid Howells if (!call)
572e49c7b2fSDavid Howells return afs_op_nomem(op);
57330062bd1SDavid Howells
57430062bd1SDavid Howells /* marshall the parameters */
57530062bd1SDavid Howells bp = call->request;
57630062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSCREATEFILE);
57730062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
578e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
579e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
58052af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, &op->create.mode, &op->mtime);
5815edc22ccSMarc Dionne bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */
58230062bd1SDavid Howells yfs_check_req(call, bp);
58330062bd1SDavid Howells
584abcbd3bfSDavid Howells call->fid = dvp->fid;
585e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
586e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
58730062bd1SDavid Howells }
58830062bd1SDavid Howells
58930062bd1SDavid Howells static const struct afs_call_type yfs_RXFSMakeDir = {
59030062bd1SDavid Howells .name = "YFS.MakeDir",
59130062bd1SDavid Howells .op = yfs_FS_MakeDir,
59230062bd1SDavid Howells .deliver = yfs_deliver_fs_create_vnode,
59330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
59430062bd1SDavid Howells };
59530062bd1SDavid Howells
59630062bd1SDavid Howells /*
59730062bd1SDavid Howells * Make a directory.
59830062bd1SDavid Howells */
yfs_fs_make_dir(struct afs_operation * op)599e49c7b2fSDavid Howells void yfs_fs_make_dir(struct afs_operation *op)
60030062bd1SDavid Howells {
601e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
602e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
60330062bd1SDavid Howells struct afs_call *call;
604e49c7b2fSDavid Howells size_t reqsz, rplsz;
60530062bd1SDavid Howells __be32 *bp;
60630062bd1SDavid Howells
60730062bd1SDavid Howells _enter("");
60830062bd1SDavid Howells
60930062bd1SDavid Howells reqsz = (sizeof(__be32) +
61030062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
61130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
612e49c7b2fSDavid Howells xdr_strlen(name->len) +
61330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus));
61430062bd1SDavid Howells rplsz = (sizeof(struct yfs_xdr_YFSFid) +
61530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
61630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
61730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
61830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
61930062bd1SDavid Howells
620e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXFSMakeDir, reqsz, rplsz);
62130062bd1SDavid Howells if (!call)
622e49c7b2fSDavid Howells return afs_op_nomem(op);
62330062bd1SDavid Howells
62430062bd1SDavid Howells /* marshall the parameters */
62530062bd1SDavid Howells bp = call->request;
62630062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSMAKEDIR);
62730062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
628e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
629e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
63052af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, &op->create.mode, &op->mtime);
63130062bd1SDavid Howells yfs_check_req(call, bp);
63230062bd1SDavid Howells
633abcbd3bfSDavid Howells call->fid = dvp->fid;
634e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
635e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
63630062bd1SDavid Howells }
63730062bd1SDavid Howells
63830062bd1SDavid Howells /*
63930062bd1SDavid Howells * Deliver reply data to a YFS.RemoveFile2 operation.
64030062bd1SDavid Howells */
yfs_deliver_fs_remove_file2(struct afs_call * call)64130062bd1SDavid Howells static int yfs_deliver_fs_remove_file2(struct afs_call *call)
64230062bd1SDavid Howells {
643e49c7b2fSDavid Howells struct afs_operation *op = call->op;
644e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
645e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
64630062bd1SDavid Howells struct afs_fid fid;
64730062bd1SDavid Howells const __be32 *bp;
64830062bd1SDavid Howells int ret;
64930062bd1SDavid Howells
65030062bd1SDavid Howells _enter("{%u}", call->unmarshall);
65130062bd1SDavid Howells
65230062bd1SDavid Howells ret = afs_transfer_reply(call);
65330062bd1SDavid Howells if (ret < 0)
65430062bd1SDavid Howells return ret;
65530062bd1SDavid Howells
65630062bd1SDavid Howells bp = call->buffer;
657e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
65830062bd1SDavid Howells xdr_decode_YFSFid(&bp, &fid);
659e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
66030062bd1SDavid Howells /* Was deleted if vnode->status.abort_code == VNOVNODE. */
66130062bd1SDavid Howells
662e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
66330062bd1SDavid Howells return 0;
66430062bd1SDavid Howells }
66530062bd1SDavid Howells
yfs_done_fs_remove_file2(struct afs_call * call)666e49c7b2fSDavid Howells static void yfs_done_fs_remove_file2(struct afs_call *call)
667e49c7b2fSDavid Howells {
668e49c7b2fSDavid Howells if (call->error == -ECONNABORTED &&
669e49c7b2fSDavid Howells call->abort_code == RX_INVALID_OPERATION) {
670e49c7b2fSDavid Howells set_bit(AFS_SERVER_FL_NO_RM2, &call->server->flags);
671e49c7b2fSDavid Howells call->op->flags |= AFS_OPERATION_DOWNGRADE;
672e49c7b2fSDavid Howells }
673e49c7b2fSDavid Howells }
674e49c7b2fSDavid Howells
67530062bd1SDavid Howells /*
67630062bd1SDavid Howells * YFS.RemoveFile2 operation type.
67730062bd1SDavid Howells */
67830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveFile2 = {
67930062bd1SDavid Howells .name = "YFS.RemoveFile2",
68030062bd1SDavid Howells .op = yfs_FS_RemoveFile2,
68130062bd1SDavid Howells .deliver = yfs_deliver_fs_remove_file2,
682e49c7b2fSDavid Howells .done = yfs_done_fs_remove_file2,
68330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
68430062bd1SDavid Howells };
68530062bd1SDavid Howells
68630062bd1SDavid Howells /*
68730062bd1SDavid Howells * Remove a file and retrieve new file status.
68830062bd1SDavid Howells */
yfs_fs_remove_file2(struct afs_operation * op)689e49c7b2fSDavid Howells void yfs_fs_remove_file2(struct afs_operation *op)
69030062bd1SDavid Howells {
691e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
692e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
69330062bd1SDavid Howells struct afs_call *call;
69430062bd1SDavid Howells __be32 *bp;
69530062bd1SDavid Howells
69630062bd1SDavid Howells _enter("");
69730062bd1SDavid Howells
698e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile2,
69930062bd1SDavid Howells sizeof(__be32) +
70030062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
70130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
702e49c7b2fSDavid Howells xdr_strlen(name->len),
70330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
70430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
70530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
70630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
70730062bd1SDavid Howells if (!call)
708e49c7b2fSDavid Howells return afs_op_nomem(op);
70930062bd1SDavid Howells
71030062bd1SDavid Howells /* marshall the parameters */
71130062bd1SDavid Howells bp = call->request;
71230062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEFILE2);
71330062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
714e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
715e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
71630062bd1SDavid Howells yfs_check_req(call, bp);
71730062bd1SDavid Howells
718abcbd3bfSDavid Howells call->fid = dvp->fid;
719e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
720e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
72130062bd1SDavid Howells }
72230062bd1SDavid Howells
72330062bd1SDavid Howells /*
72430062bd1SDavid Howells * Deliver reply data to a YFS.RemoveFile or YFS.RemoveDir operation.
72530062bd1SDavid Howells */
yfs_deliver_fs_remove(struct afs_call * call)72630062bd1SDavid Howells static int yfs_deliver_fs_remove(struct afs_call *call)
72730062bd1SDavid Howells {
728e49c7b2fSDavid Howells struct afs_operation *op = call->op;
729e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
73030062bd1SDavid Howells const __be32 *bp;
73130062bd1SDavid Howells int ret;
73230062bd1SDavid Howells
73330062bd1SDavid Howells _enter("{%u}", call->unmarshall);
73430062bd1SDavid Howells
73530062bd1SDavid Howells ret = afs_transfer_reply(call);
73630062bd1SDavid Howells if (ret < 0)
73730062bd1SDavid Howells return ret;
73830062bd1SDavid Howells
73930062bd1SDavid Howells bp = call->buffer;
740e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
741e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
74230062bd1SDavid Howells return 0;
74330062bd1SDavid Howells }
74430062bd1SDavid Howells
74530062bd1SDavid Howells /*
74630062bd1SDavid Howells * FS.RemoveDir and FS.RemoveFile operation types.
74730062bd1SDavid Howells */
74830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveFile = {
74930062bd1SDavid Howells .name = "YFS.RemoveFile",
75030062bd1SDavid Howells .op = yfs_FS_RemoveFile,
75130062bd1SDavid Howells .deliver = yfs_deliver_fs_remove,
75230062bd1SDavid Howells .destructor = afs_flat_call_destructor,
75330062bd1SDavid Howells };
75430062bd1SDavid Howells
755e49c7b2fSDavid Howells /*
756e49c7b2fSDavid Howells * Remove a file.
757e49c7b2fSDavid Howells */
yfs_fs_remove_file(struct afs_operation * op)758e49c7b2fSDavid Howells void yfs_fs_remove_file(struct afs_operation *op)
759e49c7b2fSDavid Howells {
760e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
761e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
762e49c7b2fSDavid Howells struct afs_call *call;
763e49c7b2fSDavid Howells __be32 *bp;
764e49c7b2fSDavid Howells
765e49c7b2fSDavid Howells _enter("");
766e49c7b2fSDavid Howells
76720325960SDavid Howells if (!test_bit(AFS_SERVER_FL_NO_RM2, &op->server->flags))
768e49c7b2fSDavid Howells return yfs_fs_remove_file2(op);
769e49c7b2fSDavid Howells
770e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveFile,
771e49c7b2fSDavid Howells sizeof(__be32) +
772e49c7b2fSDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
773e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFid) +
774e49c7b2fSDavid Howells xdr_strlen(name->len),
775e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
776e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
777e49c7b2fSDavid Howells if (!call)
778e49c7b2fSDavid Howells return afs_op_nomem(op);
779e49c7b2fSDavid Howells
780e49c7b2fSDavid Howells /* marshall the parameters */
781e49c7b2fSDavid Howells bp = call->request;
782e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEFILE);
783e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
784e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
785e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
786e49c7b2fSDavid Howells yfs_check_req(call, bp);
787e49c7b2fSDavid Howells
788abcbd3bfSDavid Howells call->fid = dvp->fid;
789e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
790e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
791e49c7b2fSDavid Howells }
792e49c7b2fSDavid Howells
79330062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRemoveDir = {
79430062bd1SDavid Howells .name = "YFS.RemoveDir",
79530062bd1SDavid Howells .op = yfs_FS_RemoveDir,
79630062bd1SDavid Howells .deliver = yfs_deliver_fs_remove,
79730062bd1SDavid Howells .destructor = afs_flat_call_destructor,
79830062bd1SDavid Howells };
79930062bd1SDavid Howells
80030062bd1SDavid Howells /*
801e49c7b2fSDavid Howells * Remove a directory.
80230062bd1SDavid Howells */
yfs_fs_remove_dir(struct afs_operation * op)803e49c7b2fSDavid Howells void yfs_fs_remove_dir(struct afs_operation *op)
80430062bd1SDavid Howells {
805e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
806e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
80730062bd1SDavid Howells struct afs_call *call;
80830062bd1SDavid Howells __be32 *bp;
80930062bd1SDavid Howells
81030062bd1SDavid Howells _enter("");
81130062bd1SDavid Howells
812e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRemoveDir,
81330062bd1SDavid Howells sizeof(__be32) +
81430062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
81530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
816e49c7b2fSDavid Howells xdr_strlen(name->len),
81730062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
81830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
81930062bd1SDavid Howells if (!call)
820e49c7b2fSDavid Howells return afs_op_nomem(op);
82130062bd1SDavid Howells
82230062bd1SDavid Howells /* marshall the parameters */
82330062bd1SDavid Howells bp = call->request;
824e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, YFSREMOVEDIR);
82530062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
826e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
827e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
82830062bd1SDavid Howells yfs_check_req(call, bp);
82930062bd1SDavid Howells
830abcbd3bfSDavid Howells call->fid = dvp->fid;
831e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
832e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
83330062bd1SDavid Howells }
83430062bd1SDavid Howells
83530062bd1SDavid Howells /*
83630062bd1SDavid Howells * Deliver reply data to a YFS.Link operation.
83730062bd1SDavid Howells */
yfs_deliver_fs_link(struct afs_call * call)83830062bd1SDavid Howells static int yfs_deliver_fs_link(struct afs_call *call)
83930062bd1SDavid Howells {
840e49c7b2fSDavid Howells struct afs_operation *op = call->op;
841e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
842e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
84330062bd1SDavid Howells const __be32 *bp;
84430062bd1SDavid Howells int ret;
84530062bd1SDavid Howells
84630062bd1SDavid Howells _enter("{%u}", call->unmarshall);
84730062bd1SDavid Howells
84830062bd1SDavid Howells ret = afs_transfer_reply(call);
84930062bd1SDavid Howells if (ret < 0)
85030062bd1SDavid Howells return ret;
85130062bd1SDavid Howells
85230062bd1SDavid Howells bp = call->buffer;
853e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
854e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
855e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
85630062bd1SDavid Howells _leave(" = 0 [done]");
85730062bd1SDavid Howells return 0;
85830062bd1SDavid Howells }
85930062bd1SDavid Howells
86030062bd1SDavid Howells /*
86130062bd1SDavid Howells * YFS.Link operation type.
86230062bd1SDavid Howells */
86330062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSLink = {
86430062bd1SDavid Howells .name = "YFS.Link",
86530062bd1SDavid Howells .op = yfs_FS_Link,
86630062bd1SDavid Howells .deliver = yfs_deliver_fs_link,
86730062bd1SDavid Howells .destructor = afs_flat_call_destructor,
86830062bd1SDavid Howells };
86930062bd1SDavid Howells
87030062bd1SDavid Howells /*
87130062bd1SDavid Howells * Make a hard link.
87230062bd1SDavid Howells */
yfs_fs_link(struct afs_operation * op)873e49c7b2fSDavid Howells void yfs_fs_link(struct afs_operation *op)
87430062bd1SDavid Howells {
875e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
876e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
877e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
87830062bd1SDavid Howells struct afs_call *call;
87930062bd1SDavid Howells __be32 *bp;
88030062bd1SDavid Howells
88130062bd1SDavid Howells _enter("");
88230062bd1SDavid Howells
883e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSLink,
88430062bd1SDavid Howells sizeof(__be32) +
88530062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
88630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
887e49c7b2fSDavid Howells xdr_strlen(name->len) +
88830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
88930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
89030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
89130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
89230062bd1SDavid Howells if (!call)
893e49c7b2fSDavid Howells return afs_op_nomem(op);
89430062bd1SDavid Howells
89530062bd1SDavid Howells /* marshall the parameters */
89630062bd1SDavid Howells bp = call->request;
89730062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSLINK);
89830062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
899e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
900e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
901e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
90230062bd1SDavid Howells yfs_check_req(call, bp);
90330062bd1SDavid Howells
904abcbd3bfSDavid Howells call->fid = vp->fid;
905e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &vp->fid, name);
906e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
90730062bd1SDavid Howells }
90830062bd1SDavid Howells
90930062bd1SDavid Howells /*
91030062bd1SDavid Howells * Deliver reply data to a YFS.Symlink operation.
91130062bd1SDavid Howells */
yfs_deliver_fs_symlink(struct afs_call * call)91230062bd1SDavid Howells static int yfs_deliver_fs_symlink(struct afs_call *call)
91330062bd1SDavid Howells {
914e49c7b2fSDavid Howells struct afs_operation *op = call->op;
915e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
916e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
91730062bd1SDavid Howells const __be32 *bp;
91830062bd1SDavid Howells int ret;
91930062bd1SDavid Howells
92030062bd1SDavid Howells _enter("{%u}", call->unmarshall);
92130062bd1SDavid Howells
92230062bd1SDavid Howells ret = afs_transfer_reply(call);
92330062bd1SDavid Howells if (ret < 0)
92430062bd1SDavid Howells return ret;
92530062bd1SDavid Howells
92630062bd1SDavid Howells /* unmarshall the reply once we've received all of it */
92730062bd1SDavid Howells bp = call->buffer;
928e49c7b2fSDavid Howells xdr_decode_YFSFid(&bp, &vp->fid);
929e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
930e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &dvp->scb);
931e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
93230062bd1SDavid Howells
93330062bd1SDavid Howells _leave(" = 0 [done]");
93430062bd1SDavid Howells return 0;
93530062bd1SDavid Howells }
93630062bd1SDavid Howells
93730062bd1SDavid Howells /*
93830062bd1SDavid Howells * YFS.Symlink operation type
93930062bd1SDavid Howells */
94030062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSSymlink = {
94130062bd1SDavid Howells .name = "YFS.Symlink",
94230062bd1SDavid Howells .op = yfs_FS_Symlink,
94330062bd1SDavid Howells .deliver = yfs_deliver_fs_symlink,
94430062bd1SDavid Howells .destructor = afs_flat_call_destructor,
94530062bd1SDavid Howells };
94630062bd1SDavid Howells
94730062bd1SDavid Howells /*
94830062bd1SDavid Howells * Create a symbolic link.
94930062bd1SDavid Howells */
yfs_fs_symlink(struct afs_operation * op)950e49c7b2fSDavid Howells void yfs_fs_symlink(struct afs_operation *op)
95130062bd1SDavid Howells {
952e49c7b2fSDavid Howells const struct qstr *name = &op->dentry->d_name;
953e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
95430062bd1SDavid Howells struct afs_call *call;
955e49c7b2fSDavid Howells size_t contents_sz;
95652af7105SMarc Dionne mode_t mode = 0777;
95730062bd1SDavid Howells __be32 *bp;
95830062bd1SDavid Howells
95930062bd1SDavid Howells _enter("");
96030062bd1SDavid Howells
961e49c7b2fSDavid Howells contents_sz = strlen(op->create.symlink);
962e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSSymlink,
96330062bd1SDavid Howells sizeof(__be32) +
96430062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
96530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
966e49c7b2fSDavid Howells xdr_strlen(name->len) +
96730062bd1SDavid Howells xdr_strlen(contents_sz) +
96830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus),
96930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
97030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
97130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
97230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
97330062bd1SDavid Howells if (!call)
974e49c7b2fSDavid Howells return afs_op_nomem(op);
97530062bd1SDavid Howells
97630062bd1SDavid Howells /* marshall the parameters */
97730062bd1SDavid Howells bp = call->request;
97830062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSYMLINK);
97930062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
980e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
981e49c7b2fSDavid Howells bp = xdr_encode_name(bp, name);
982e49c7b2fSDavid Howells bp = xdr_encode_string(bp, op->create.symlink, contents_sz);
98352af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, &mode, &op->mtime);
98430062bd1SDavid Howells yfs_check_req(call, bp);
98530062bd1SDavid Howells
986abcbd3bfSDavid Howells call->fid = dvp->fid;
987e49c7b2fSDavid Howells trace_afs_make_fs_call1(call, &dvp->fid, name);
988e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
98930062bd1SDavid Howells }
99030062bd1SDavid Howells
99130062bd1SDavid Howells /*
99230062bd1SDavid Howells * Deliver reply data to a YFS.Rename operation.
99330062bd1SDavid Howells */
yfs_deliver_fs_rename(struct afs_call * call)99430062bd1SDavid Howells static int yfs_deliver_fs_rename(struct afs_call *call)
99530062bd1SDavid Howells {
996e49c7b2fSDavid Howells struct afs_operation *op = call->op;
997e49c7b2fSDavid Howells struct afs_vnode_param *orig_dvp = &op->file[0];
998e49c7b2fSDavid Howells struct afs_vnode_param *new_dvp = &op->file[1];
99930062bd1SDavid Howells const __be32 *bp;
100030062bd1SDavid Howells int ret;
100130062bd1SDavid Howells
100230062bd1SDavid Howells _enter("{%u}", call->unmarshall);
100330062bd1SDavid Howells
100430062bd1SDavid Howells ret = afs_transfer_reply(call);
100530062bd1SDavid Howells if (ret < 0)
100630062bd1SDavid Howells return ret;
100730062bd1SDavid Howells
100830062bd1SDavid Howells bp = call->buffer;
100938355eecSDavid Howells /* If the two dirs are the same, we have two copies of the same status
101038355eecSDavid Howells * report, so we just decode it twice.
101138355eecSDavid Howells */
1012e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &orig_dvp->scb);
1013e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &new_dvp->scb);
1014e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
101530062bd1SDavid Howells _leave(" = 0 [done]");
101630062bd1SDavid Howells return 0;
101730062bd1SDavid Howells }
101830062bd1SDavid Howells
101930062bd1SDavid Howells /*
102030062bd1SDavid Howells * YFS.Rename operation type
102130062bd1SDavid Howells */
102230062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSRename = {
102330062bd1SDavid Howells .name = "FS.Rename",
102430062bd1SDavid Howells .op = yfs_FS_Rename,
102530062bd1SDavid Howells .deliver = yfs_deliver_fs_rename,
102630062bd1SDavid Howells .destructor = afs_flat_call_destructor,
102730062bd1SDavid Howells };
102830062bd1SDavid Howells
102930062bd1SDavid Howells /*
103030062bd1SDavid Howells * Rename a file or directory.
103130062bd1SDavid Howells */
yfs_fs_rename(struct afs_operation * op)1032e49c7b2fSDavid Howells void yfs_fs_rename(struct afs_operation *op)
103330062bd1SDavid Howells {
1034e49c7b2fSDavid Howells struct afs_vnode_param *orig_dvp = &op->file[0];
1035e49c7b2fSDavid Howells struct afs_vnode_param *new_dvp = &op->file[1];
1036e49c7b2fSDavid Howells const struct qstr *orig_name = &op->dentry->d_name;
1037e49c7b2fSDavid Howells const struct qstr *new_name = &op->dentry_2->d_name;
103830062bd1SDavid Howells struct afs_call *call;
103930062bd1SDavid Howells __be32 *bp;
104030062bd1SDavid Howells
104130062bd1SDavid Howells _enter("");
104230062bd1SDavid Howells
1043e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename,
104430062bd1SDavid Howells sizeof(__be32) +
104530062bd1SDavid Howells sizeof(struct yfs_xdr_RPCFlags) +
104630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
1047e49c7b2fSDavid Howells xdr_strlen(orig_name->len) +
104830062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
1049e49c7b2fSDavid Howells xdr_strlen(new_name->len),
105030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
105130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
105230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
105330062bd1SDavid Howells if (!call)
1054e49c7b2fSDavid Howells return afs_op_nomem(op);
105530062bd1SDavid Howells
105630062bd1SDavid Howells /* marshall the parameters */
105730062bd1SDavid Howells bp = call->request;
105830062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSRENAME);
105930062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1060e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &orig_dvp->fid);
1061e49c7b2fSDavid Howells bp = xdr_encode_name(bp, orig_name);
1062e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &new_dvp->fid);
1063e49c7b2fSDavid Howells bp = xdr_encode_name(bp, new_name);
106430062bd1SDavid Howells yfs_check_req(call, bp);
106530062bd1SDavid Howells
1066abcbd3bfSDavid Howells call->fid = orig_dvp->fid;
1067e49c7b2fSDavid Howells trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name);
1068e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
106930062bd1SDavid Howells }
107030062bd1SDavid Howells
107130062bd1SDavid Howells /*
107230062bd1SDavid Howells * YFS.StoreData64 operation type.
107330062bd1SDavid Howells */
107430062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreData64 = {
107530062bd1SDavid Howells .name = "YFS.StoreData64",
107630062bd1SDavid Howells .op = yfs_FS_StoreData64,
1077a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync,
107830062bd1SDavid Howells .destructor = afs_flat_call_destructor,
107930062bd1SDavid Howells };
108030062bd1SDavid Howells
108130062bd1SDavid Howells /*
108230062bd1SDavid Howells * Store a set of pages to a large file.
108330062bd1SDavid Howells */
yfs_fs_store_data(struct afs_operation * op)1084e49c7b2fSDavid Howells void yfs_fs_store_data(struct afs_operation *op)
108530062bd1SDavid Howells {
1086e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
108730062bd1SDavid Howells struct afs_call *call;
108830062bd1SDavid Howells __be32 *bp;
108930062bd1SDavid Howells
109030062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1091e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
109230062bd1SDavid Howells
109330062bd1SDavid Howells _debug("size %llx, at %llx, i_size %llx",
1094bd80d8a8SDavid Howells (unsigned long long)op->store.size,
1095bd80d8a8SDavid Howells (unsigned long long)op->store.pos,
1096bd80d8a8SDavid Howells (unsigned long long)op->store.i_size);
109730062bd1SDavid Howells
1098e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64,
109930062bd1SDavid Howells sizeof(__be32) +
110030062bd1SDavid Howells sizeof(__be32) +
110130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
110230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) +
110330062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 3,
110430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
110530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
110630062bd1SDavid Howells if (!call)
1107e49c7b2fSDavid Howells return afs_op_nomem(op);
110830062bd1SDavid Howells
1109bd80d8a8SDavid Howells call->write_iter = op->store.write_iter;
111030062bd1SDavid Howells
111130062bd1SDavid Howells /* marshall the parameters */
111230062bd1SDavid Howells bp = call->request;
111330062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREDATA64);
111430062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1115e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
111652af7105SMarc Dionne bp = xdr_encode_YFSStoreStatus(bp, NULL, &op->mtime);
1117bd80d8a8SDavid Howells bp = xdr_encode_u64(bp, op->store.pos);
1118bd80d8a8SDavid Howells bp = xdr_encode_u64(bp, op->store.size);
1119bd80d8a8SDavid Howells bp = xdr_encode_u64(bp, op->store.i_size);
112030062bd1SDavid Howells yfs_check_req(call, bp);
112130062bd1SDavid Howells
1122abcbd3bfSDavid Howells call->fid = vp->fid;
1123e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1124e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
112530062bd1SDavid Howells }
112630062bd1SDavid Howells
112730062bd1SDavid Howells /*
112830062bd1SDavid Howells * YFS.StoreStatus operation type
112930062bd1SDavid Howells */
113030062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreStatus = {
113130062bd1SDavid Howells .name = "YFS.StoreStatus",
113230062bd1SDavid Howells .op = yfs_FS_StoreStatus,
1133a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync,
113430062bd1SDavid Howells .destructor = afs_flat_call_destructor,
113530062bd1SDavid Howells };
113630062bd1SDavid Howells
113730062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = {
113830062bd1SDavid Howells .name = "YFS.StoreData64",
113930062bd1SDavid Howells .op = yfs_FS_StoreData64,
1140a58823acSDavid Howells .deliver = yfs_deliver_status_and_volsync,
114130062bd1SDavid Howells .destructor = afs_flat_call_destructor,
114230062bd1SDavid Howells };
114330062bd1SDavid Howells
114430062bd1SDavid Howells /*
114530062bd1SDavid Howells * Set the attributes on a file, using YFS.StoreData64 rather than
114630062bd1SDavid Howells * YFS.StoreStatus so as to alter the file size also.
114730062bd1SDavid Howells */
yfs_fs_setattr_size(struct afs_operation * op)1148e49c7b2fSDavid Howells static void yfs_fs_setattr_size(struct afs_operation *op)
114930062bd1SDavid Howells {
1150e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
115130062bd1SDavid Howells struct afs_call *call;
1152e49c7b2fSDavid Howells struct iattr *attr = op->setattr.attr;
115330062bd1SDavid Howells __be32 *bp;
115430062bd1SDavid Howells
115530062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1156e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
115730062bd1SDavid Howells
1158e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreData64_as_Status,
115930062bd1SDavid Howells sizeof(__be32) * 2 +
116030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
116130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus) +
116230062bd1SDavid Howells sizeof(struct yfs_xdr_u64) * 3,
116330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
116430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
116530062bd1SDavid Howells if (!call)
1166e49c7b2fSDavid Howells return afs_op_nomem(op);
116730062bd1SDavid Howells
116830062bd1SDavid Howells /* marshall the parameters */
116930062bd1SDavid Howells bp = call->request;
117030062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREDATA64);
117130062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1172e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
117330062bd1SDavid Howells bp = xdr_encode_YFS_StoreStatus(bp, attr);
11748c7ae38dSDavid Howells bp = xdr_encode_u64(bp, attr->ia_size); /* position of start of write */
117530062bd1SDavid Howells bp = xdr_encode_u64(bp, 0); /* size of write */
117630062bd1SDavid Howells bp = xdr_encode_u64(bp, attr->ia_size); /* new file length */
117730062bd1SDavid Howells yfs_check_req(call, bp);
117830062bd1SDavid Howells
1179abcbd3bfSDavid Howells call->fid = vp->fid;
1180e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1181e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
118230062bd1SDavid Howells }
118330062bd1SDavid Howells
118430062bd1SDavid Howells /*
118530062bd1SDavid Howells * Set the attributes on a file, using YFS.StoreData64 if there's a change in
118630062bd1SDavid Howells * file size, and YFS.StoreStatus otherwise.
118730062bd1SDavid Howells */
yfs_fs_setattr(struct afs_operation * op)1188e49c7b2fSDavid Howells void yfs_fs_setattr(struct afs_operation *op)
118930062bd1SDavid Howells {
1190e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
119130062bd1SDavid Howells struct afs_call *call;
1192e49c7b2fSDavid Howells struct iattr *attr = op->setattr.attr;
119330062bd1SDavid Howells __be32 *bp;
119430062bd1SDavid Howells
119530062bd1SDavid Howells if (attr->ia_valid & ATTR_SIZE)
1196e49c7b2fSDavid Howells return yfs_fs_setattr_size(op);
119730062bd1SDavid Howells
119830062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1199e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
120030062bd1SDavid Howells
1201e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreStatus,
120230062bd1SDavid Howells sizeof(__be32) * 2 +
120330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
120430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSStoreStatus),
120530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
120630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
120730062bd1SDavid Howells if (!call)
1208e49c7b2fSDavid Howells return afs_op_nomem(op);
120930062bd1SDavid Howells
121030062bd1SDavid Howells /* marshall the parameters */
121130062bd1SDavid Howells bp = call->request;
121230062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSTORESTATUS);
121330062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1214e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
121530062bd1SDavid Howells bp = xdr_encode_YFS_StoreStatus(bp, attr);
121630062bd1SDavid Howells yfs_check_req(call, bp);
121730062bd1SDavid Howells
1218abcbd3bfSDavid Howells call->fid = vp->fid;
1219e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1220e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
122130062bd1SDavid Howells }
122230062bd1SDavid Howells
122330062bd1SDavid Howells /*
122430062bd1SDavid Howells * Deliver reply data to a YFS.GetVolumeStatus operation.
122530062bd1SDavid Howells */
yfs_deliver_fs_get_volume_status(struct afs_call * call)122630062bd1SDavid Howells static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
122730062bd1SDavid Howells {
1228e49c7b2fSDavid Howells struct afs_operation *op = call->op;
122930062bd1SDavid Howells const __be32 *bp;
123030062bd1SDavid Howells char *p;
123130062bd1SDavid Howells u32 size;
123230062bd1SDavid Howells int ret;
123330062bd1SDavid Howells
123430062bd1SDavid Howells _enter("{%u}", call->unmarshall);
123530062bd1SDavid Howells
123630062bd1SDavid Howells switch (call->unmarshall) {
123730062bd1SDavid Howells case 0:
123830062bd1SDavid Howells call->unmarshall++;
123930062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus));
1240df561f66SGustavo A. R. Silva fallthrough;
124130062bd1SDavid Howells
124235a3a90cSGustavo A. R. Silva /* extract the returned status record */
124330062bd1SDavid Howells case 1:
124430062bd1SDavid Howells _debug("extract status");
124530062bd1SDavid Howells ret = afs_extract_data(call, true);
124630062bd1SDavid Howells if (ret < 0)
124730062bd1SDavid Howells return ret;
124830062bd1SDavid Howells
124930062bd1SDavid Howells bp = call->buffer;
1250e49c7b2fSDavid Howells xdr_decode_YFSFetchVolumeStatus(&bp, &op->volstatus.vs);
125130062bd1SDavid Howells call->unmarshall++;
125230062bd1SDavid Howells afs_extract_to_tmp(call);
1253df561f66SGustavo A. R. Silva fallthrough;
125430062bd1SDavid Howells
125535a3a90cSGustavo A. R. Silva /* extract the volume name length */
125630062bd1SDavid Howells case 2:
125730062bd1SDavid Howells ret = afs_extract_data(call, true);
125830062bd1SDavid Howells if (ret < 0)
125930062bd1SDavid Howells return ret;
126030062bd1SDavid Howells
126130062bd1SDavid Howells call->count = ntohl(call->tmp);
126230062bd1SDavid Howells _debug("volname length: %u", call->count);
126330062bd1SDavid Howells if (call->count >= AFSNAMEMAX)
12647126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_volname_len);
126530062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */
1266ffba718eSDavid Howells afs_extract_to_buf(call, size);
126730062bd1SDavid Howells call->unmarshall++;
1268df561f66SGustavo A. R. Silva fallthrough;
126930062bd1SDavid Howells
127035a3a90cSGustavo A. R. Silva /* extract the volume name */
127130062bd1SDavid Howells case 3:
127230062bd1SDavid Howells _debug("extract volname");
127330062bd1SDavid Howells ret = afs_extract_data(call, true);
127430062bd1SDavid Howells if (ret < 0)
127530062bd1SDavid Howells return ret;
127630062bd1SDavid Howells
1277ffba718eSDavid Howells p = call->buffer;
127830062bd1SDavid Howells p[call->count] = 0;
127930062bd1SDavid Howells _debug("volname '%s'", p);
128030062bd1SDavid Howells afs_extract_to_tmp(call);
128130062bd1SDavid Howells call->unmarshall++;
1282df561f66SGustavo A. R. Silva fallthrough;
128330062bd1SDavid Howells
128435a3a90cSGustavo A. R. Silva /* extract the offline message length */
128530062bd1SDavid Howells case 4:
128630062bd1SDavid Howells ret = afs_extract_data(call, true);
128730062bd1SDavid Howells if (ret < 0)
128830062bd1SDavid Howells return ret;
128930062bd1SDavid Howells
129030062bd1SDavid Howells call->count = ntohl(call->tmp);
129130062bd1SDavid Howells _debug("offline msg length: %u", call->count);
129230062bd1SDavid Howells if (call->count >= AFSNAMEMAX)
12937126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_offline_msg_len);
129430062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */
1295ffba718eSDavid Howells afs_extract_to_buf(call, size);
129630062bd1SDavid Howells call->unmarshall++;
1297df561f66SGustavo A. R. Silva fallthrough;
129830062bd1SDavid Howells
129935a3a90cSGustavo A. R. Silva /* extract the offline message */
130030062bd1SDavid Howells case 5:
130130062bd1SDavid Howells _debug("extract offline");
130230062bd1SDavid Howells ret = afs_extract_data(call, true);
130330062bd1SDavid Howells if (ret < 0)
130430062bd1SDavid Howells return ret;
130530062bd1SDavid Howells
1306ffba718eSDavid Howells p = call->buffer;
130730062bd1SDavid Howells p[call->count] = 0;
130830062bd1SDavid Howells _debug("offline '%s'", p);
130930062bd1SDavid Howells
131030062bd1SDavid Howells afs_extract_to_tmp(call);
131130062bd1SDavid Howells call->unmarshall++;
1312df561f66SGustavo A. R. Silva fallthrough;
131330062bd1SDavid Howells
131435a3a90cSGustavo A. R. Silva /* extract the message of the day length */
131530062bd1SDavid Howells case 6:
131630062bd1SDavid Howells ret = afs_extract_data(call, true);
131730062bd1SDavid Howells if (ret < 0)
131830062bd1SDavid Howells return ret;
131930062bd1SDavid Howells
132030062bd1SDavid Howells call->count = ntohl(call->tmp);
132130062bd1SDavid Howells _debug("motd length: %u", call->count);
132230062bd1SDavid Howells if (call->count >= AFSNAMEMAX)
13237126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_motd_len);
132430062bd1SDavid Howells size = (call->count + 3) & ~3; /* It's padded */
1325ffba718eSDavid Howells afs_extract_to_buf(call, size);
132630062bd1SDavid Howells call->unmarshall++;
1327df561f66SGustavo A. R. Silva fallthrough;
132830062bd1SDavid Howells
132935a3a90cSGustavo A. R. Silva /* extract the message of the day */
133030062bd1SDavid Howells case 7:
133130062bd1SDavid Howells _debug("extract motd");
133230062bd1SDavid Howells ret = afs_extract_data(call, false);
133330062bd1SDavid Howells if (ret < 0)
133430062bd1SDavid Howells return ret;
133530062bd1SDavid Howells
1336ffba718eSDavid Howells p = call->buffer;
133730062bd1SDavid Howells p[call->count] = 0;
133830062bd1SDavid Howells _debug("motd '%s'", p);
133930062bd1SDavid Howells
134030062bd1SDavid Howells call->unmarshall++;
1341df561f66SGustavo A. R. Silva fallthrough;
134235a3a90cSGustavo A. R. Silva
134330062bd1SDavid Howells case 8:
134430062bd1SDavid Howells break;
134530062bd1SDavid Howells }
134630062bd1SDavid Howells
134730062bd1SDavid Howells _leave(" = 0 [done]");
134830062bd1SDavid Howells return 0;
134930062bd1SDavid Howells }
135030062bd1SDavid Howells
135130062bd1SDavid Howells /*
135230062bd1SDavid Howells * YFS.GetVolumeStatus operation type
135330062bd1SDavid Howells */
135430062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSGetVolumeStatus = {
135530062bd1SDavid Howells .name = "YFS.GetVolumeStatus",
135630062bd1SDavid Howells .op = yfs_FS_GetVolumeStatus,
135730062bd1SDavid Howells .deliver = yfs_deliver_fs_get_volume_status,
1358ffba718eSDavid Howells .destructor = afs_flat_call_destructor,
135930062bd1SDavid Howells };
136030062bd1SDavid Howells
136130062bd1SDavid Howells /*
136230062bd1SDavid Howells * fetch the status of a volume
136330062bd1SDavid Howells */
yfs_fs_get_volume_status(struct afs_operation * op)1364e49c7b2fSDavid Howells void yfs_fs_get_volume_status(struct afs_operation *op)
136530062bd1SDavid Howells {
1366e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
136730062bd1SDavid Howells struct afs_call *call;
136830062bd1SDavid Howells __be32 *bp;
136930062bd1SDavid Howells
137030062bd1SDavid Howells _enter("");
137130062bd1SDavid Howells
1372e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSGetVolumeStatus,
137330062bd1SDavid Howells sizeof(__be32) * 2 +
137430062bd1SDavid Howells sizeof(struct yfs_xdr_u64),
1375ffba718eSDavid Howells max_t(size_t,
137630062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchVolumeStatus) +
1377ffba718eSDavid Howells sizeof(__be32),
1378ffba718eSDavid Howells AFSOPAQUEMAX + 1));
1379ffba718eSDavid Howells if (!call)
1380e49c7b2fSDavid Howells return afs_op_nomem(op);
138130062bd1SDavid Howells
138230062bd1SDavid Howells /* marshall the parameters */
138330062bd1SDavid Howells bp = call->request;
138430062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSGETVOLUMESTATUS);
138530062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1386e49c7b2fSDavid Howells bp = xdr_encode_u64(bp, vp->fid.vid);
138730062bd1SDavid Howells yfs_check_req(call, bp);
138830062bd1SDavid Howells
1389abcbd3bfSDavid Howells call->fid = vp->fid;
1390e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1391e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
139230062bd1SDavid Howells }
139330062bd1SDavid Howells
139430062bd1SDavid Howells /*
139530062bd1SDavid Howells * YFS.SetLock operation type
139630062bd1SDavid Howells */
139730062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSSetLock = {
139830062bd1SDavid Howells .name = "YFS.SetLock",
139930062bd1SDavid Howells .op = yfs_FS_SetLock,
1400f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
1401a690f60aSDavid Howells .done = afs_lock_op_done,
140230062bd1SDavid Howells .destructor = afs_flat_call_destructor,
140330062bd1SDavid Howells };
140430062bd1SDavid Howells
140530062bd1SDavid Howells /*
140630062bd1SDavid Howells * YFS.ExtendLock operation type
140730062bd1SDavid Howells */
140830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSExtendLock = {
140930062bd1SDavid Howells .name = "YFS.ExtendLock",
141030062bd1SDavid Howells .op = yfs_FS_ExtendLock,
1411f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
1412a690f60aSDavid Howells .done = afs_lock_op_done,
141330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
141430062bd1SDavid Howells };
141530062bd1SDavid Howells
141630062bd1SDavid Howells /*
141730062bd1SDavid Howells * YFS.ReleaseLock operation type
141830062bd1SDavid Howells */
141930062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSReleaseLock = {
142030062bd1SDavid Howells .name = "YFS.ReleaseLock",
142130062bd1SDavid Howells .op = yfs_FS_ReleaseLock,
1422f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
142330062bd1SDavid Howells .destructor = afs_flat_call_destructor,
142430062bd1SDavid Howells };
142530062bd1SDavid Howells
142630062bd1SDavid Howells /*
142730062bd1SDavid Howells * Set a lock on a file
142830062bd1SDavid Howells */
yfs_fs_set_lock(struct afs_operation * op)1429e49c7b2fSDavid Howells void yfs_fs_set_lock(struct afs_operation *op)
143030062bd1SDavid Howells {
1431e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
143230062bd1SDavid Howells struct afs_call *call;
143330062bd1SDavid Howells __be32 *bp;
143430062bd1SDavid Howells
143530062bd1SDavid Howells _enter("");
143630062bd1SDavid Howells
1437e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSSetLock,
143830062bd1SDavid Howells sizeof(__be32) * 2 +
143930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
144030062bd1SDavid Howells sizeof(__be32),
144130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
144230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
144330062bd1SDavid Howells if (!call)
1444e49c7b2fSDavid Howells return afs_op_nomem(op);
144530062bd1SDavid Howells
144630062bd1SDavid Howells /* marshall the parameters */
144730062bd1SDavid Howells bp = call->request;
144830062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSSETLOCK);
144930062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1450e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1451e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, op->lock.type);
145230062bd1SDavid Howells yfs_check_req(call, bp);
145330062bd1SDavid Howells
1454abcbd3bfSDavid Howells call->fid = vp->fid;
1455e49c7b2fSDavid Howells trace_afs_make_fs_calli(call, &vp->fid, op->lock.type);
1456e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
145730062bd1SDavid Howells }
145830062bd1SDavid Howells
145930062bd1SDavid Howells /*
146030062bd1SDavid Howells * extend a lock on a file
146130062bd1SDavid Howells */
yfs_fs_extend_lock(struct afs_operation * op)1462e49c7b2fSDavid Howells void yfs_fs_extend_lock(struct afs_operation *op)
146330062bd1SDavid Howells {
1464e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
146530062bd1SDavid Howells struct afs_call *call;
146630062bd1SDavid Howells __be32 *bp;
146730062bd1SDavid Howells
146830062bd1SDavid Howells _enter("");
146930062bd1SDavid Howells
1470e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSExtendLock,
147130062bd1SDavid Howells sizeof(__be32) * 2 +
147230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
147330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
147430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
147530062bd1SDavid Howells if (!call)
1476e49c7b2fSDavid Howells return afs_op_nomem(op);
147730062bd1SDavid Howells
147830062bd1SDavid Howells /* marshall the parameters */
147930062bd1SDavid Howells bp = call->request;
148030062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSEXTENDLOCK);
148130062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1482e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
148330062bd1SDavid Howells yfs_check_req(call, bp);
148430062bd1SDavid Howells
1485abcbd3bfSDavid Howells call->fid = vp->fid;
1486e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1487e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
148830062bd1SDavid Howells }
148930062bd1SDavid Howells
149030062bd1SDavid Howells /*
149130062bd1SDavid Howells * release a lock on a file
149230062bd1SDavid Howells */
yfs_fs_release_lock(struct afs_operation * op)1493e49c7b2fSDavid Howells void yfs_fs_release_lock(struct afs_operation *op)
149430062bd1SDavid Howells {
1495e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
149630062bd1SDavid Howells struct afs_call *call;
149730062bd1SDavid Howells __be32 *bp;
149830062bd1SDavid Howells
149930062bd1SDavid Howells _enter("");
150030062bd1SDavid Howells
1501e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSReleaseLock,
150230062bd1SDavid Howells sizeof(__be32) * 2 +
150330062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
150430062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
150530062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
150630062bd1SDavid Howells if (!call)
1507e49c7b2fSDavid Howells return afs_op_nomem(op);
150830062bd1SDavid Howells
150930062bd1SDavid Howells /* marshall the parameters */
151030062bd1SDavid Howells bp = call->request;
151130062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSRELEASELOCK);
151230062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1513e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
151430062bd1SDavid Howells yfs_check_req(call, bp);
151530062bd1SDavid Howells
1516abcbd3bfSDavid Howells call->fid = vp->fid;
1517e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1518e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
151930062bd1SDavid Howells }
152030062bd1SDavid Howells
152130062bd1SDavid Howells /*
15229bd87ec6SDavid Howells * Deliver a reply to YFS.FetchStatus
15239bd87ec6SDavid Howells */
yfs_deliver_fs_fetch_status(struct afs_call * call)15249bd87ec6SDavid Howells static int yfs_deliver_fs_fetch_status(struct afs_call *call)
15259bd87ec6SDavid Howells {
15269bd87ec6SDavid Howells struct afs_operation *op = call->op;
15279bd87ec6SDavid Howells struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
15289bd87ec6SDavid Howells const __be32 *bp;
15299bd87ec6SDavid Howells int ret;
15309bd87ec6SDavid Howells
15319bd87ec6SDavid Howells ret = afs_transfer_reply(call);
15329bd87ec6SDavid Howells if (ret < 0)
15339bd87ec6SDavid Howells return ret;
15349bd87ec6SDavid Howells
15359bd87ec6SDavid Howells /* unmarshall the reply once we've received all of it */
15369bd87ec6SDavid Howells bp = call->buffer;
15379bd87ec6SDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
15389bd87ec6SDavid Howells xdr_decode_YFSCallBack(&bp, call, &vp->scb);
15399bd87ec6SDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
15409bd87ec6SDavid Howells
15419bd87ec6SDavid Howells _leave(" = 0 [done]");
15429bd87ec6SDavid Howells return 0;
15439bd87ec6SDavid Howells }
15449bd87ec6SDavid Howells
15459bd87ec6SDavid Howells /*
154630062bd1SDavid Howells * YFS.FetchStatus operation type
154730062bd1SDavid Howells */
154830062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSFetchStatus = {
154930062bd1SDavid Howells .name = "YFS.FetchStatus",
155030062bd1SDavid Howells .op = yfs_FS_FetchStatus,
15519bd87ec6SDavid Howells .deliver = yfs_deliver_fs_fetch_status,
155230062bd1SDavid Howells .destructor = afs_flat_call_destructor,
155330062bd1SDavid Howells };
155430062bd1SDavid Howells
155530062bd1SDavid Howells /*
155630062bd1SDavid Howells * Fetch the status information for a fid without needing a vnode handle.
155730062bd1SDavid Howells */
yfs_fs_fetch_status(struct afs_operation * op)1558e49c7b2fSDavid Howells void yfs_fs_fetch_status(struct afs_operation *op)
155930062bd1SDavid Howells {
15609bd87ec6SDavid Howells struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
156130062bd1SDavid Howells struct afs_call *call;
156230062bd1SDavid Howells __be32 *bp;
156330062bd1SDavid Howells
156430062bd1SDavid Howells _enter(",%x,{%llx:%llu},,",
1565e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
156630062bd1SDavid Howells
1567e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchStatus,
156830062bd1SDavid Howells sizeof(__be32) * 2 +
156930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFid),
157030062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
157130062bd1SDavid Howells sizeof(struct yfs_xdr_YFSCallBack) +
157230062bd1SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1573e49c7b2fSDavid Howells if (!call)
1574e49c7b2fSDavid Howells return afs_op_nomem(op);
157530062bd1SDavid Howells
157630062bd1SDavid Howells /* marshall the parameters */
157730062bd1SDavid Howells bp = call->request;
157830062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSFETCHSTATUS);
157930062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1580e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
158130062bd1SDavid Howells yfs_check_req(call, bp);
158230062bd1SDavid Howells
1583abcbd3bfSDavid Howells call->fid = vp->fid;
1584e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1585e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
158630062bd1SDavid Howells }
158730062bd1SDavid Howells
158830062bd1SDavid Howells /*
158930062bd1SDavid Howells * Deliver reply data to an YFS.InlineBulkStatus call
159030062bd1SDavid Howells */
yfs_deliver_fs_inline_bulk_status(struct afs_call * call)159130062bd1SDavid Howells static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
159230062bd1SDavid Howells {
1593e49c7b2fSDavid Howells struct afs_operation *op = call->op;
159487182759SDavid Howells struct afs_status_cb *scb;
159530062bd1SDavid Howells const __be32 *bp;
159630062bd1SDavid Howells u32 tmp;
159730062bd1SDavid Howells int ret;
159830062bd1SDavid Howells
159930062bd1SDavid Howells _enter("{%u}", call->unmarshall);
160030062bd1SDavid Howells
160130062bd1SDavid Howells switch (call->unmarshall) {
160230062bd1SDavid Howells case 0:
160330062bd1SDavid Howells afs_extract_to_tmp(call);
160430062bd1SDavid Howells call->unmarshall++;
1605df561f66SGustavo A. R. Silva fallthrough;
160630062bd1SDavid Howells
160730062bd1SDavid Howells /* Extract the file status count and array in two steps */
160830062bd1SDavid Howells case 1:
160930062bd1SDavid Howells _debug("extract status count");
161030062bd1SDavid Howells ret = afs_extract_data(call, true);
161130062bd1SDavid Howells if (ret < 0)
161230062bd1SDavid Howells return ret;
161330062bd1SDavid Howells
161430062bd1SDavid Howells tmp = ntohl(call->tmp);
1615e49c7b2fSDavid Howells _debug("status count: %u/%u", tmp, op->nr_files);
1616e49c7b2fSDavid Howells if (tmp != op->nr_files)
16177126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_ibulkst_count);
161830062bd1SDavid Howells
161930062bd1SDavid Howells call->count = 0;
162030062bd1SDavid Howells call->unmarshall++;
162130062bd1SDavid Howells more_counts:
162230062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus));
1623df561f66SGustavo A. R. Silva fallthrough;
162435a3a90cSGustavo A. R. Silva
162530062bd1SDavid Howells case 2:
162630062bd1SDavid Howells _debug("extract status array %u", call->count);
162730062bd1SDavid Howells ret = afs_extract_data(call, true);
162830062bd1SDavid Howells if (ret < 0)
162930062bd1SDavid Howells return ret;
163030062bd1SDavid Howells
1631e49c7b2fSDavid Howells switch (call->count) {
1632e49c7b2fSDavid Howells case 0:
1633e49c7b2fSDavid Howells scb = &op->file[0].scb;
1634e49c7b2fSDavid Howells break;
1635e49c7b2fSDavid Howells case 1:
1636e49c7b2fSDavid Howells scb = &op->file[1].scb;
1637e49c7b2fSDavid Howells break;
1638e49c7b2fSDavid Howells default:
1639e49c7b2fSDavid Howells scb = &op->more_files[call->count - 2].scb;
1640e49c7b2fSDavid Howells break;
1641e49c7b2fSDavid Howells }
1642e49c7b2fSDavid Howells
164330062bd1SDavid Howells bp = call->buffer;
164438355eecSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, scb);
164530062bd1SDavid Howells
164630062bd1SDavid Howells call->count++;
1647e49c7b2fSDavid Howells if (call->count < op->nr_files)
164830062bd1SDavid Howells goto more_counts;
164930062bd1SDavid Howells
165030062bd1SDavid Howells call->count = 0;
165130062bd1SDavid Howells call->unmarshall++;
165230062bd1SDavid Howells afs_extract_to_tmp(call);
1653df561f66SGustavo A. R. Silva fallthrough;
165430062bd1SDavid Howells
165530062bd1SDavid Howells /* Extract the callback count and array in two steps */
165630062bd1SDavid Howells case 3:
165730062bd1SDavid Howells _debug("extract CB count");
165830062bd1SDavid Howells ret = afs_extract_data(call, true);
165930062bd1SDavid Howells if (ret < 0)
166030062bd1SDavid Howells return ret;
166130062bd1SDavid Howells
166230062bd1SDavid Howells tmp = ntohl(call->tmp);
166330062bd1SDavid Howells _debug("CB count: %u", tmp);
1664e49c7b2fSDavid Howells if (tmp != op->nr_files)
16657126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_ibulkst_cb_count);
166630062bd1SDavid Howells call->count = 0;
166730062bd1SDavid Howells call->unmarshall++;
166830062bd1SDavid Howells more_cbs:
166930062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack));
1670df561f66SGustavo A. R. Silva fallthrough;
167135a3a90cSGustavo A. R. Silva
167230062bd1SDavid Howells case 4:
167330062bd1SDavid Howells _debug("extract CB array");
167430062bd1SDavid Howells ret = afs_extract_data(call, true);
167530062bd1SDavid Howells if (ret < 0)
167630062bd1SDavid Howells return ret;
167730062bd1SDavid Howells
167830062bd1SDavid Howells _debug("unmarshall CB array");
1679e49c7b2fSDavid Howells switch (call->count) {
1680e49c7b2fSDavid Howells case 0:
1681e49c7b2fSDavid Howells scb = &op->file[0].scb;
1682e49c7b2fSDavid Howells break;
1683e49c7b2fSDavid Howells case 1:
1684e49c7b2fSDavid Howells scb = &op->file[1].scb;
1685e49c7b2fSDavid Howells break;
1686e49c7b2fSDavid Howells default:
1687e49c7b2fSDavid Howells scb = &op->more_files[call->count - 2].scb;
1688e49c7b2fSDavid Howells break;
1689e49c7b2fSDavid Howells }
1690e49c7b2fSDavid Howells
169130062bd1SDavid Howells bp = call->buffer;
1692a58823acSDavid Howells xdr_decode_YFSCallBack(&bp, call, scb);
169330062bd1SDavid Howells call->count++;
1694e49c7b2fSDavid Howells if (call->count < op->nr_files)
169530062bd1SDavid Howells goto more_cbs;
169630062bd1SDavid Howells
169730062bd1SDavid Howells afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync));
169830062bd1SDavid Howells call->unmarshall++;
1699df561f66SGustavo A. R. Silva fallthrough;
170035a3a90cSGustavo A. R. Silva
170130062bd1SDavid Howells case 5:
170230062bd1SDavid Howells ret = afs_extract_data(call, false);
170330062bd1SDavid Howells if (ret < 0)
170430062bd1SDavid Howells return ret;
170530062bd1SDavid Howells
170630062bd1SDavid Howells bp = call->buffer;
1707e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
170830062bd1SDavid Howells
170930062bd1SDavid Howells call->unmarshall++;
1710df561f66SGustavo A. R. Silva fallthrough;
171135a3a90cSGustavo A. R. Silva
171230062bd1SDavid Howells case 6:
171330062bd1SDavid Howells break;
171430062bd1SDavid Howells }
171530062bd1SDavid Howells
171630062bd1SDavid Howells _leave(" = 0 [done]");
171730062bd1SDavid Howells return 0;
171830062bd1SDavid Howells }
171930062bd1SDavid Howells
172030062bd1SDavid Howells /*
172130062bd1SDavid Howells * FS.InlineBulkStatus operation type
172230062bd1SDavid Howells */
172330062bd1SDavid Howells static const struct afs_call_type yfs_RXYFSInlineBulkStatus = {
172430062bd1SDavid Howells .name = "YFS.InlineBulkStatus",
172530062bd1SDavid Howells .op = yfs_FS_InlineBulkStatus,
172630062bd1SDavid Howells .deliver = yfs_deliver_fs_inline_bulk_status,
172730062bd1SDavid Howells .destructor = afs_flat_call_destructor,
172830062bd1SDavid Howells };
172930062bd1SDavid Howells
173030062bd1SDavid Howells /*
173130062bd1SDavid Howells * Fetch the status information for up to 1024 files
173230062bd1SDavid Howells */
yfs_fs_inline_bulk_status(struct afs_operation * op)1733e49c7b2fSDavid Howells void yfs_fs_inline_bulk_status(struct afs_operation *op)
173430062bd1SDavid Howells {
1735e49c7b2fSDavid Howells struct afs_vnode_param *dvp = &op->file[0];
1736e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[1];
173730062bd1SDavid Howells struct afs_call *call;
173830062bd1SDavid Howells __be32 *bp;
173930062bd1SDavid Howells int i;
174030062bd1SDavid Howells
174130062bd1SDavid Howells _enter(",%x,{%llx:%llu},%u",
1742e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode, op->nr_files);
174330062bd1SDavid Howells
1744e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSInlineBulkStatus,
174530062bd1SDavid Howells sizeof(__be32) +
174630062bd1SDavid Howells sizeof(__be32) +
174730062bd1SDavid Howells sizeof(__be32) +
1748e49c7b2fSDavid Howells sizeof(struct yfs_xdr_YFSFid) * op->nr_files,
174930062bd1SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus));
1750e49c7b2fSDavid Howells if (!call)
1751e49c7b2fSDavid Howells return afs_op_nomem(op);
175230062bd1SDavid Howells
175330062bd1SDavid Howells /* marshall the parameters */
175430062bd1SDavid Howells bp = call->request;
175530062bd1SDavid Howells bp = xdr_encode_u32(bp, YFSINLINEBULKSTATUS);
175630062bd1SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPCFlags */
1757e49c7b2fSDavid Howells bp = xdr_encode_u32(bp, op->nr_files);
1758e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &dvp->fid);
1759e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1760e49c7b2fSDavid Howells for (i = 0; i < op->nr_files - 2; i++)
1761e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &op->more_files[i].fid);
176230062bd1SDavid Howells yfs_check_req(call, bp);
176330062bd1SDavid Howells
1764abcbd3bfSDavid Howells call->fid = vp->fid;
1765e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1766e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_NOFS);
176730062bd1SDavid Howells }
1768ae46578bSDavid Howells
1769ae46578bSDavid Howells /*
1770ae46578bSDavid Howells * Deliver reply data to an YFS.FetchOpaqueACL.
1771ae46578bSDavid Howells */
yfs_deliver_fs_fetch_opaque_acl(struct afs_call * call)1772ae46578bSDavid Howells static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
1773ae46578bSDavid Howells {
1774e49c7b2fSDavid Howells struct afs_operation *op = call->op;
1775e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
1776e49c7b2fSDavid Howells struct yfs_acl *yacl = op->yacl;
1777ae46578bSDavid Howells struct afs_acl *acl;
1778ae46578bSDavid Howells const __be32 *bp;
1779ae46578bSDavid Howells unsigned int size;
1780ae46578bSDavid Howells int ret;
1781ae46578bSDavid Howells
1782ae46578bSDavid Howells _enter("{%u}", call->unmarshall);
1783ae46578bSDavid Howells
1784ae46578bSDavid Howells switch (call->unmarshall) {
1785ae46578bSDavid Howells case 0:
1786ae46578bSDavid Howells afs_extract_to_tmp(call);
1787ae46578bSDavid Howells call->unmarshall++;
1788df561f66SGustavo A. R. Silva fallthrough;
1789ae46578bSDavid Howells
1790ae46578bSDavid Howells /* Extract the file ACL length */
1791ae46578bSDavid Howells case 1:
1792ae46578bSDavid Howells ret = afs_extract_data(call, true);
1793ae46578bSDavid Howells if (ret < 0)
1794ae46578bSDavid Howells return ret;
1795ae46578bSDavid Howells
1796ae46578bSDavid Howells size = call->count2 = ntohl(call->tmp);
1797ae46578bSDavid Howells size = round_up(size, 4);
1798ae46578bSDavid Howells
1799ae46578bSDavid Howells if (yacl->flags & YFS_ACL_WANT_ACL) {
1800ae46578bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
1801ae46578bSDavid Howells if (!acl)
1802ae46578bSDavid Howells return -ENOMEM;
1803ae46578bSDavid Howells yacl->acl = acl;
1804ae46578bSDavid Howells acl->size = call->count2;
1805ae46578bSDavid Howells afs_extract_begin(call, acl->data, size);
1806ae46578bSDavid Howells } else {
180723a28913SDavid Howells afs_extract_discard(call, size);
1808ae46578bSDavid Howells }
1809ae46578bSDavid Howells call->unmarshall++;
1810df561f66SGustavo A. R. Silva fallthrough;
1811ae46578bSDavid Howells
1812ae46578bSDavid Howells /* Extract the file ACL */
1813ae46578bSDavid Howells case 2:
1814ae46578bSDavid Howells ret = afs_extract_data(call, true);
1815ae46578bSDavid Howells if (ret < 0)
1816ae46578bSDavid Howells return ret;
1817ae46578bSDavid Howells
1818ae46578bSDavid Howells afs_extract_to_tmp(call);
1819ae46578bSDavid Howells call->unmarshall++;
1820df561f66SGustavo A. R. Silva fallthrough;
1821ae46578bSDavid Howells
1822ae46578bSDavid Howells /* Extract the volume ACL length */
1823ae46578bSDavid Howells case 3:
1824ae46578bSDavid Howells ret = afs_extract_data(call, true);
1825ae46578bSDavid Howells if (ret < 0)
1826ae46578bSDavid Howells return ret;
1827ae46578bSDavid Howells
1828ae46578bSDavid Howells size = call->count2 = ntohl(call->tmp);
1829ae46578bSDavid Howells size = round_up(size, 4);
1830ae46578bSDavid Howells
1831ae46578bSDavid Howells if (yacl->flags & YFS_ACL_WANT_VOL_ACL) {
1832ae46578bSDavid Howells acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
1833ae46578bSDavid Howells if (!acl)
1834ae46578bSDavid Howells return -ENOMEM;
1835ae46578bSDavid Howells yacl->vol_acl = acl;
1836ae46578bSDavid Howells acl->size = call->count2;
1837ae46578bSDavid Howells afs_extract_begin(call, acl->data, size);
1838ae46578bSDavid Howells } else {
183923a28913SDavid Howells afs_extract_discard(call, size);
1840ae46578bSDavid Howells }
1841ae46578bSDavid Howells call->unmarshall++;
1842df561f66SGustavo A. R. Silva fallthrough;
1843ae46578bSDavid Howells
1844ae46578bSDavid Howells /* Extract the volume ACL */
1845ae46578bSDavid Howells case 4:
1846ae46578bSDavid Howells ret = afs_extract_data(call, true);
1847ae46578bSDavid Howells if (ret < 0)
1848ae46578bSDavid Howells return ret;
1849ae46578bSDavid Howells
1850ae46578bSDavid Howells afs_extract_to_buf(call,
1851ae46578bSDavid Howells sizeof(__be32) * 2 +
1852ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
1853ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1854ae46578bSDavid Howells call->unmarshall++;
1855df561f66SGustavo A. R. Silva fallthrough;
1856ae46578bSDavid Howells
1857ae46578bSDavid Howells /* extract the metadata */
1858ae46578bSDavid Howells case 5:
1859ae46578bSDavid Howells ret = afs_extract_data(call, false);
1860ae46578bSDavid Howells if (ret < 0)
1861ae46578bSDavid Howells return ret;
1862ae46578bSDavid Howells
1863ae46578bSDavid Howells bp = call->buffer;
1864ae46578bSDavid Howells yacl->inherit_flag = ntohl(*bp++);
1865ae46578bSDavid Howells yacl->num_cleaned = ntohl(*bp++);
1866e49c7b2fSDavid Howells xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
1867e49c7b2fSDavid Howells xdr_decode_YFSVolSync(&bp, &op->volsync);
1868ae46578bSDavid Howells
1869ae46578bSDavid Howells call->unmarshall++;
1870df561f66SGustavo A. R. Silva fallthrough;
1871ae46578bSDavid Howells
1872ae46578bSDavid Howells case 6:
1873ae46578bSDavid Howells break;
1874ae46578bSDavid Howells }
1875ae46578bSDavid Howells
1876ae46578bSDavid Howells _leave(" = 0 [done]");
1877ae46578bSDavid Howells return 0;
1878ae46578bSDavid Howells }
1879ae46578bSDavid Howells
yfs_free_opaque_acl(struct yfs_acl * yacl)1880ae46578bSDavid Howells void yfs_free_opaque_acl(struct yfs_acl *yacl)
1881ae46578bSDavid Howells {
1882ae46578bSDavid Howells if (yacl) {
1883ae46578bSDavid Howells kfree(yacl->acl);
1884ae46578bSDavid Howells kfree(yacl->vol_acl);
1885ae46578bSDavid Howells kfree(yacl);
1886ae46578bSDavid Howells }
1887ae46578bSDavid Howells }
1888ae46578bSDavid Howells
1889ae46578bSDavid Howells /*
1890ae46578bSDavid Howells * YFS.FetchOpaqueACL operation type
1891ae46578bSDavid Howells */
1892ae46578bSDavid Howells static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = {
1893ae46578bSDavid Howells .name = "YFS.FetchOpaqueACL",
1894ae46578bSDavid Howells .op = yfs_FS_FetchOpaqueACL,
1895ae46578bSDavid Howells .deliver = yfs_deliver_fs_fetch_opaque_acl,
1896773e0c40SDavid Howells .destructor = afs_flat_call_destructor,
1897ae46578bSDavid Howells };
1898ae46578bSDavid Howells
1899ae46578bSDavid Howells /*
1900ae46578bSDavid Howells * Fetch the YFS advanced ACLs for a file.
1901ae46578bSDavid Howells */
yfs_fs_fetch_opaque_acl(struct afs_operation * op)1902e49c7b2fSDavid Howells void yfs_fs_fetch_opaque_acl(struct afs_operation *op)
1903ae46578bSDavid Howells {
1904e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
1905ae46578bSDavid Howells struct afs_call *call;
1906ae46578bSDavid Howells __be32 *bp;
1907ae46578bSDavid Howells
1908ae46578bSDavid Howells _enter(",%x,{%llx:%llu},,",
1909e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
1910ae46578bSDavid Howells
1911e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchOpaqueACL,
1912ae46578bSDavid Howells sizeof(__be32) * 2 +
1913ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFid),
1914ae46578bSDavid Howells sizeof(__be32) * 2 +
1915ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
1916ae46578bSDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1917e49c7b2fSDavid Howells if (!call)
1918e49c7b2fSDavid Howells return afs_op_nomem(op);
1919ae46578bSDavid Howells
1920ae46578bSDavid Howells /* marshall the parameters */
1921ae46578bSDavid Howells bp = call->request;
1922ae46578bSDavid Howells bp = xdr_encode_u32(bp, YFSFETCHOPAQUEACL);
1923ae46578bSDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1924e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1925ae46578bSDavid Howells yfs_check_req(call, bp);
1926ae46578bSDavid Howells
1927abcbd3bfSDavid Howells call->fid = vp->fid;
1928e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1929e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_KERNEL);
1930ae46578bSDavid Howells }
1931f5e45463SDavid Howells
1932f5e45463SDavid Howells /*
1933f5e45463SDavid Howells * YFS.StoreOpaqueACL2 operation type
1934f5e45463SDavid Howells */
1935f5e45463SDavid Howells static const struct afs_call_type yfs_RXYFSStoreOpaqueACL2 = {
1936f5e45463SDavid Howells .name = "YFS.StoreOpaqueACL2",
1937f5e45463SDavid Howells .op = yfs_FS_StoreOpaqueACL2,
1938f5e45463SDavid Howells .deliver = yfs_deliver_status_and_volsync,
1939f5e45463SDavid Howells .destructor = afs_flat_call_destructor,
1940f5e45463SDavid Howells };
1941f5e45463SDavid Howells
1942f5e45463SDavid Howells /*
1943f5e45463SDavid Howells * Fetch the YFS ACL for a file.
1944f5e45463SDavid Howells */
yfs_fs_store_opaque_acl2(struct afs_operation * op)1945e49c7b2fSDavid Howells void yfs_fs_store_opaque_acl2(struct afs_operation *op)
1946f5e45463SDavid Howells {
1947e49c7b2fSDavid Howells struct afs_vnode_param *vp = &op->file[0];
1948f5e45463SDavid Howells struct afs_call *call;
1949e49c7b2fSDavid Howells struct afs_acl *acl = op->acl;
1950f5e45463SDavid Howells size_t size;
1951f5e45463SDavid Howells __be32 *bp;
1952f5e45463SDavid Howells
1953f5e45463SDavid Howells _enter(",%x,{%llx:%llu},,",
1954e49c7b2fSDavid Howells key_serial(op->key), vp->fid.vid, vp->fid.vnode);
1955f5e45463SDavid Howells
1956f5e45463SDavid Howells size = round_up(acl->size, 4);
1957e49c7b2fSDavid Howells call = afs_alloc_flat_call(op->net, &yfs_RXYFSStoreOpaqueACL2,
1958f5e45463SDavid Howells sizeof(__be32) * 2 +
1959f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSFid) +
1960f5e45463SDavid Howells sizeof(__be32) + size,
1961f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSFetchStatus) +
1962f5e45463SDavid Howells sizeof(struct yfs_xdr_YFSVolSync));
1963e49c7b2fSDavid Howells if (!call)
1964e49c7b2fSDavid Howells return afs_op_nomem(op);
1965f5e45463SDavid Howells
1966f5e45463SDavid Howells /* marshall the parameters */
1967f5e45463SDavid Howells bp = call->request;
1968f5e45463SDavid Howells bp = xdr_encode_u32(bp, YFSSTOREOPAQUEACL2);
1969f5e45463SDavid Howells bp = xdr_encode_u32(bp, 0); /* RPC flags */
1970e49c7b2fSDavid Howells bp = xdr_encode_YFSFid(bp, &vp->fid);
1971f5e45463SDavid Howells bp = xdr_encode_u32(bp, acl->size);
1972f5e45463SDavid Howells memcpy(bp, acl->data, acl->size);
1973f5e45463SDavid Howells if (acl->size != size)
1974f5e45463SDavid Howells memset((void *)bp + acl->size, 0, size - acl->size);
1975c80afa1dSDavid Howells bp += size / sizeof(__be32);
1976f5e45463SDavid Howells yfs_check_req(call, bp);
1977f5e45463SDavid Howells
1978abcbd3bfSDavid Howells call->fid = vp->fid;
1979e49c7b2fSDavid Howells trace_afs_make_fs_call(call, &vp->fid);
1980e49c7b2fSDavid Howells afs_make_op_call(op, call, GFP_KERNEL);
198130062bd1SDavid Howells }
1982