blob: 89b684c957b9917e6c84f4c1d9f3833e541d9561 [file] [log] [blame]
David Howells08e0e7c2007-04-26 15:55:03 -07001/* AFS File Server client stubs
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
David Howells08e0e7c2007-04-26 15:55:03 -07003 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/sched.h>
David Howells08e0e7c2007-04-26 15:55:03 -070015#include <linux/circ_buf.h>
Jeff Laytona01179e2017-12-11 06:35:11 -050016#include <linux/iversion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070018#include "afs_fs.h"
David Howellsdd9fbcb2018-04-06 14:17:24 +010019#include "xdr_fs.h"
David Howells30062bd2018-10-20 00:57:58 +010020#include "protocol_yfs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
David Howells025db802017-11-02 15:27:51 +000022static const struct afs_fid afs_zero_fid;
23
David Howellsd2ddc772017-11-02 15:27:50 +000024static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
David Howellsc435ee32017-11-02 15:27:49 +000025{
David Howellsd2ddc772017-11-02 15:27:50 +000026 call->cbi = afs_get_cb_interest(cbi);
David Howellsc435ee32017-11-02 15:27:49 +000027}
28
David Howells6db3ac32017-03-16 16:27:44 +000029/*
David Howells260a9802007-04-26 15:59:35 -070030 * decode an AFSFid block
31 */
32static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
33{
34 const __be32 *bp = *_bp;
35
36 fid->vid = ntohl(*bp++);
37 fid->vnode = ntohl(*bp++);
38 fid->unique = ntohl(*bp++);
39 *_bp = bp;
40}
41
42/*
David Howells888b3382018-04-06 14:17:24 +010043 * Dump a bad file status record.
44 */
45static void xdr_dump_bad(const __be32 *bp)
46{
47 __be32 x[4];
48 int i;
49
50 pr_notice("AFS XDR: Bad status record\n");
51 for (i = 0; i < 5 * 4 * 4; i += 16) {
52 memcpy(x, bp, 16);
53 bp += 4;
54 pr_notice("%03x: %08x %08x %08x %08x\n",
55 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
56 }
57
58 memcpy(x, bp, 4);
59 pr_notice("0x50: %08x\n", ntohl(x[0]));
60}
61
62/*
David Howellsdd9fbcb2018-04-06 14:17:24 +010063 * decode an AFSFetchStatus block
64 */
David Howellsa58823a2019-05-09 15:16:10 +010065static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
66 struct afs_call *call,
67 struct afs_status_cb *scb)
David Howellsdd9fbcb2018-04-06 14:17:24 +010068{
69 const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
David Howellsa58823a2019-05-09 15:16:10 +010070 struct afs_file_status *status = &scb->status;
David Howells684b0f62018-05-10 21:51:47 +010071 bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
David Howellsdd9fbcb2018-04-06 14:17:24 +010072 u64 data_version, size;
73 u32 type, abort_code;
David Howellsdd9fbcb2018-04-06 14:17:24 +010074
David Howells684b0f62018-05-10 21:51:47 +010075 abort_code = ntohl(xdr->abort_code);
76
David Howellsdd9fbcb2018-04-06 14:17:24 +010077 if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
David Howells684b0f62018-05-10 21:51:47 +010078 if (xdr->if_version == htonl(0) &&
79 abort_code != 0 &&
80 inline_error) {
81 /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
82 * whereby it doesn't set the interface version in the error
83 * case.
84 */
85 status->abort_code = abort_code;
Al Virode52cf92018-06-02 18:08:11 -040086 return 0;
David Howells684b0f62018-05-10 21:51:47 +010087 }
88
David Howellsdd9fbcb2018-04-06 14:17:24 +010089 pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
90 goto bad;
91 }
92
David Howells684b0f62018-05-10 21:51:47 +010093 if (abort_code != 0 && inline_error) {
94 status->abort_code = abort_code;
Al Virode52cf92018-06-02 18:08:11 -040095 return 0;
David Howells684b0f62018-05-10 21:51:47 +010096 }
97
David Howellsdd9fbcb2018-04-06 14:17:24 +010098 type = ntohl(xdr->type);
David Howellsdd9fbcb2018-04-06 14:17:24 +010099 switch (type) {
100 case AFS_FTYPE_FILE:
101 case AFS_FTYPE_DIR:
102 case AFS_FTYPE_SYMLINK:
David Howellsdd9fbcb2018-04-06 14:17:24 +0100103 status->type = type;
104 break;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100105 default:
106 goto bad;
107 }
108
David Howellsa58823a2019-05-09 15:16:10 +0100109 status->nlink = ntohl(xdr->nlink);
110 status->author = ntohl(xdr->author);
111 status->owner = ntohl(xdr->owner);
112 status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */
113 status->anon_access = ntohl(xdr->anon_access);
114 status->mode = ntohl(xdr->mode) & S_IALLUGO;
115 status->group = ntohl(xdr->group);
116 status->lock_count = ntohl(xdr->lock_count);
David Howellsdd9fbcb2018-04-06 14:17:24 +0100117
David Howellsd4936802018-10-20 00:57:58 +0100118 status->mtime_client.tv_sec = ntohl(xdr->mtime_client);
119 status->mtime_client.tv_nsec = 0;
120 status->mtime_server.tv_sec = ntohl(xdr->mtime_server);
121 status->mtime_server.tv_nsec = 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100122
123 size = (u64)ntohl(xdr->size_lo);
124 size |= (u64)ntohl(xdr->size_hi) << 32;
David Howells63a46812018-04-06 14:17:25 +0100125 status->size = size;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100126
127 data_version = (u64)ntohl(xdr->data_version_lo);
128 data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
David Howellsa58823a2019-05-09 15:16:10 +0100129 status->data_version = data_version;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100130
131 *_bp = (const void *)*_bp + sizeof(*xdr);
David Howellsc875c762018-05-23 11:32:06 +0100132 return 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100133
134bad:
135 xdr_dump_bad(*_bp);
David Howells160cb952018-10-20 00:57:56 +0100136 return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
David Howellsc875c762018-05-23 11:32:06 +0100137}
138
David Howells78107052019-05-09 17:56:53 +0100139static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
140{
141 return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry;
142}
143
David Howellsa58823a2019-05-09 15:16:10 +0100144static void xdr_decode_AFSCallBack(const __be32 **_bp,
145 struct afs_call *call,
146 struct afs_status_cb *scb)
David Howells78107052019-05-09 17:56:53 +0100147{
David Howellsa58823a2019-05-09 15:16:10 +0100148 struct afs_callback *cb = &scb->callback;
David Howells78107052019-05-09 17:56:53 +0100149 const __be32 *bp = *_bp;
150
David Howells7c712452019-05-14 15:35:44 +0100151 bp++; /* version */
David Howells78107052019-05-09 17:56:53 +0100152 cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++));
David Howells7c712452019-05-14 15:35:44 +0100153 bp++; /* type */
David Howellsa58823a2019-05-09 15:16:10 +0100154 scb->have_cb = true;
David Howells78107052019-05-09 17:56:53 +0100155 *_bp = bp;
156}
157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158/*
David Howells08e0e7c2007-04-26 15:55:03 -0700159 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 */
David Howells08e0e7c2007-04-26 15:55:03 -0700161static void xdr_decode_AFSVolSync(const __be32 **_bp,
162 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163{
David Howells08e0e7c2007-04-26 15:55:03 -0700164 const __be32 *bp = *_bp;
David Howells30062bd2018-10-20 00:57:58 +0100165 u32 creation;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
David Howells30062bd2018-10-20 00:57:58 +0100167 creation = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -0700168 bp++; /* spare2 */
169 bp++; /* spare3 */
170 bp++; /* spare4 */
171 bp++; /* spare5 */
172 bp++; /* spare6 */
173 *_bp = bp;
David Howells30062bd2018-10-20 00:57:58 +0100174
175 if (volsync)
176 volsync->creation = creation;
David Howellsec268152007-04-26 15:49:28 -0700177}
David Howells08e0e7c2007-04-26 15:55:03 -0700178
179/*
David Howells31143d52007-05-09 02:33:46 -0700180 * encode the requested attributes into an AFSStoreStatus block
181 */
182static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
183{
184 __be32 *bp = *_bp;
185 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
186
187 mask = 0;
188 if (attr->ia_valid & ATTR_MTIME) {
189 mask |= AFS_SET_MTIME;
190 mtime = attr->ia_mtime.tv_sec;
191 }
192
193 if (attr->ia_valid & ATTR_UID) {
194 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800195 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700196 }
197
198 if (attr->ia_valid & ATTR_GID) {
199 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800200 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700201 }
202
203 if (attr->ia_valid & ATTR_MODE) {
204 mask |= AFS_SET_MODE;
205 mode = attr->ia_mode & S_IALLUGO;
206 }
207
208 *bp++ = htonl(mask);
209 *bp++ = htonl(mtime);
210 *bp++ = htonl(owner);
211 *bp++ = htonl(group);
212 *bp++ = htonl(mode);
213 *bp++ = 0; /* segment size */
214 *_bp = bp;
215}
216
217/*
David Howells45222b92007-05-10 22:22:20 -0700218 * decode an AFSFetchVolumeStatus block
219 */
220static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
221 struct afs_volume_status *vs)
222{
223 const __be32 *bp = *_bp;
224
225 vs->vid = ntohl(*bp++);
226 vs->parent_id = ntohl(*bp++);
227 vs->online = ntohl(*bp++);
228 vs->in_service = ntohl(*bp++);
229 vs->blessed = ntohl(*bp++);
230 vs->needs_salvage = ntohl(*bp++);
231 vs->type = ntohl(*bp++);
232 vs->min_quota = ntohl(*bp++);
233 vs->max_quota = ntohl(*bp++);
234 vs->blocks_in_use = ntohl(*bp++);
235 vs->part_blocks_avail = ntohl(*bp++);
236 vs->part_max_blocks = ntohl(*bp++);
David Howells30062bd2018-10-20 00:57:58 +0100237 vs->vol_copy_date = 0;
238 vs->vol_backup_date = 0;
David Howells45222b92007-05-10 22:22:20 -0700239 *_bp = bp;
240}
241
242/*
David Howells08e0e7c2007-04-26 15:55:03 -0700243 * deliver reply data to an FS.FetchStatus
244 */
David Howells5cf9dd52018-04-09 21:12:31 +0100245static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700246{
247 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100248 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700249
David Howellsd0016482016-08-30 20:42:14 +0100250 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100251 if (ret < 0)
252 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700253
254 /* unmarshall the reply once we've received all of it */
255 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +0100256 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +0100257 if (ret < 0)
258 return ret;
David Howellsa58823a2019-05-09 15:16:10 +0100259 xdr_decode_AFSCallBack(&bp, call, call->out_scb);
David Howellsffba7182019-05-09 22:22:50 +0100260 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells08e0e7c2007-04-26 15:55:03 -0700261
262 _leave(" = 0 [done]");
263 return 0;
264}
265
266/*
267 * FS.FetchStatus operation type
268 */
David Howells5cf9dd52018-04-09 21:12:31 +0100269static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
270 .name = "FS.FetchStatus(vnode)",
David Howells025db802017-11-02 15:27:51 +0000271 .op = afs_FS_FetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100272 .deliver = afs_deliver_fs_fetch_status_vnode,
David Howells08e0e7c2007-04-26 15:55:03 -0700273 .destructor = afs_flat_call_destructor,
274};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276/*
277 * fetch the status information for a file
278 */
David Howellsa58823a2019-05-09 15:16:10 +0100279int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb,
280 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
David Howellsd2ddc772017-11-02 15:27:50 +0000282 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700283 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000284 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 __be32 *bp;
286
David Howells30062bd2018-10-20 00:57:58 +0100287 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +0100288 return yfs_fs_fetch_file_status(fc, scb, volsync);
David Howells30062bd2018-10-20 00:57:58 +0100289
David Howells3b6492d2018-10-20 00:57:57 +0100290 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000291 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
David Howells5cf9dd52018-04-09 21:12:31 +0100293 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
294 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000295 if (!call) {
296 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700297 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
David Howellsd2ddc772017-11-02 15:27:50 +0000300 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +0100301 call->out_scb = scb;
David Howellsffba7182019-05-09 22:22:50 +0100302 call->out_volsync = volsync;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
304 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700305 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 bp[0] = htonl(FSFETCHSTATUS);
307 bp[1] = htonl(vnode->fid.vid);
308 bp[2] = htonl(vnode->fid.vnode);
309 bp[3] = htonl(vnode->fid.unique);
310
David Howellsd2ddc772017-11-02 15:27:50 +0000311 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000312 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +0100313
David Howells20b83912019-05-08 16:16:31 +0100314 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +0100315 afs_make_call(&fc->ac, call, GFP_NOFS);
316 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsec268152007-04-26 15:49:28 -0700317}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319/*
David Howells08e0e7c2007-04-26 15:55:03 -0700320 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 */
David Howellsd0016482016-08-30 20:42:14 +0100322static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
David Howellsffba7182019-05-09 22:22:50 +0100324 struct afs_read *req = call->read_request;
David Howells08e0e7c2007-04-26 15:55:03 -0700325 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000326 unsigned int size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700328
David Howells12bdcf32018-10-20 00:57:56 +0100329 _enter("{%u,%zu/%llu}",
330 call->unmarshall, iov_iter_count(&call->iter), req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700331
332 switch (call->unmarshall) {
333 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000334 req->actual_len = 0;
David Howells12bdcf32018-10-20 00:57:56 +0100335 req->index = 0;
336 req->offset = req->pos & (PAGE_SIZE - 1);
David Howells08e0e7c2007-04-26 15:55:03 -0700337 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +0100338 if (call->operation_ID == FSFETCHDATA64) {
339 afs_extract_to_tmp64(call);
340 } else {
341 call->tmp_u = htonl(0);
342 afs_extract_to_tmp(call);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700343 }
David Howells08e0e7c2007-04-26 15:55:03 -0700344
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -0600345 /* Fall through - and extract the returned data length */
David Howells12bdcf32018-10-20 00:57:56 +0100346 case 1:
David Howells08e0e7c2007-04-26 15:55:03 -0700347 _debug("extract data length");
David Howells12bdcf32018-10-20 00:57:56 +0100348 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +0100349 if (ret < 0)
350 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700351
David Howells12bdcf32018-10-20 00:57:56 +0100352 req->actual_len = be64_to_cpu(call->tmp64);
David Howells196ee9c2017-01-05 10:38:34 +0000353 _debug("DATA length: %llu", req->actual_len);
David Howells12bdcf32018-10-20 00:57:56 +0100354 req->remain = min(req->len, req->actual_len);
355 if (req->remain == 0)
David Howells196ee9c2017-01-05 10:38:34 +0000356 goto no_more_data;
David Howells12bdcf32018-10-20 00:57:56 +0100357
David Howells08e0e7c2007-04-26 15:55:03 -0700358 call->unmarshall++;
359
David Howells196ee9c2017-01-05 10:38:34 +0000360 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000361 ASSERTCMP(req->index, <, req->nr_pages);
David Howells12bdcf32018-10-20 00:57:56 +0100362 if (req->remain > PAGE_SIZE - req->offset)
363 size = PAGE_SIZE - req->offset;
David Howells196ee9c2017-01-05 10:38:34 +0000364 else
365 size = req->remain;
David Howells12bdcf32018-10-20 00:57:56 +0100366 call->bvec[0].bv_len = size;
367 call->bvec[0].bv_offset = req->offset;
368 call->bvec[0].bv_page = req->pages[req->index];
369 iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
370 ASSERTCMP(size, <=, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000371
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -0600372 /* Fall through - and extract the returned data */
David Howells12bdcf32018-10-20 00:57:56 +0100373 case 2:
374 _debug("extract data %zu/%llu",
375 iov_iter_count(&call->iter), req->remain);
David Howells196ee9c2017-01-05 10:38:34 +0000376
David Howells12bdcf32018-10-20 00:57:56 +0100377 ret = afs_extract_data(call, true);
David Howells196ee9c2017-01-05 10:38:34 +0000378 if (ret < 0)
379 return ret;
David Howells12bdcf32018-10-20 00:57:56 +0100380 req->remain -= call->bvec[0].bv_len;
381 req->offset += call->bvec[0].bv_len;
382 ASSERTCMP(req->offset, <=, PAGE_SIZE);
383 if (req->offset == PAGE_SIZE) {
384 req->offset = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000385 if (req->page_done)
David Howellsa58823a2019-05-09 15:16:10 +0100386 req->page_done(req);
David Howells29f06982017-03-16 16:27:46 +0000387 req->index++;
David Howells12bdcf32018-10-20 00:57:56 +0100388 if (req->remain > 0)
David Howells196ee9c2017-01-05 10:38:34 +0000389 goto begin_page;
David Howells08e0e7c2007-04-26 15:55:03 -0700390 }
David Howells12bdcf32018-10-20 00:57:56 +0100391
392 ASSERTCMP(req->remain, ==, 0);
393 if (req->actual_len <= req->len)
394 goto no_more_data;
David Howells6db3ac32017-03-16 16:27:44 +0000395
396 /* Discard any excess data the server gave us */
David Howells12bdcf32018-10-20 00:57:56 +0100397 iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
398 call->unmarshall = 3;
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -0600399
400 /* Fall through */
David Howells12bdcf32018-10-20 00:57:56 +0100401 case 3:
402 _debug("extract discard %zu/%llu",
403 iov_iter_count(&call->iter), req->actual_len - req->len);
David Howells6db3ac32017-03-16 16:27:44 +0000404
David Howells12bdcf32018-10-20 00:57:56 +0100405 ret = afs_extract_data(call, true);
David Howells6db3ac32017-03-16 16:27:44 +0000406 if (ret < 0)
407 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700408
David Howells196ee9c2017-01-05 10:38:34 +0000409 no_more_data:
David Howells12bdcf32018-10-20 00:57:56 +0100410 call->unmarshall = 4;
411 afs_extract_to_buf(call, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700412
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -0600413 /* Fall through - and extract the metadata */
David Howells12bdcf32018-10-20 00:57:56 +0100414 case 4:
415 ret = afs_extract_data(call, false);
David Howells372ee162016-08-03 14:11:40 +0100416 if (ret < 0)
417 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700418
419 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +0100420 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +0100421 if (ret < 0)
422 return ret;
David Howellsa58823a2019-05-09 15:16:10 +0100423 xdr_decode_AFSCallBack(&bp, call, call->out_scb);
David Howellsffba7182019-05-09 22:22:50 +0100424 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells08e0e7c2007-04-26 15:55:03 -0700425
David Howellsa58823a2019-05-09 15:16:10 +0100426 req->data_version = call->out_scb->status.data_version;
427 req->file_size = call->out_scb->status.size;
428
David Howells08e0e7c2007-04-26 15:55:03 -0700429 call->unmarshall++;
430
David Howells12bdcf32018-10-20 00:57:56 +0100431 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700432 break;
433 }
434
David Howells6db3ac32017-03-16 16:27:44 +0000435 for (; req->index < req->nr_pages; req->index++) {
David Howells12bdcf32018-10-20 00:57:56 +0100436 if (req->offset < PAGE_SIZE)
David Howells6db3ac32017-03-16 16:27:44 +0000437 zero_user_segment(req->pages[req->index],
David Howells12bdcf32018-10-20 00:57:56 +0100438 req->offset, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000439 if (req->page_done)
David Howellsa58823a2019-05-09 15:16:10 +0100440 req->page_done(req);
David Howells12bdcf32018-10-20 00:57:56 +0100441 req->offset = 0;
David Howells416351f2007-05-09 02:33:45 -0700442 }
443
David Howells08e0e7c2007-04-26 15:55:03 -0700444 _leave(" = 0 [done]");
445 return 0;
446}
447
David Howells196ee9c2017-01-05 10:38:34 +0000448static void afs_fetch_data_destructor(struct afs_call *call)
449{
David Howellsffba7182019-05-09 22:22:50 +0100450 struct afs_read *req = call->read_request;
David Howells196ee9c2017-01-05 10:38:34 +0000451
452 afs_put_read(req);
453 afs_flat_call_destructor(call);
454}
455
David Howells08e0e7c2007-04-26 15:55:03 -0700456/*
457 * FS.FetchData operation type
458 */
459static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700460 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000461 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700462 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000463 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700464};
465
David Howellsb9b1f8d2007-05-10 03:15:21 -0700466static const struct afs_call_type afs_RXFSFetchData64 = {
467 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000468 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700469 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000470 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700471};
472
473/*
474 * fetch data from a very large file
475 */
David Howellsa58823a2019-05-09 15:16:10 +0100476static int afs_fs_fetch_data64(struct afs_fs_cursor *fc,
477 struct afs_status_cb *scb,
478 struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700479{
David Howellsd2ddc772017-11-02 15:27:50 +0000480 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700481 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000482 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700483 __be32 *bp;
484
485 _enter("");
486
David Howellsf044c882017-11-02 15:27:45 +0000487 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700488 if (!call)
489 return -ENOMEM;
490
David Howellsd2ddc772017-11-02 15:27:50 +0000491 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +0100492 call->out_scb = scb;
David Howellsffba7182019-05-09 22:22:50 +0100493 call->out_volsync = NULL;
494 call->read_request = req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700495
496 /* marshall the parameters */
497 bp = call->request;
498 bp[0] = htonl(FSFETCHDATA64);
499 bp[1] = htonl(vnode->fid.vid);
500 bp[2] = htonl(vnode->fid.vnode);
501 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000502 bp[4] = htonl(upper_32_bits(req->pos));
503 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700504 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000505 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700506
David Howellsf3ddee82018-04-06 14:17:25 +0100507 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000508 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000509 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +0100510 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +0100511 afs_make_call(&fc->ac, call, GFP_NOFS);
512 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700513}
514
David Howells08e0e7c2007-04-26 15:55:03 -0700515/*
516 * fetch data from a file
517 */
David Howellsa58823a2019-05-09 15:16:10 +0100518int afs_fs_fetch_data(struct afs_fs_cursor *fc,
519 struct afs_status_cb *scb,
520 struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700521{
David Howellsd2ddc772017-11-02 15:27:50 +0000522 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700523 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000524 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 __be32 *bp;
526
David Howells30062bd2018-10-20 00:57:58 +0100527 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +0100528 return yfs_fs_fetch_data(fc, scb, req);
David Howells30062bd2018-10-20 00:57:58 +0100529
David Howells196ee9c2017-01-05 10:38:34 +0000530 if (upper_32_bits(req->pos) ||
531 upper_32_bits(req->len) ||
532 upper_32_bits(req->pos + req->len))
David Howellsa58823a2019-05-09 15:16:10 +0100533 return afs_fs_fetch_data64(fc, scb, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700534
David Howells08e0e7c2007-04-26 15:55:03 -0700535 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
David Howellsf044c882017-11-02 15:27:45 +0000537 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700538 if (!call)
539 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
David Howellsd2ddc772017-11-02 15:27:50 +0000541 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +0100542 call->out_scb = scb;
David Howellsffba7182019-05-09 22:22:50 +0100543 call->out_volsync = NULL;
544 call->read_request = req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700547 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700549 bp[1] = htonl(vnode->fid.vid);
550 bp[2] = htonl(vnode->fid.vnode);
551 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000552 bp[4] = htonl(lower_32_bits(req->pos));
553 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
David Howellsf3ddee82018-04-06 14:17:25 +0100555 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000556 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000557 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +0100558 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +0100559 afs_make_call(&fc->ac, call, GFP_NOFS);
560 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsec268152007-04-26 15:49:28 -0700561}
David Howells260a9802007-04-26 15:59:35 -0700562
563/*
564 * deliver reply data to an FS.CreateFile or an FS.MakeDir
565 */
David Howellsd0016482016-08-30 20:42:14 +0100566static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700567{
David Howells260a9802007-04-26 15:59:35 -0700568 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100569 int ret;
David Howells260a9802007-04-26 15:59:35 -0700570
David Howellsd0016482016-08-30 20:42:14 +0100571 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100572 if (ret < 0)
573 return ret;
David Howells260a9802007-04-26 15:59:35 -0700574
575 /* unmarshall the reply once we've received all of it */
576 bp = call->buffer;
David Howellsffba7182019-05-09 22:22:50 +0100577 xdr_decode_AFSFid(&bp, call->out_fid);
David Howellsa58823a2019-05-09 15:16:10 +0100578 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +0100579 if (ret < 0)
580 return ret;
David Howellsa58823a2019-05-09 15:16:10 +0100581 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
David Howells160cb952018-10-20 00:57:56 +0100582 if (ret < 0)
583 return ret;
David Howellsa58823a2019-05-09 15:16:10 +0100584 xdr_decode_AFSCallBack(&bp, call, call->out_scb);
David Howellsffba7182019-05-09 22:22:50 +0100585 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells260a9802007-04-26 15:59:35 -0700586
587 _leave(" = 0 [done]");
588 return 0;
589}
590
591/*
592 * FS.CreateFile and FS.MakeDir operation type
593 */
David Howells025db802017-11-02 15:27:51 +0000594static const struct afs_call_type afs_RXFSCreateFile = {
595 .name = "FS.CreateFile",
596 .op = afs_FS_CreateFile,
597 .deliver = afs_deliver_fs_create_vnode,
598 .destructor = afs_flat_call_destructor,
599};
600
601static const struct afs_call_type afs_RXFSMakeDir = {
602 .name = "FS.MakeDir",
603 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700604 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700605 .destructor = afs_flat_call_destructor,
606};
607
608/*
609 * create a file or make a directory
610 */
David Howells8b2a4642017-11-02 15:27:50 +0000611int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700612 const char *name,
613 umode_t mode,
David Howellsa58823a2019-05-09 15:16:10 +0100614 struct afs_status_cb *dvnode_scb,
David Howells260a9802007-04-26 15:59:35 -0700615 struct afs_fid *newfid,
David Howellsa58823a2019-05-09 15:16:10 +0100616 struct afs_status_cb *new_scb)
David Howells260a9802007-04-26 15:59:35 -0700617{
David Howellsffba7182019-05-09 22:22:50 +0100618 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700619 struct afs_call *call;
David Howellsffba7182019-05-09 22:22:50 +0100620 struct afs_net *net = afs_v2net(dvnode);
David Howells260a9802007-04-26 15:59:35 -0700621 size_t namesz, reqsz, padsz;
622 __be32 *bp;
623
David Howells30062bd2018-10-20 00:57:58 +0100624 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){
625 if (S_ISDIR(mode))
David Howellsa58823a2019-05-09 15:16:10 +0100626 return yfs_fs_make_dir(fc, name, mode, dvnode_scb,
627 newfid, new_scb);
David Howells30062bd2018-10-20 00:57:58 +0100628 else
David Howellsa58823a2019-05-09 15:16:10 +0100629 return yfs_fs_create_file(fc, name, mode, dvnode_scb,
630 newfid, new_scb);
David Howells30062bd2018-10-20 00:57:58 +0100631 }
632
David Howells260a9802007-04-26 15:59:35 -0700633 _enter("");
634
635 namesz = strlen(name);
636 padsz = (4 - (namesz & 3)) & 3;
637 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
638
David Howells025db802017-11-02 15:27:51 +0000639 call = afs_alloc_flat_call(
640 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
641 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700642 if (!call)
643 return -ENOMEM;
644
David Howellsd2ddc772017-11-02 15:27:50 +0000645 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +0100646 call->out_dir_scb = dvnode_scb;
David Howellsffba7182019-05-09 22:22:50 +0100647 call->out_fid = newfid;
David Howellsa58823a2019-05-09 15:16:10 +0100648 call->out_scb = new_scb;
David Howells260a9802007-04-26 15:59:35 -0700649
650 /* marshall the parameters */
651 bp = call->request;
652 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
David Howellsffba7182019-05-09 22:22:50 +0100653 *bp++ = htonl(dvnode->fid.vid);
654 *bp++ = htonl(dvnode->fid.vnode);
655 *bp++ = htonl(dvnode->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700656 *bp++ = htonl(namesz);
657 memcpy(bp, name, namesz);
658 bp = (void *) bp + namesz;
659 if (padsz > 0) {
660 memset(bp, 0, padsz);
661 bp = (void *) bp + padsz;
662 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000663 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
David Howellsffba7182019-05-09 22:22:50 +0100664 *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700665 *bp++ = 0; /* owner */
666 *bp++ = 0; /* group */
667 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
668 *bp++ = 0; /* segment size */
669
David Howellsd2ddc772017-11-02 15:27:50 +0000670 afs_use_fs_server(call, fc->cbi);
David Howellsffba7182019-05-09 22:22:50 +0100671 trace_afs_make_fs_call1(call, &dvnode->fid, name);
David Howells20b83912019-05-08 16:16:31 +0100672 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +0100673 afs_make_call(&fc->ac, call, GFP_NOFS);
674 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -0700675}
676
677/*
David Howellsffba7182019-05-09 22:22:50 +0100678 * Deliver reply data to any operation that returns directory status and volume
Joe Gorseb10494a2019-04-25 14:26:52 +0100679 * sync.
David Howells260a9802007-04-26 15:59:35 -0700680 */
David Howellsffba7182019-05-09 22:22:50 +0100681static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700682{
David Howells260a9802007-04-26 15:59:35 -0700683 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100684 int ret;
David Howells260a9802007-04-26 15:59:35 -0700685
David Howellsd0016482016-08-30 20:42:14 +0100686 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100687 if (ret < 0)
688 return ret;
David Howells260a9802007-04-26 15:59:35 -0700689
690 /* unmarshall the reply once we've received all of it */
691 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +0100692 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
David Howells160cb952018-10-20 00:57:56 +0100693 if (ret < 0)
694 return ret;
David Howellsffba7182019-05-09 22:22:50 +0100695 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells260a9802007-04-26 15:59:35 -0700696
697 _leave(" = 0 [done]");
698 return 0;
699}
700
701/*
702 * FS.RemoveDir/FS.RemoveFile operation type
703 */
David Howells025db802017-11-02 15:27:51 +0000704static const struct afs_call_type afs_RXFSRemoveFile = {
705 .name = "FS.RemoveFile",
706 .op = afs_FS_RemoveFile,
David Howellsffba7182019-05-09 22:22:50 +0100707 .deliver = afs_deliver_fs_dir_status_and_vol,
David Howells025db802017-11-02 15:27:51 +0000708 .destructor = afs_flat_call_destructor,
709};
710
711static const struct afs_call_type afs_RXFSRemoveDir = {
712 .name = "FS.RemoveDir",
713 .op = afs_FS_RemoveDir,
David Howellsffba7182019-05-09 22:22:50 +0100714 .deliver = afs_deliver_fs_dir_status_and_vol,
David Howells260a9802007-04-26 15:59:35 -0700715 .destructor = afs_flat_call_destructor,
716};
717
718/*
719 * remove a file or directory
720 */
David Howells30062bd2018-10-20 00:57:58 +0100721int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
David Howellsa58823a2019-05-09 15:16:10 +0100722 const char *name, bool isdir, struct afs_status_cb *dvnode_scb)
David Howells260a9802007-04-26 15:59:35 -0700723{
David Howells30062bd2018-10-20 00:57:58 +0100724 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700725 struct afs_call *call;
David Howells30062bd2018-10-20 00:57:58 +0100726 struct afs_net *net = afs_v2net(dvnode);
David Howells260a9802007-04-26 15:59:35 -0700727 size_t namesz, reqsz, padsz;
728 __be32 *bp;
729
David Howells30062bd2018-10-20 00:57:58 +0100730 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +0100731 return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb);
David Howells30062bd2018-10-20 00:57:58 +0100732
David Howells260a9802007-04-26 15:59:35 -0700733 _enter("");
734
735 namesz = strlen(name);
736 padsz = (4 - (namesz & 3)) & 3;
737 reqsz = (5 * 4) + namesz + padsz;
738
David Howells025db802017-11-02 15:27:51 +0000739 call = afs_alloc_flat_call(
740 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
741 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700742 if (!call)
743 return -ENOMEM;
744
David Howellsd2ddc772017-11-02 15:27:50 +0000745 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +0100746 call->out_dir_scb = dvnode_scb;
David Howells260a9802007-04-26 15:59:35 -0700747
748 /* marshall the parameters */
749 bp = call->request;
750 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
David Howells30062bd2018-10-20 00:57:58 +0100751 *bp++ = htonl(dvnode->fid.vid);
752 *bp++ = htonl(dvnode->fid.vnode);
753 *bp++ = htonl(dvnode->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700754 *bp++ = htonl(namesz);
755 memcpy(bp, name, namesz);
756 bp = (void *) bp + namesz;
757 if (padsz > 0) {
758 memset(bp, 0, padsz);
759 bp = (void *) bp + padsz;
760 }
761
David Howellsd2ddc772017-11-02 15:27:50 +0000762 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +0100763 trace_afs_make_fs_call1(call, &dvnode->fid, name);
David Howells20b83912019-05-08 16:16:31 +0100764 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +0100765 afs_make_call(&fc->ac, call, GFP_NOFS);
766 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -0700767}
768
769/*
770 * deliver reply data to an FS.Link
771 */
David Howellsd0016482016-08-30 20:42:14 +0100772static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700773{
David Howells260a9802007-04-26 15:59:35 -0700774 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100775 int ret;
David Howells260a9802007-04-26 15:59:35 -0700776
David Howellsd0016482016-08-30 20:42:14 +0100777 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700778
David Howellsd0016482016-08-30 20:42:14 +0100779 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100780 if (ret < 0)
781 return ret;
David Howells260a9802007-04-26 15:59:35 -0700782
783 /* unmarshall the reply once we've received all of it */
784 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +0100785 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +0100786 if (ret < 0)
787 return ret;
David Howellsa58823a2019-05-09 15:16:10 +0100788 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
David Howells160cb952018-10-20 00:57:56 +0100789 if (ret < 0)
790 return ret;
David Howellsffba7182019-05-09 22:22:50 +0100791 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells260a9802007-04-26 15:59:35 -0700792
793 _leave(" = 0 [done]");
794 return 0;
795}
796
797/*
798 * FS.Link operation type
799 */
800static const struct afs_call_type afs_RXFSLink = {
801 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000802 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700803 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700804 .destructor = afs_flat_call_destructor,
805};
806
807/*
808 * make a hard link
809 */
David Howellsd2ddc772017-11-02 15:27:50 +0000810int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
David Howellsa58823a2019-05-09 15:16:10 +0100811 const char *name,
812 struct afs_status_cb *dvnode_scb,
813 struct afs_status_cb *vnode_scb)
David Howells260a9802007-04-26 15:59:35 -0700814{
David Howellsd2ddc772017-11-02 15:27:50 +0000815 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700816 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000817 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700818 size_t namesz, reqsz, padsz;
819 __be32 *bp;
820
David Howells30062bd2018-10-20 00:57:58 +0100821 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +0100822 return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb);
David Howells30062bd2018-10-20 00:57:58 +0100823
David Howells260a9802007-04-26 15:59:35 -0700824 _enter("");
825
826 namesz = strlen(name);
827 padsz = (4 - (namesz & 3)) & 3;
828 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
829
David Howellsf044c882017-11-02 15:27:45 +0000830 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700831 if (!call)
832 return -ENOMEM;
833
David Howellsd2ddc772017-11-02 15:27:50 +0000834 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +0100835 call->out_dir_scb = dvnode_scb;
836 call->out_scb = vnode_scb;
David Howells260a9802007-04-26 15:59:35 -0700837
838 /* marshall the parameters */
839 bp = call->request;
840 *bp++ = htonl(FSLINK);
841 *bp++ = htonl(dvnode->fid.vid);
842 *bp++ = htonl(dvnode->fid.vnode);
843 *bp++ = htonl(dvnode->fid.unique);
844 *bp++ = htonl(namesz);
845 memcpy(bp, name, namesz);
846 bp = (void *) bp + namesz;
847 if (padsz > 0) {
848 memset(bp, 0, padsz);
849 bp = (void *) bp + padsz;
850 }
851 *bp++ = htonl(vnode->fid.vid);
852 *bp++ = htonl(vnode->fid.vnode);
853 *bp++ = htonl(vnode->fid.unique);
854
David Howellsd2ddc772017-11-02 15:27:50 +0000855 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +0100856 trace_afs_make_fs_call1(call, &vnode->fid, name);
David Howells20b83912019-05-08 16:16:31 +0100857 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +0100858 afs_make_call(&fc->ac, call, GFP_NOFS);
859 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -0700860}
861
862/*
863 * deliver reply data to an FS.Symlink
864 */
David Howellsd0016482016-08-30 20:42:14 +0100865static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700866{
David Howells260a9802007-04-26 15:59:35 -0700867 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100868 int ret;
David Howells260a9802007-04-26 15:59:35 -0700869
David Howellsd0016482016-08-30 20:42:14 +0100870 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700871
David Howellsd0016482016-08-30 20:42:14 +0100872 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100873 if (ret < 0)
874 return ret;
David Howells260a9802007-04-26 15:59:35 -0700875
876 /* unmarshall the reply once we've received all of it */
877 bp = call->buffer;
David Howellsffba7182019-05-09 22:22:50 +0100878 xdr_decode_AFSFid(&bp, call->out_fid);
David Howellsa58823a2019-05-09 15:16:10 +0100879 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +0100880 if (ret < 0)
881 return ret;
David Howellsa58823a2019-05-09 15:16:10 +0100882 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
David Howells160cb952018-10-20 00:57:56 +0100883 if (ret < 0)
884 return ret;
David Howellsffba7182019-05-09 22:22:50 +0100885 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells260a9802007-04-26 15:59:35 -0700886
887 _leave(" = 0 [done]");
888 return 0;
889}
890
891/*
892 * FS.Symlink operation type
893 */
894static const struct afs_call_type afs_RXFSSymlink = {
895 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +0000896 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -0700897 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700898 .destructor = afs_flat_call_destructor,
899};
900
901/*
902 * create a symbolic link
903 */
David Howells8b2a4642017-11-02 15:27:50 +0000904int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700905 const char *name,
906 const char *contents,
David Howellsa58823a2019-05-09 15:16:10 +0100907 struct afs_status_cb *dvnode_scb,
David Howells260a9802007-04-26 15:59:35 -0700908 struct afs_fid *newfid,
David Howellsa58823a2019-05-09 15:16:10 +0100909 struct afs_status_cb *new_scb)
David Howells260a9802007-04-26 15:59:35 -0700910{
David Howellsffba7182019-05-09 22:22:50 +0100911 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700912 struct afs_call *call;
David Howellsffba7182019-05-09 22:22:50 +0100913 struct afs_net *net = afs_v2net(dvnode);
David Howells260a9802007-04-26 15:59:35 -0700914 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
915 __be32 *bp;
916
David Howells30062bd2018-10-20 00:57:58 +0100917 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +0100918 return yfs_fs_symlink(fc, name, contents, dvnode_scb,
919 newfid, new_scb);
David Howells30062bd2018-10-20 00:57:58 +0100920
David Howells260a9802007-04-26 15:59:35 -0700921 _enter("");
922
923 namesz = strlen(name);
924 padsz = (4 - (namesz & 3)) & 3;
925
926 c_namesz = strlen(contents);
927 c_padsz = (4 - (c_namesz & 3)) & 3;
928
929 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
930
David Howellsf044c882017-11-02 15:27:45 +0000931 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700932 (3 + 21 + 21 + 6) * 4);
933 if (!call)
934 return -ENOMEM;
935
David Howellsd2ddc772017-11-02 15:27:50 +0000936 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +0100937 call->out_dir_scb = dvnode_scb;
David Howellsffba7182019-05-09 22:22:50 +0100938 call->out_fid = newfid;
David Howellsa58823a2019-05-09 15:16:10 +0100939 call->out_scb = new_scb;
David Howells260a9802007-04-26 15:59:35 -0700940
941 /* marshall the parameters */
942 bp = call->request;
943 *bp++ = htonl(FSSYMLINK);
David Howellsffba7182019-05-09 22:22:50 +0100944 *bp++ = htonl(dvnode->fid.vid);
945 *bp++ = htonl(dvnode->fid.vnode);
946 *bp++ = htonl(dvnode->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700947 *bp++ = htonl(namesz);
948 memcpy(bp, name, namesz);
949 bp = (void *) bp + namesz;
950 if (padsz > 0) {
951 memset(bp, 0, padsz);
952 bp = (void *) bp + padsz;
953 }
954 *bp++ = htonl(c_namesz);
955 memcpy(bp, contents, c_namesz);
956 bp = (void *) bp + c_namesz;
957 if (c_padsz > 0) {
958 memset(bp, 0, c_padsz);
959 bp = (void *) bp + c_padsz;
960 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000961 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
David Howellsffba7182019-05-09 22:22:50 +0100962 *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700963 *bp++ = 0; /* owner */
964 *bp++ = 0; /* group */
965 *bp++ = htonl(S_IRWXUGO); /* unix mode */
966 *bp++ = 0; /* segment size */
967
David Howellsd2ddc772017-11-02 15:27:50 +0000968 afs_use_fs_server(call, fc->cbi);
David Howellsffba7182019-05-09 22:22:50 +0100969 trace_afs_make_fs_call1(call, &dvnode->fid, name);
David Howells20b83912019-05-08 16:16:31 +0100970 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +0100971 afs_make_call(&fc->ac, call, GFP_NOFS);
972 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -0700973}
974
975/*
976 * deliver reply data to an FS.Rename
977 */
David Howellsd0016482016-08-30 20:42:14 +0100978static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700979{
David Howells260a9802007-04-26 15:59:35 -0700980 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100981 int ret;
David Howells260a9802007-04-26 15:59:35 -0700982
David Howellsd0016482016-08-30 20:42:14 +0100983 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100984 if (ret < 0)
985 return ret;
David Howells260a9802007-04-26 15:59:35 -0700986
987 /* unmarshall the reply once we've received all of it */
988 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +0100989 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
David Howells160cb952018-10-20 00:57:56 +0100990 if (ret < 0)
991 return ret;
David Howellsa58823a2019-05-09 15:16:10 +0100992 if (call->out_dir_scb != call->out_scb) {
993 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +0100994 if (ret < 0)
995 return ret;
996 }
David Howellsffba7182019-05-09 22:22:50 +0100997 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells260a9802007-04-26 15:59:35 -0700998
999 _leave(" = 0 [done]");
1000 return 0;
1001}
1002
1003/*
1004 * FS.Rename operation type
1005 */
1006static const struct afs_call_type afs_RXFSRename = {
1007 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001008 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001009 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001010 .destructor = afs_flat_call_destructor,
1011};
1012
1013/*
David Howellsa58823a2019-05-09 15:16:10 +01001014 * Rename/move a file or directory.
David Howells260a9802007-04-26 15:59:35 -07001015 */
David Howells8b2a4642017-11-02 15:27:50 +00001016int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001017 const char *orig_name,
1018 struct afs_vnode *new_dvnode,
David Howells63a46812018-04-06 14:17:25 +01001019 const char *new_name,
David Howellsa58823a2019-05-09 15:16:10 +01001020 struct afs_status_cb *orig_dvnode_scb,
1021 struct afs_status_cb *new_dvnode_scb)
David Howells260a9802007-04-26 15:59:35 -07001022{
David Howellsd2ddc772017-11-02 15:27:50 +00001023 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001024 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001025 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001026 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1027 __be32 *bp;
1028
David Howells30062bd2018-10-20 00:57:58 +01001029 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1030 return yfs_fs_rename(fc, orig_name,
1031 new_dvnode, new_name,
David Howellsa58823a2019-05-09 15:16:10 +01001032 orig_dvnode_scb,
1033 new_dvnode_scb);
David Howells30062bd2018-10-20 00:57:58 +01001034
David Howells260a9802007-04-26 15:59:35 -07001035 _enter("");
1036
1037 o_namesz = strlen(orig_name);
1038 o_padsz = (4 - (o_namesz & 3)) & 3;
1039
1040 n_namesz = strlen(new_name);
1041 n_padsz = (4 - (n_namesz & 3)) & 3;
1042
1043 reqsz = (4 * 4) +
1044 4 + o_namesz + o_padsz +
1045 (3 * 4) +
1046 4 + n_namesz + n_padsz;
1047
David Howellsf044c882017-11-02 15:27:45 +00001048 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001049 if (!call)
1050 return -ENOMEM;
1051
David Howellsd2ddc772017-11-02 15:27:50 +00001052 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01001053 call->out_dir_scb = orig_dvnode_scb;
1054 call->out_scb = new_dvnode_scb;
David Howells260a9802007-04-26 15:59:35 -07001055
1056 /* marshall the parameters */
1057 bp = call->request;
1058 *bp++ = htonl(FSRENAME);
1059 *bp++ = htonl(orig_dvnode->fid.vid);
1060 *bp++ = htonl(orig_dvnode->fid.vnode);
1061 *bp++ = htonl(orig_dvnode->fid.unique);
1062 *bp++ = htonl(o_namesz);
1063 memcpy(bp, orig_name, o_namesz);
1064 bp = (void *) bp + o_namesz;
1065 if (o_padsz > 0) {
1066 memset(bp, 0, o_padsz);
1067 bp = (void *) bp + o_padsz;
1068 }
1069
1070 *bp++ = htonl(new_dvnode->fid.vid);
1071 *bp++ = htonl(new_dvnode->fid.vnode);
1072 *bp++ = htonl(new_dvnode->fid.unique);
1073 *bp++ = htonl(n_namesz);
1074 memcpy(bp, new_name, n_namesz);
1075 bp = (void *) bp + n_namesz;
1076 if (n_padsz > 0) {
1077 memset(bp, 0, n_padsz);
1078 bp = (void *) bp + n_padsz;
1079 }
1080
David Howellsd2ddc772017-11-02 15:27:50 +00001081 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +01001082 trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name);
David Howells20b83912019-05-08 16:16:31 +01001083 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001084 afs_make_call(&fc->ac, call, GFP_NOFS);
1085 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -07001086}
David Howells31143d52007-05-09 02:33:46 -07001087
1088/*
1089 * deliver reply data to an FS.StoreData
1090 */
David Howellsd0016482016-08-30 20:42:14 +01001091static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001092{
David Howells31143d52007-05-09 02:33:46 -07001093 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001094 int ret;
David Howells31143d52007-05-09 02:33:46 -07001095
David Howellsd0016482016-08-30 20:42:14 +01001096 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001097
David Howellsd0016482016-08-30 20:42:14 +01001098 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001099 if (ret < 0)
1100 return ret;
David Howells31143d52007-05-09 02:33:46 -07001101
1102 /* unmarshall the reply once we've received all of it */
1103 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +01001104 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +01001105 if (ret < 0)
1106 return ret;
David Howellsffba7182019-05-09 22:22:50 +01001107 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells31143d52007-05-09 02:33:46 -07001108
David Howells31143d52007-05-09 02:33:46 -07001109 _leave(" = 0 [done]");
1110 return 0;
1111}
1112
1113/*
1114 * FS.StoreData operation type
1115 */
1116static const struct afs_call_type afs_RXFSStoreData = {
1117 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001118 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001119 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001120 .destructor = afs_flat_call_destructor,
1121};
1122
David Howellsb9b1f8d2007-05-10 03:15:21 -07001123static const struct afs_call_type afs_RXFSStoreData64 = {
1124 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001125 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001126 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001127 .destructor = afs_flat_call_destructor,
1128};
1129
1130/*
1131 * store a set of pages to a very large file
1132 */
David Howells8b2a4642017-11-02 15:27:50 +00001133static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001134 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001135 pgoff_t first, pgoff_t last,
1136 unsigned offset, unsigned to,
David Howellsa58823a2019-05-09 15:16:10 +01001137 loff_t size, loff_t pos, loff_t i_size,
1138 struct afs_status_cb *scb)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001139{
David Howells4343d002017-11-02 15:27:52 +00001140 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001141 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001142 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001143 __be32 *bp;
1144
David Howells3b6492d2018-10-20 00:57:57 +01001145 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001146 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001147
David Howellsf044c882017-11-02 15:27:45 +00001148 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001149 (4 + 6 + 3 * 2) * 4,
1150 (21 + 6) * 4);
1151 if (!call)
1152 return -ENOMEM;
1153
David Howells4343d002017-11-02 15:27:52 +00001154 call->key = fc->key;
1155 call->mapping = mapping;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001156 call->first = first;
1157 call->last = last;
1158 call->first_offset = offset;
1159 call->last_to = to;
1160 call->send_pages = true;
David Howellsa58823a2019-05-09 15:16:10 +01001161 call->out_scb = scb;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001162
1163 /* marshall the parameters */
1164 bp = call->request;
1165 *bp++ = htonl(FSSTOREDATA64);
1166 *bp++ = htonl(vnode->fid.vid);
1167 *bp++ = htonl(vnode->fid.vnode);
1168 *bp++ = htonl(vnode->fid.unique);
1169
Marc Dionneab94f5d2017-03-16 16:27:47 +00001170 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1171 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001172 *bp++ = 0; /* owner */
1173 *bp++ = 0; /* group */
1174 *bp++ = 0; /* unix mode */
1175 *bp++ = 0; /* segment size */
1176
1177 *bp++ = htonl(pos >> 32);
1178 *bp++ = htonl((u32) pos);
1179 *bp++ = htonl(size >> 32);
1180 *bp++ = htonl((u32) size);
1181 *bp++ = htonl(i_size >> 32);
1182 *bp++ = htonl((u32) i_size);
1183
David Howells025db802017-11-02 15:27:51 +00001184 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001185 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001186 afs_make_call(&fc->ac, call, GFP_NOFS);
1187 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001188}
1189
David Howells31143d52007-05-09 02:33:46 -07001190/*
1191 * store a set of pages
1192 */
David Howells4343d002017-11-02 15:27:52 +00001193int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001194 pgoff_t first, pgoff_t last,
David Howellsa58823a2019-05-09 15:16:10 +01001195 unsigned offset, unsigned to,
1196 struct afs_status_cb *scb)
David Howells31143d52007-05-09 02:33:46 -07001197{
David Howells4343d002017-11-02 15:27:52 +00001198 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001199 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001200 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001201 loff_t size, pos, i_size;
1202 __be32 *bp;
1203
David Howells30062bd2018-10-20 00:57:58 +01001204 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +01001205 return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb);
David Howells30062bd2018-10-20 00:57:58 +01001206
David Howells3b6492d2018-10-20 00:57:57 +01001207 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001208 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001209
David Howells146a1192017-03-16 16:27:47 +00001210 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001211 if (first != last)
1212 size += (loff_t)(last - first) << PAGE_SHIFT;
1213 pos = (loff_t)first << PAGE_SHIFT;
1214 pos += offset;
1215
1216 i_size = i_size_read(&vnode->vfs_inode);
1217 if (pos + size > i_size)
1218 i_size = size + pos;
1219
1220 _debug("size %llx, at %llx, i_size %llx",
1221 (unsigned long long) size, (unsigned long long) pos,
1222 (unsigned long long) i_size);
1223
David Howellsb9b1f8d2007-05-10 03:15:21 -07001224 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001225 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsa58823a2019-05-09 15:16:10 +01001226 size, pos, i_size, scb);
David Howells31143d52007-05-09 02:33:46 -07001227
David Howellsf044c882017-11-02 15:27:45 +00001228 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001229 (4 + 6 + 3) * 4,
1230 (21 + 6) * 4);
1231 if (!call)
1232 return -ENOMEM;
1233
David Howells4343d002017-11-02 15:27:52 +00001234 call->key = fc->key;
1235 call->mapping = mapping;
David Howells31143d52007-05-09 02:33:46 -07001236 call->first = first;
1237 call->last = last;
1238 call->first_offset = offset;
1239 call->last_to = to;
1240 call->send_pages = true;
David Howellsa58823a2019-05-09 15:16:10 +01001241 call->out_scb = scb;
David Howells31143d52007-05-09 02:33:46 -07001242
1243 /* marshall the parameters */
1244 bp = call->request;
1245 *bp++ = htonl(FSSTOREDATA);
1246 *bp++ = htonl(vnode->fid.vid);
1247 *bp++ = htonl(vnode->fid.vnode);
1248 *bp++ = htonl(vnode->fid.unique);
1249
Marc Dionneab94f5d2017-03-16 16:27:47 +00001250 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1251 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001252 *bp++ = 0; /* owner */
1253 *bp++ = 0; /* group */
1254 *bp++ = 0; /* unix mode */
1255 *bp++ = 0; /* segment size */
1256
1257 *bp++ = htonl(pos);
1258 *bp++ = htonl(size);
1259 *bp++ = htonl(i_size);
1260
David Howellsd2ddc772017-11-02 15:27:50 +00001261 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001262 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001263 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001264 afs_make_call(&fc->ac, call, GFP_NOFS);
1265 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells31143d52007-05-09 02:33:46 -07001266}
1267
1268/*
1269 * deliver reply data to an FS.StoreStatus
1270 */
David Howellsd0016482016-08-30 20:42:14 +01001271static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001272{
David Howells31143d52007-05-09 02:33:46 -07001273 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001274 int ret;
David Howells31143d52007-05-09 02:33:46 -07001275
David Howellsd0016482016-08-30 20:42:14 +01001276 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001277
David Howellsd0016482016-08-30 20:42:14 +01001278 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001279 if (ret < 0)
1280 return ret;
David Howells31143d52007-05-09 02:33:46 -07001281
1282 /* unmarshall the reply once we've received all of it */
David Howells31143d52007-05-09 02:33:46 -07001283 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +01001284 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +01001285 if (ret < 0)
1286 return ret;
David Howellsffba7182019-05-09 22:22:50 +01001287 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells31143d52007-05-09 02:33:46 -07001288
1289 _leave(" = 0 [done]");
1290 return 0;
1291}
1292
1293/*
1294 * FS.StoreStatus operation type
1295 */
1296static const struct afs_call_type afs_RXFSStoreStatus = {
1297 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001298 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001299 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001300 .destructor = afs_flat_call_destructor,
1301};
1302
1303static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1304 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001305 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001306 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001307 .destructor = afs_flat_call_destructor,
1308};
1309
David Howellsb9b1f8d2007-05-10 03:15:21 -07001310static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1311 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001312 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001313 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001314 .destructor = afs_flat_call_destructor,
1315};
1316
1317/*
1318 * set the attributes on a very large file, using FS.StoreData rather than
1319 * FS.StoreStatus so as to alter the file size also
1320 */
David Howellsa58823a2019-05-09 15:16:10 +01001321static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr,
1322 struct afs_status_cb *scb)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001323{
David Howellsd2ddc772017-11-02 15:27:50 +00001324 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001325 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001326 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001327 __be32 *bp;
1328
David Howells3b6492d2018-10-20 00:57:57 +01001329 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001330 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001331
1332 ASSERT(attr->ia_valid & ATTR_SIZE);
1333
David Howellsf044c882017-11-02 15:27:45 +00001334 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001335 (4 + 6 + 3 * 2) * 4,
1336 (21 + 6) * 4);
1337 if (!call)
1338 return -ENOMEM;
1339
David Howellsd2ddc772017-11-02 15:27:50 +00001340 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01001341 call->out_scb = scb;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001342
1343 /* marshall the parameters */
1344 bp = call->request;
1345 *bp++ = htonl(FSSTOREDATA64);
1346 *bp++ = htonl(vnode->fid.vid);
1347 *bp++ = htonl(vnode->fid.vnode);
1348 *bp++ = htonl(vnode->fid.unique);
1349
1350 xdr_encode_AFS_StoreStatus(&bp, attr);
1351
David Howells8c7ae382019-03-27 22:48:02 +00001352 *bp++ = htonl(attr->ia_size >> 32); /* position of start of write */
1353 *bp++ = htonl((u32) attr->ia_size);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001354 *bp++ = 0; /* size of write */
1355 *bp++ = 0;
1356 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1357 *bp++ = htonl((u32) attr->ia_size);
1358
David Howellsd2ddc772017-11-02 15:27:50 +00001359 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001360 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001361 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001362 afs_make_call(&fc->ac, call, GFP_NOFS);
1363 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001364}
1365
David Howells31143d52007-05-09 02:33:46 -07001366/*
1367 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1368 * so as to alter the file size also
1369 */
David Howellsa58823a2019-05-09 15:16:10 +01001370static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr,
1371 struct afs_status_cb *scb)
David Howells31143d52007-05-09 02:33:46 -07001372{
David Howellsd2ddc772017-11-02 15:27:50 +00001373 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001374 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001375 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001376 __be32 *bp;
1377
David Howells3b6492d2018-10-20 00:57:57 +01001378 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001379 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001380
1381 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001382 if (attr->ia_size >> 32)
David Howellsa58823a2019-05-09 15:16:10 +01001383 return afs_fs_setattr_size64(fc, attr, scb);
David Howells31143d52007-05-09 02:33:46 -07001384
David Howellsf044c882017-11-02 15:27:45 +00001385 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001386 (4 + 6 + 3) * 4,
1387 (21 + 6) * 4);
1388 if (!call)
1389 return -ENOMEM;
1390
David Howellsd2ddc772017-11-02 15:27:50 +00001391 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01001392 call->out_scb = scb;
David Howells31143d52007-05-09 02:33:46 -07001393
1394 /* marshall the parameters */
1395 bp = call->request;
1396 *bp++ = htonl(FSSTOREDATA);
1397 *bp++ = htonl(vnode->fid.vid);
1398 *bp++ = htonl(vnode->fid.vnode);
1399 *bp++ = htonl(vnode->fid.unique);
1400
1401 xdr_encode_AFS_StoreStatus(&bp, attr);
1402
David Howells8c7ae382019-03-27 22:48:02 +00001403 *bp++ = htonl(attr->ia_size); /* position of start of write */
David Howells31143d52007-05-09 02:33:46 -07001404 *bp++ = 0; /* size of write */
1405 *bp++ = htonl(attr->ia_size); /* new file length */
1406
David Howellsd2ddc772017-11-02 15:27:50 +00001407 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001408 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001409 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001410 afs_make_call(&fc->ac, call, GFP_NOFS);
1411 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells31143d52007-05-09 02:33:46 -07001412}
1413
1414/*
1415 * set the attributes on a file, using FS.StoreData if there's a change in file
1416 * size, and FS.StoreStatus otherwise
1417 */
David Howellsa58823a2019-05-09 15:16:10 +01001418int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr,
1419 struct afs_status_cb *scb)
David Howells31143d52007-05-09 02:33:46 -07001420{
David Howellsd2ddc772017-11-02 15:27:50 +00001421 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001422 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001423 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001424 __be32 *bp;
1425
David Howells30062bd2018-10-20 00:57:58 +01001426 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +01001427 return yfs_fs_setattr(fc, attr, scb);
David Howells30062bd2018-10-20 00:57:58 +01001428
David Howells31143d52007-05-09 02:33:46 -07001429 if (attr->ia_valid & ATTR_SIZE)
David Howellsa58823a2019-05-09 15:16:10 +01001430 return afs_fs_setattr_size(fc, attr, scb);
David Howells31143d52007-05-09 02:33:46 -07001431
David Howells3b6492d2018-10-20 00:57:57 +01001432 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001433 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001434
David Howellsf044c882017-11-02 15:27:45 +00001435 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001436 (4 + 6) * 4,
1437 (21 + 6) * 4);
1438 if (!call)
1439 return -ENOMEM;
1440
David Howellsd2ddc772017-11-02 15:27:50 +00001441 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01001442 call->out_scb = scb;
David Howells31143d52007-05-09 02:33:46 -07001443
1444 /* marshall the parameters */
1445 bp = call->request;
1446 *bp++ = htonl(FSSTORESTATUS);
1447 *bp++ = htonl(vnode->fid.vid);
1448 *bp++ = htonl(vnode->fid.vnode);
1449 *bp++ = htonl(vnode->fid.unique);
1450
1451 xdr_encode_AFS_StoreStatus(&bp, attr);
1452
David Howellsd2ddc772017-11-02 15:27:50 +00001453 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001454 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001455 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001456 afs_make_call(&fc->ac, call, GFP_NOFS);
1457 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells31143d52007-05-09 02:33:46 -07001458}
David Howells45222b92007-05-10 22:22:20 -07001459
1460/*
1461 * deliver reply data to an FS.GetVolumeStatus
1462 */
David Howellsd0016482016-08-30 20:42:14 +01001463static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001464{
1465 const __be32 *bp;
1466 char *p;
David Howells12bdcf32018-10-20 00:57:56 +01001467 u32 size;
David Howells45222b92007-05-10 22:22:20 -07001468 int ret;
1469
David Howellsd0016482016-08-30 20:42:14 +01001470 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001471
1472 switch (call->unmarshall) {
1473 case 0:
David Howells45222b92007-05-10 22:22:20 -07001474 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001475 afs_extract_to_buf(call, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001476
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001477 /* Fall through - and extract the returned status record */
David Howells45222b92007-05-10 22:22:20 -07001478 case 1:
1479 _debug("extract status");
David Howells12bdcf32018-10-20 00:57:56 +01001480 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001481 if (ret < 0)
1482 return ret;
David Howells45222b92007-05-10 22:22:20 -07001483
1484 bp = call->buffer;
David Howellsffba7182019-05-09 22:22:50 +01001485 xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus);
David Howells45222b92007-05-10 22:22:20 -07001486 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001487 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001488
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001489 /* Fall through - and extract the volume name length */
David Howells45222b92007-05-10 22:22:20 -07001490 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001491 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001492 if (ret < 0)
1493 return ret;
David Howells45222b92007-05-10 22:22:20 -07001494
1495 call->count = ntohl(call->tmp);
1496 _debug("volname length: %u", call->count);
1497 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001498 return afs_protocol_error(call, -EBADMSG,
1499 afs_eproto_volname_len);
David Howells12bdcf32018-10-20 00:57:56 +01001500 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001501 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001502 call->unmarshall++;
1503
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001504 /* Fall through - and extract the volume name */
David Howells45222b92007-05-10 22:22:20 -07001505 case 3:
1506 _debug("extract volname");
David Howells12bdcf32018-10-20 00:57:56 +01001507 ret = afs_extract_data(call, true);
1508 if (ret < 0)
1509 return ret;
David Howells45222b92007-05-10 22:22:20 -07001510
David Howellsffba7182019-05-09 22:22:50 +01001511 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001512 p[call->count] = 0;
1513 _debug("volname '%s'", p);
David Howells12bdcf32018-10-20 00:57:56 +01001514 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001515 call->unmarshall++;
1516
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001517 /* Fall through - and extract the offline message length */
David Howells12bdcf32018-10-20 00:57:56 +01001518 case 4:
1519 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001520 if (ret < 0)
1521 return ret;
David Howells45222b92007-05-10 22:22:20 -07001522
1523 call->count = ntohl(call->tmp);
1524 _debug("offline msg length: %u", call->count);
1525 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001526 return afs_protocol_error(call, -EBADMSG,
1527 afs_eproto_offline_msg_len);
David Howells12bdcf32018-10-20 00:57:56 +01001528 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001529 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001530 call->unmarshall++;
1531
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001532 /* Fall through - and extract the offline message */
David Howells12bdcf32018-10-20 00:57:56 +01001533 case 5:
David Howells45222b92007-05-10 22:22:20 -07001534 _debug("extract offline");
David Howells12bdcf32018-10-20 00:57:56 +01001535 ret = afs_extract_data(call, true);
1536 if (ret < 0)
1537 return ret;
David Howells45222b92007-05-10 22:22:20 -07001538
David Howellsffba7182019-05-09 22:22:50 +01001539 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001540 p[call->count] = 0;
1541 _debug("offline '%s'", p);
1542
David Howells12bdcf32018-10-20 00:57:56 +01001543 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001544 call->unmarshall++;
1545
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001546 /* Fall through - and extract the message of the day length */
David Howells12bdcf32018-10-20 00:57:56 +01001547 case 6:
1548 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001549 if (ret < 0)
1550 return ret;
David Howells45222b92007-05-10 22:22:20 -07001551
1552 call->count = ntohl(call->tmp);
1553 _debug("motd length: %u", call->count);
1554 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001555 return afs_protocol_error(call, -EBADMSG,
1556 afs_eproto_motd_len);
David Howells12bdcf32018-10-20 00:57:56 +01001557 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001558 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001559 call->unmarshall++;
1560
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001561 /* Fall through - and extract the message of the day */
David Howells12bdcf32018-10-20 00:57:56 +01001562 case 7:
David Howells45222b92007-05-10 22:22:20 -07001563 _debug("extract motd");
David Howells12bdcf32018-10-20 00:57:56 +01001564 ret = afs_extract_data(call, false);
1565 if (ret < 0)
1566 return ret;
David Howells45222b92007-05-10 22:22:20 -07001567
David Howellsffba7182019-05-09 22:22:50 +01001568 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001569 p[call->count] = 0;
1570 _debug("motd '%s'", p);
1571
David Howells45222b92007-05-10 22:22:20 -07001572 call->unmarshall++;
1573
David Howells12bdcf32018-10-20 00:57:56 +01001574 case 8:
David Howells45222b92007-05-10 22:22:20 -07001575 break;
1576 }
1577
David Howells45222b92007-05-10 22:22:20 -07001578 _leave(" = 0 [done]");
1579 return 0;
1580}
1581
1582/*
David Howells45222b92007-05-10 22:22:20 -07001583 * FS.GetVolumeStatus operation type
1584 */
1585static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1586 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001587 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001588 .deliver = afs_deliver_fs_get_volume_status,
David Howellsffba7182019-05-09 22:22:50 +01001589 .destructor = afs_flat_call_destructor,
David Howells45222b92007-05-10 22:22:20 -07001590};
1591
1592/*
1593 * fetch the status of a volume
1594 */
David Howells8b2a4642017-11-02 15:27:50 +00001595int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001596 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001597{
David Howellsd2ddc772017-11-02 15:27:50 +00001598 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001599 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001600 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001601 __be32 *bp;
David Howells45222b92007-05-10 22:22:20 -07001602
David Howells30062bd2018-10-20 00:57:58 +01001603 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1604 return yfs_fs_get_volume_status(fc, vs);
1605
David Howells45222b92007-05-10 22:22:20 -07001606 _enter("");
1607
David Howellsffba7182019-05-09 22:22:50 +01001608 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4,
1609 max(12 * 4, AFSOPAQUEMAX + 1));
1610 if (!call)
David Howells45222b92007-05-10 22:22:20 -07001611 return -ENOMEM;
1612
David Howellsd2ddc772017-11-02 15:27:50 +00001613 call->key = fc->key;
David Howellsffba7182019-05-09 22:22:50 +01001614 call->out_volstatus = vs;
David Howells45222b92007-05-10 22:22:20 -07001615
1616 /* marshall the parameters */
1617 bp = call->request;
1618 bp[0] = htonl(FSGETVOLUMESTATUS);
1619 bp[1] = htonl(vnode->fid.vid);
1620
David Howellsd2ddc772017-11-02 15:27:50 +00001621 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001622 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001623 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001624 afs_make_call(&fc->ac, call, GFP_NOFS);
1625 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells45222b92007-05-10 22:22:20 -07001626}
David Howellse8d6c552007-07-15 23:40:12 -07001627
1628/*
1629 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1630 */
David Howellsd0016482016-08-30 20:42:14 +01001631static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001632{
1633 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001634 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001635
David Howellsd0016482016-08-30 20:42:14 +01001636 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001637
David Howellsd0016482016-08-30 20:42:14 +01001638 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001639 if (ret < 0)
1640 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001641
1642 /* unmarshall the reply once we've received all of it */
1643 bp = call->buffer;
David Howellsffba7182019-05-09 22:22:50 +01001644 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howellse8d6c552007-07-15 23:40:12 -07001645
1646 _leave(" = 0 [done]");
1647 return 0;
1648}
1649
1650/*
1651 * FS.SetLock operation type
1652 */
1653static const struct afs_call_type afs_RXFSSetLock = {
1654 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001655 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001656 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001657 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001658 .destructor = afs_flat_call_destructor,
1659};
1660
1661/*
1662 * FS.ExtendLock operation type
1663 */
1664static const struct afs_call_type afs_RXFSExtendLock = {
1665 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001666 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001667 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001668 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001669 .destructor = afs_flat_call_destructor,
1670};
1671
1672/*
1673 * FS.ReleaseLock operation type
1674 */
1675static const struct afs_call_type afs_RXFSReleaseLock = {
1676 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001677 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001678 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001679 .destructor = afs_flat_call_destructor,
1680};
1681
1682/*
David Howellsd2ddc772017-11-02 15:27:50 +00001683 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001684 */
David Howellsa58823a2019-05-09 15:16:10 +01001685int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type,
1686 struct afs_status_cb *scb)
David Howellse8d6c552007-07-15 23:40:12 -07001687{
David Howellsd2ddc772017-11-02 15:27:50 +00001688 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001689 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001690 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001691 __be32 *bp;
1692
David Howells30062bd2018-10-20 00:57:58 +01001693 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +01001694 return yfs_fs_set_lock(fc, type, scb);
David Howells30062bd2018-10-20 00:57:58 +01001695
David Howellse8d6c552007-07-15 23:40:12 -07001696 _enter("");
1697
David Howellsf044c882017-11-02 15:27:45 +00001698 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001699 if (!call)
1700 return -ENOMEM;
1701
David Howellsd2ddc772017-11-02 15:27:50 +00001702 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01001703 call->lvnode = vnode;
1704 call->out_scb = scb;
David Howellse8d6c552007-07-15 23:40:12 -07001705
1706 /* marshall the parameters */
1707 bp = call->request;
1708 *bp++ = htonl(FSSETLOCK);
1709 *bp++ = htonl(vnode->fid.vid);
1710 *bp++ = htonl(vnode->fid.vnode);
1711 *bp++ = htonl(vnode->fid.unique);
1712 *bp++ = htonl(type);
1713
David Howellsd2ddc772017-11-02 15:27:50 +00001714 afs_use_fs_server(call, fc->cbi);
David Howells6c6c1d62019-04-25 14:26:52 +01001715 trace_afs_make_fs_calli(call, &vnode->fid, type);
David Howells20b83912019-05-08 16:16:31 +01001716 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001717 afs_make_call(&fc->ac, call, GFP_NOFS);
1718 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellse8d6c552007-07-15 23:40:12 -07001719}
1720
1721/*
1722 * extend a lock on a file
1723 */
David Howellsa58823a2019-05-09 15:16:10 +01001724int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
David Howellse8d6c552007-07-15 23:40:12 -07001725{
David Howellsd2ddc772017-11-02 15:27:50 +00001726 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001727 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001728 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001729 __be32 *bp;
1730
David Howells30062bd2018-10-20 00:57:58 +01001731 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +01001732 return yfs_fs_extend_lock(fc, scb);
David Howells30062bd2018-10-20 00:57:58 +01001733
David Howellse8d6c552007-07-15 23:40:12 -07001734 _enter("");
1735
David Howellsf044c882017-11-02 15:27:45 +00001736 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001737 if (!call)
1738 return -ENOMEM;
1739
David Howellsd2ddc772017-11-02 15:27:50 +00001740 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01001741 call->lvnode = vnode;
1742 call->out_scb = scb;
David Howellse8d6c552007-07-15 23:40:12 -07001743
1744 /* marshall the parameters */
1745 bp = call->request;
1746 *bp++ = htonl(FSEXTENDLOCK);
1747 *bp++ = htonl(vnode->fid.vid);
1748 *bp++ = htonl(vnode->fid.vnode);
1749 *bp++ = htonl(vnode->fid.unique);
1750
David Howellsd2ddc772017-11-02 15:27:50 +00001751 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001752 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001753 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001754 afs_make_call(&fc->ac, call, GFP_NOFS);
1755 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellse8d6c552007-07-15 23:40:12 -07001756}
1757
1758/*
1759 * release a lock on a file
1760 */
David Howellsa58823a2019-05-09 15:16:10 +01001761int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
David Howellse8d6c552007-07-15 23:40:12 -07001762{
David Howellsd2ddc772017-11-02 15:27:50 +00001763 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001764 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001765 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001766 __be32 *bp;
1767
David Howells30062bd2018-10-20 00:57:58 +01001768 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +01001769 return yfs_fs_release_lock(fc, scb);
David Howells30062bd2018-10-20 00:57:58 +01001770
David Howellse8d6c552007-07-15 23:40:12 -07001771 _enter("");
1772
David Howellsf044c882017-11-02 15:27:45 +00001773 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001774 if (!call)
1775 return -ENOMEM;
1776
David Howellsd2ddc772017-11-02 15:27:50 +00001777 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01001778 call->lvnode = vnode;
1779 call->out_scb = scb;
David Howellse8d6c552007-07-15 23:40:12 -07001780
1781 /* marshall the parameters */
1782 bp = call->request;
1783 *bp++ = htonl(FSRELEASELOCK);
1784 *bp++ = htonl(vnode->fid.vid);
1785 *bp++ = htonl(vnode->fid.vnode);
1786 *bp++ = htonl(vnode->fid.unique);
1787
David Howellsd2ddc772017-11-02 15:27:50 +00001788 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001789 trace_afs_make_fs_call(call, &vnode->fid);
David Howells20b83912019-05-08 16:16:31 +01001790 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01001791 afs_make_call(&fc->ac, call, GFP_NOFS);
1792 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsc435ee32017-11-02 15:27:49 +00001793}
1794
1795/*
1796 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1797 */
1798static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1799{
1800 return afs_transfer_reply(call);
1801}
1802
1803/*
1804 * FS.GiveUpAllCallBacks operation type
1805 */
1806static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1807 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001808 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001809 .deliver = afs_deliver_fs_give_up_all_callbacks,
1810 .destructor = afs_flat_call_destructor,
1811};
1812
1813/*
1814 * Flush all the callbacks we have on a server.
1815 */
David Howellsd2ddc772017-11-02 15:27:50 +00001816int afs_fs_give_up_all_callbacks(struct afs_net *net,
1817 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001818 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001819 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001820{
1821 struct afs_call *call;
1822 __be32 *bp;
1823
1824 _enter("");
1825
David Howellsd2ddc772017-11-02 15:27:50 +00001826 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001827 if (!call)
1828 return -ENOMEM;
1829
1830 call->key = key;
1831
1832 /* marshall the parameters */
1833 bp = call->request;
1834 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1835
1836 /* Can't take a ref on server */
David Howells0b9bf382019-04-25 14:26:50 +01001837 afs_make_call(ac, call, GFP_NOFS);
1838 return afs_wait_for_call_to_complete(call, ac);
David Howellsd2ddc772017-11-02 15:27:50 +00001839}
1840
1841/*
1842 * Deliver reply data to an FS.GetCapabilities operation.
1843 */
1844static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1845{
1846 u32 count;
1847 int ret;
1848
David Howells12bdcf32018-10-20 00:57:56 +01001849 _enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter));
David Howellsd2ddc772017-11-02 15:27:50 +00001850
David Howellsd2ddc772017-11-02 15:27:50 +00001851 switch (call->unmarshall) {
1852 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01001853 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00001854 call->unmarshall++;
1855
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001856 /* Fall through - and extract the capabilities word count */
David Howellsd2ddc772017-11-02 15:27:50 +00001857 case 1:
David Howells12bdcf32018-10-20 00:57:56 +01001858 ret = afs_extract_data(call, true);
David Howellsd2ddc772017-11-02 15:27:50 +00001859 if (ret < 0)
1860 return ret;
1861
1862 count = ntohl(call->tmp);
1863
1864 call->count = count;
1865 call->count2 = count;
David Howells12bdcf32018-10-20 00:57:56 +01001866 iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
David Howellsd2ddc772017-11-02 15:27:50 +00001867 call->unmarshall++;
1868
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06001869 /* Fall through - and extract capabilities words */
David Howellsd2ddc772017-11-02 15:27:50 +00001870 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001871 ret = afs_extract_data(call, false);
David Howellsd2ddc772017-11-02 15:27:50 +00001872 if (ret < 0)
1873 return ret;
1874
1875 /* TODO: Examine capabilities */
1876
David Howellsd2ddc772017-11-02 15:27:50 +00001877 call->unmarshall++;
1878 break;
1879 }
1880
1881 _leave(" = 0 [done]");
1882 return 0;
1883}
1884
1885/*
1886 * FS.GetCapabilities operation type
1887 */
1888static const struct afs_call_type afs_RXFSGetCapabilities = {
1889 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001890 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001891 .deliver = afs_deliver_fs_get_capabilities,
David Howells3bf0fb62018-10-20 00:57:59 +01001892 .done = afs_fileserver_probe_result,
David Howellsffba7182019-05-09 22:22:50 +01001893 .destructor = afs_flat_call_destructor,
David Howellsd2ddc772017-11-02 15:27:50 +00001894};
1895
1896/*
1897 * Probe a fileserver for the capabilities that it supports. This can
1898 * return up to 196 words.
1899 */
David Howells0b9bf382019-04-25 14:26:50 +01001900struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
1901 struct afs_server *server,
1902 struct afs_addr_cursor *ac,
1903 struct key *key,
1904 unsigned int server_index)
David Howellsd2ddc772017-11-02 15:27:50 +00001905{
1906 struct afs_call *call;
1907 __be32 *bp;
1908
1909 _enter("");
1910
1911 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1912 if (!call)
David Howells0b9bf382019-04-25 14:26:50 +01001913 return ERR_PTR(-ENOMEM);
David Howellsd2ddc772017-11-02 15:27:50 +00001914
1915 call->key = key;
David Howellsffba7182019-05-09 22:22:50 +01001916 call->server = afs_get_server(server);
1917 call->server_index = server_index;
David Howells30062bd2018-10-20 00:57:58 +01001918 call->upgrade = true;
David Howells0b9bf382019-04-25 14:26:50 +01001919 call->async = true;
David Howells94f699c2019-05-16 13:21:59 +01001920 call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
David Howellsd2ddc772017-11-02 15:27:50 +00001921
1922 /* marshall the parameters */
1923 bp = call->request;
1924 *bp++ = htonl(FSGETCAPABILITIES);
1925
1926 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00001927 trace_afs_make_fs_call(call, NULL);
David Howells0b9bf382019-04-25 14:26:50 +01001928 afs_make_call(ac, call, GFP_NOFS);
1929 return call;
David Howellse8d6c552007-07-15 23:40:12 -07001930}
David Howells5cf9dd52018-04-09 21:12:31 +01001931
1932/*
1933 * Deliver reply data to an FS.FetchStatus with no vnode.
1934 */
1935static int afs_deliver_fs_fetch_status(struct afs_call *call)
1936{
David Howells5cf9dd52018-04-09 21:12:31 +01001937 const __be32 *bp;
1938 int ret;
1939
1940 ret = afs_transfer_reply(call);
1941 if (ret < 0)
1942 return ret;
1943
David Howells5cf9dd52018-04-09 21:12:31 +01001944 /* unmarshall the reply once we've received all of it */
1945 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +01001946 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells160cb952018-10-20 00:57:56 +01001947 if (ret < 0)
1948 return ret;
David Howellsa58823a2019-05-09 15:16:10 +01001949 xdr_decode_AFSCallBack(&bp, call, call->out_scb);
1950 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells5cf9dd52018-04-09 21:12:31 +01001951
1952 _leave(" = 0 [done]");
1953 return 0;
1954}
1955
1956/*
1957 * FS.FetchStatus operation type
1958 */
1959static const struct afs_call_type afs_RXFSFetchStatus = {
1960 .name = "FS.FetchStatus",
1961 .op = afs_FS_FetchStatus,
1962 .deliver = afs_deliver_fs_fetch_status,
1963 .destructor = afs_flat_call_destructor,
1964};
1965
1966/*
1967 * Fetch the status information for a fid without needing a vnode handle.
1968 */
1969int afs_fs_fetch_status(struct afs_fs_cursor *fc,
1970 struct afs_net *net,
1971 struct afs_fid *fid,
David Howellsa58823a2019-05-09 15:16:10 +01001972 struct afs_status_cb *scb,
David Howells5cf9dd52018-04-09 21:12:31 +01001973 struct afs_volsync *volsync)
1974{
1975 struct afs_call *call;
1976 __be32 *bp;
1977
David Howells30062bd2018-10-20 00:57:58 +01001978 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howellsa58823a2019-05-09 15:16:10 +01001979 return yfs_fs_fetch_status(fc, net, fid, scb, volsync);
David Howells30062bd2018-10-20 00:57:58 +01001980
David Howells3b6492d2018-10-20 00:57:57 +01001981 _enter(",%x,{%llx:%llu},,",
David Howells5cf9dd52018-04-09 21:12:31 +01001982 key_serial(fc->key), fid->vid, fid->vnode);
1983
1984 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
1985 if (!call) {
1986 fc->ac.error = -ENOMEM;
1987 return -ENOMEM;
1988 }
1989
1990 call->key = fc->key;
David Howellsffba7182019-05-09 22:22:50 +01001991 call->out_fid = fid;
David Howellsa58823a2019-05-09 15:16:10 +01001992 call->out_scb = scb;
David Howellsffba7182019-05-09 22:22:50 +01001993 call->out_volsync = volsync;
David Howells5cf9dd52018-04-09 21:12:31 +01001994
1995 /* marshall the parameters */
1996 bp = call->request;
1997 bp[0] = htonl(FSFETCHSTATUS);
1998 bp[1] = htonl(fid->vid);
1999 bp[2] = htonl(fid->vnode);
2000 bp[3] = htonl(fid->unique);
2001
David Howells5cf9dd52018-04-09 21:12:31 +01002002 afs_use_fs_server(call, fc->cbi);
2003 trace_afs_make_fs_call(call, fid);
David Howells20b83912019-05-08 16:16:31 +01002004 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01002005 afs_make_call(&fc->ac, call, GFP_NOFS);
2006 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells5cf9dd52018-04-09 21:12:31 +01002007}
2008
2009/*
2010 * Deliver reply data to an FS.InlineBulkStatus call
2011 */
2012static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2013{
David Howells87182752019-05-09 16:17:05 +01002014 struct afs_status_cb *scb;
David Howells5cf9dd52018-04-09 21:12:31 +01002015 const __be32 *bp;
2016 u32 tmp;
2017 int ret;
2018
2019 _enter("{%u}", call->unmarshall);
2020
2021 switch (call->unmarshall) {
2022 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01002023 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002024 call->unmarshall++;
2025
2026 /* Extract the file status count and array in two steps */
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06002027 /* Fall through */
David Howells5cf9dd52018-04-09 21:12:31 +01002028 case 1:
2029 _debug("extract status count");
David Howells12bdcf32018-10-20 00:57:56 +01002030 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002031 if (ret < 0)
2032 return ret;
2033
2034 tmp = ntohl(call->tmp);
2035 _debug("status count: %u/%u", tmp, call->count2);
2036 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002037 return afs_protocol_error(call, -EBADMSG,
2038 afs_eproto_ibulkst_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002039
2040 call->count = 0;
2041 call->unmarshall++;
2042 more_counts:
David Howells12bdcf32018-10-20 00:57:56 +01002043 afs_extract_to_buf(call, 21 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002044
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06002045 /* Fall through */
David Howells5cf9dd52018-04-09 21:12:31 +01002046 case 2:
2047 _debug("extract status array %u", call->count);
David Howells12bdcf32018-10-20 00:57:56 +01002048 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002049 if (ret < 0)
2050 return ret;
2051
2052 bp = call->buffer;
David Howells87182752019-05-09 16:17:05 +01002053 scb = &call->out_scb[call->count];
David Howellsa58823a2019-05-09 15:16:10 +01002054 ret = xdr_decode_AFSFetchStatus(&bp, call, scb);
David Howells160cb952018-10-20 00:57:56 +01002055 if (ret < 0)
2056 return ret;
David Howells5cf9dd52018-04-09 21:12:31 +01002057
2058 call->count++;
2059 if (call->count < call->count2)
2060 goto more_counts;
2061
2062 call->count = 0;
2063 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01002064 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002065
2066 /* Extract the callback count and array in two steps */
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06002067 /* Fall through */
David Howells5cf9dd52018-04-09 21:12:31 +01002068 case 3:
2069 _debug("extract CB count");
David Howells12bdcf32018-10-20 00:57:56 +01002070 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002071 if (ret < 0)
2072 return ret;
2073
2074 tmp = ntohl(call->tmp);
2075 _debug("CB count: %u", tmp);
2076 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002077 return afs_protocol_error(call, -EBADMSG,
2078 afs_eproto_ibulkst_cb_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002079 call->count = 0;
2080 call->unmarshall++;
2081 more_cbs:
David Howells12bdcf32018-10-20 00:57:56 +01002082 afs_extract_to_buf(call, 3 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002083
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06002084 /* Fall through */
David Howells5cf9dd52018-04-09 21:12:31 +01002085 case 4:
2086 _debug("extract CB array");
David Howells12bdcf32018-10-20 00:57:56 +01002087 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002088 if (ret < 0)
2089 return ret;
2090
2091 _debug("unmarshall CB array");
2092 bp = call->buffer;
David Howells87182752019-05-09 16:17:05 +01002093 scb = &call->out_scb[call->count];
David Howellsa58823a2019-05-09 15:16:10 +01002094 xdr_decode_AFSCallBack(&bp, call, scb);
David Howells5cf9dd52018-04-09 21:12:31 +01002095 call->count++;
2096 if (call->count < call->count2)
2097 goto more_cbs;
2098
David Howells12bdcf32018-10-20 00:57:56 +01002099 afs_extract_to_buf(call, 6 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002100 call->unmarshall++;
2101
Gustavo A. R. Silvae690c9e2019-01-10 15:52:25 -06002102 /* Fall through */
David Howells5cf9dd52018-04-09 21:12:31 +01002103 case 5:
David Howells12bdcf32018-10-20 00:57:56 +01002104 ret = afs_extract_data(call, false);
David Howells5cf9dd52018-04-09 21:12:31 +01002105 if (ret < 0)
2106 return ret;
2107
2108 bp = call->buffer;
David Howellsffba7182019-05-09 22:22:50 +01002109 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells5cf9dd52018-04-09 21:12:31 +01002110
David Howells5cf9dd52018-04-09 21:12:31 +01002111 call->unmarshall++;
2112
2113 case 6:
2114 break;
2115 }
2116
2117 _leave(" = 0 [done]");
2118 return 0;
2119}
2120
2121/*
2122 * FS.InlineBulkStatus operation type
2123 */
2124static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2125 .name = "FS.InlineBulkStatus",
2126 .op = afs_FS_InlineBulkStatus,
2127 .deliver = afs_deliver_fs_inline_bulk_status,
2128 .destructor = afs_flat_call_destructor,
2129};
2130
2131/*
2132 * Fetch the status information for up to 50 files
2133 */
2134int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2135 struct afs_net *net,
2136 struct afs_fid *fids,
David Howells87182752019-05-09 16:17:05 +01002137 struct afs_status_cb *statuses,
David Howells5cf9dd52018-04-09 21:12:31 +01002138 unsigned int nr_fids,
2139 struct afs_volsync *volsync)
2140{
2141 struct afs_call *call;
2142 __be32 *bp;
2143 int i;
2144
David Howells30062bd2018-10-20 00:57:58 +01002145 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
David Howells87182752019-05-09 16:17:05 +01002146 return yfs_fs_inline_bulk_status(fc, net, fids, statuses,
David Howells30062bd2018-10-20 00:57:58 +01002147 nr_fids, volsync);
2148
David Howells3b6492d2018-10-20 00:57:57 +01002149 _enter(",%x,{%llx:%llu},%u",
David Howells5cf9dd52018-04-09 21:12:31 +01002150 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2151
2152 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2153 (2 + nr_fids * 3) * 4,
2154 21 * 4);
2155 if (!call) {
2156 fc->ac.error = -ENOMEM;
2157 return -ENOMEM;
2158 }
2159
2160 call->key = fc->key;
David Howells87182752019-05-09 16:17:05 +01002161 call->out_scb = statuses;
David Howellsffba7182019-05-09 22:22:50 +01002162 call->out_volsync = volsync;
David Howells5cf9dd52018-04-09 21:12:31 +01002163 call->count2 = nr_fids;
2164
2165 /* marshall the parameters */
2166 bp = call->request;
2167 *bp++ = htonl(FSINLINEBULKSTATUS);
2168 *bp++ = htonl(nr_fids);
2169 for (i = 0; i < nr_fids; i++) {
2170 *bp++ = htonl(fids[i].vid);
2171 *bp++ = htonl(fids[i].vnode);
2172 *bp++ = htonl(fids[i].unique);
2173 }
2174
David Howells5cf9dd52018-04-09 21:12:31 +01002175 afs_use_fs_server(call, fc->cbi);
2176 trace_afs_make_fs_call(call, &fids[0]);
David Howells20b83912019-05-08 16:16:31 +01002177 afs_set_fc_call(call, fc);
David Howells0b9bf382019-04-25 14:26:50 +01002178 afs_make_call(&fc->ac, call, GFP_NOFS);
2179 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells5cf9dd52018-04-09 21:12:31 +01002180}
David Howells260f0822019-04-25 14:26:52 +01002181
2182/*
2183 * deliver reply data to an FS.FetchACL
2184 */
2185static int afs_deliver_fs_fetch_acl(struct afs_call *call)
2186{
David Howells260f0822019-04-25 14:26:52 +01002187 struct afs_acl *acl;
2188 const __be32 *bp;
2189 unsigned int size;
2190 int ret;
2191
2192 _enter("{%u}", call->unmarshall);
2193
2194 switch (call->unmarshall) {
2195 case 0:
2196 afs_extract_to_tmp(call);
2197 call->unmarshall++;
2198
2199 /* extract the returned data length */
2200 case 1:
2201 ret = afs_extract_data(call, true);
2202 if (ret < 0)
2203 return ret;
2204
2205 size = call->count2 = ntohl(call->tmp);
2206 size = round_up(size, 4);
2207
2208 acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
2209 if (!acl)
2210 return -ENOMEM;
David Howellsffba7182019-05-09 22:22:50 +01002211 call->ret_acl = acl;
David Howells260f0822019-04-25 14:26:52 +01002212 acl->size = call->count2;
2213 afs_extract_begin(call, acl->data, size);
2214 call->unmarshall++;
2215
2216 /* extract the returned data */
2217 case 2:
2218 ret = afs_extract_data(call, true);
2219 if (ret < 0)
2220 return ret;
2221
2222 afs_extract_to_buf(call, (21 + 6) * 4);
2223 call->unmarshall++;
2224
2225 /* extract the metadata */
2226 case 3:
2227 ret = afs_extract_data(call, false);
2228 if (ret < 0)
2229 return ret;
2230
2231 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +01002232 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howells260f0822019-04-25 14:26:52 +01002233 if (ret < 0)
2234 return ret;
David Howellsffba7182019-05-09 22:22:50 +01002235 xdr_decode_AFSVolSync(&bp, call->out_volsync);
David Howells260f0822019-04-25 14:26:52 +01002236
2237 call->unmarshall++;
2238
2239 case 4:
2240 break;
2241 }
2242
2243 _leave(" = 0 [done]");
2244 return 0;
2245}
2246
2247static void afs_destroy_fs_fetch_acl(struct afs_call *call)
2248{
David Howellsffba7182019-05-09 22:22:50 +01002249 kfree(call->ret_acl);
David Howells260f0822019-04-25 14:26:52 +01002250 afs_flat_call_destructor(call);
2251}
2252
2253/*
2254 * FS.FetchACL operation type
2255 */
2256static const struct afs_call_type afs_RXFSFetchACL = {
2257 .name = "FS.FetchACL",
2258 .op = afs_FS_FetchACL,
2259 .deliver = afs_deliver_fs_fetch_acl,
2260 .destructor = afs_destroy_fs_fetch_acl,
2261};
2262
2263/*
2264 * Fetch the ACL for a file.
2265 */
David Howellsa58823a2019-05-09 15:16:10 +01002266struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc,
2267 struct afs_status_cb *scb)
David Howells260f0822019-04-25 14:26:52 +01002268{
2269 struct afs_vnode *vnode = fc->vnode;
2270 struct afs_call *call;
2271 struct afs_net *net = afs_v2net(vnode);
2272 __be32 *bp;
2273
2274 _enter(",%x,{%llx:%llu},,",
2275 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
2276
2277 call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4);
2278 if (!call) {
2279 fc->ac.error = -ENOMEM;
2280 return ERR_PTR(-ENOMEM);
2281 }
2282
2283 call->key = fc->key;
David Howellsffba7182019-05-09 22:22:50 +01002284 call->ret_acl = NULL;
David Howellsa58823a2019-05-09 15:16:10 +01002285 call->out_scb = scb;
David Howellsffba7182019-05-09 22:22:50 +01002286 call->out_volsync = NULL;
David Howells260f0822019-04-25 14:26:52 +01002287
2288 /* marshall the parameters */
2289 bp = call->request;
2290 bp[0] = htonl(FSFETCHACL);
2291 bp[1] = htonl(vnode->fid.vid);
2292 bp[2] = htonl(vnode->fid.vnode);
2293 bp[3] = htonl(vnode->fid.unique);
2294
David Howells260f0822019-04-25 14:26:52 +01002295 afs_use_fs_server(call, fc->cbi);
2296 trace_afs_make_fs_call(call, &vnode->fid);
2297 afs_make_call(&fc->ac, call, GFP_KERNEL);
2298 return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
2299}
Joe Gorseb10494a2019-04-25 14:26:52 +01002300
2301/*
David Howellsffba7182019-05-09 22:22:50 +01002302 * Deliver reply data to any operation that returns file status and volume
2303 * sync.
2304 */
2305static int afs_deliver_fs_file_status_and_vol(struct afs_call *call)
2306{
David Howellsffba7182019-05-09 22:22:50 +01002307 const __be32 *bp;
2308 int ret;
2309
David Howellsffba7182019-05-09 22:22:50 +01002310 ret = afs_transfer_reply(call);
2311 if (ret < 0)
2312 return ret;
2313
David Howellsffba7182019-05-09 22:22:50 +01002314 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +01002315 ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
David Howellsffba7182019-05-09 22:22:50 +01002316 if (ret < 0)
2317 return ret;
2318 xdr_decode_AFSVolSync(&bp, call->out_volsync);
2319
2320 _leave(" = 0 [done]");
2321 return 0;
2322}
2323
2324/*
Joe Gorseb10494a2019-04-25 14:26:52 +01002325 * FS.StoreACL operation type
2326 */
2327static const struct afs_call_type afs_RXFSStoreACL = {
2328 .name = "FS.StoreACL",
2329 .op = afs_FS_StoreACL,
David Howellsffba7182019-05-09 22:22:50 +01002330 .deliver = afs_deliver_fs_file_status_and_vol,
Joe Gorseb10494a2019-04-25 14:26:52 +01002331 .destructor = afs_flat_call_destructor,
2332};
2333
2334/*
2335 * Fetch the ACL for a file.
2336 */
David Howellsa58823a2019-05-09 15:16:10 +01002337int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl,
2338 struct afs_status_cb *scb)
Joe Gorseb10494a2019-04-25 14:26:52 +01002339{
2340 struct afs_vnode *vnode = fc->vnode;
2341 struct afs_call *call;
2342 struct afs_net *net = afs_v2net(vnode);
2343 size_t size;
2344 __be32 *bp;
2345
2346 _enter(",%x,{%llx:%llu},,",
2347 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
2348
2349 size = round_up(acl->size, 4);
2350 call = afs_alloc_flat_call(net, &afs_RXFSStoreACL,
2351 5 * 4 + size, (21 + 6) * 4);
2352 if (!call) {
2353 fc->ac.error = -ENOMEM;
2354 return -ENOMEM;
2355 }
2356
2357 call->key = fc->key;
David Howellsa58823a2019-05-09 15:16:10 +01002358 call->out_scb = scb;
David Howellsffba7182019-05-09 22:22:50 +01002359 call->out_volsync = NULL;
Joe Gorseb10494a2019-04-25 14:26:52 +01002360
2361 /* marshall the parameters */
2362 bp = call->request;
2363 bp[0] = htonl(FSSTOREACL);
2364 bp[1] = htonl(vnode->fid.vid);
2365 bp[2] = htonl(vnode->fid.vnode);
2366 bp[3] = htonl(vnode->fid.unique);
2367 bp[4] = htonl(acl->size);
2368 memcpy(&bp[5], acl->data, acl->size);
2369 if (acl->size != size)
2370 memset((void *)&bp[5] + acl->size, 0, size - acl->size);
2371
2372 trace_afs_make_fs_call(call, &vnode->fid);
2373 afs_make_call(&fc->ac, call, GFP_KERNEL);
2374 return afs_wait_for_call_to_complete(call, &fc->ac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375}