blob: 4943413d9c5f7ff3011ea2fad230e5a84a6e48e5 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
David Howells08e0e7c2007-04-26 15:55:03 -07002/* AFS File Server client stubs
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
David Howells08e0e7c2007-04-26 15:55:03 -07004 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Written by David Howells (dhowells@redhat.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7
8#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09009#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/sched.h>
David Howells08e0e7c2007-04-26 15:55:03 -070011#include <linux/circ_buf.h>
Jeff Laytona01179e2017-12-11 06:35:11 -050012#include <linux/iversion.h>
David Howells5cbf0392020-02-06 14:22:29 +000013#include <linux/netfs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070015#include "afs_fs.h"
David Howellsdd9fbcb2018-04-06 14:17:24 +010016#include "xdr_fs.h"
David Howellsc435ee32017-11-02 15:27:49 +000017
David Howells6db3ac32017-03-16 16:27:44 +000018/*
David Howells260a9802007-04-26 15:59:35 -070019 * decode an AFSFid block
20 */
21static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
22{
23 const __be32 *bp = *_bp;
24
25 fid->vid = ntohl(*bp++);
26 fid->vnode = ntohl(*bp++);
27 fid->unique = ntohl(*bp++);
28 *_bp = bp;
29}
30
31/*
David Howells888b3382018-04-06 14:17:24 +010032 * Dump a bad file status record.
33 */
34static void xdr_dump_bad(const __be32 *bp)
35{
36 __be32 x[4];
37 int i;
38
39 pr_notice("AFS XDR: Bad status record\n");
40 for (i = 0; i < 5 * 4 * 4; i += 16) {
41 memcpy(x, bp, 16);
42 bp += 4;
43 pr_notice("%03x: %08x %08x %08x %08x\n",
44 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
45 }
46
47 memcpy(x, bp, 4);
48 pr_notice("0x50: %08x\n", ntohl(x[0]));
49}
50
51/*
David Howellsdd9fbcb2018-04-06 14:17:24 +010052 * decode an AFSFetchStatus block
53 */
David Howells38355ee2020-04-08 16:13:20 +010054static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
55 struct afs_call *call,
56 struct afs_status_cb *scb)
David Howellsdd9fbcb2018-04-06 14:17:24 +010057{
58 const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
David Howellsa58823a2019-05-09 15:16:10 +010059 struct afs_file_status *status = &scb->status;
David Howells684b0f62018-05-10 21:51:47 +010060 bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
David Howellsdd9fbcb2018-04-06 14:17:24 +010061 u64 data_version, size;
62 u32 type, abort_code;
David Howellsdd9fbcb2018-04-06 14:17:24 +010063
David Howells684b0f62018-05-10 21:51:47 +010064 abort_code = ntohl(xdr->abort_code);
65
David Howellsdd9fbcb2018-04-06 14:17:24 +010066 if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
David Howells684b0f62018-05-10 21:51:47 +010067 if (xdr->if_version == htonl(0) &&
68 abort_code != 0 &&
69 inline_error) {
70 /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
71 * whereby it doesn't set the interface version in the error
72 * case.
73 */
74 status->abort_code = abort_code;
David Howellsa38a7552019-05-14 12:29:11 +010075 scb->have_error = true;
David Howells38355ee2020-04-08 16:13:20 +010076 goto advance;
David Howells684b0f62018-05-10 21:51:47 +010077 }
78
David Howellsdd9fbcb2018-04-06 14:17:24 +010079 pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
80 goto bad;
81 }
82
David Howells684b0f62018-05-10 21:51:47 +010083 if (abort_code != 0 && inline_error) {
84 status->abort_code = abort_code;
David Howells3e0d9892020-04-08 17:32:10 +010085 scb->have_error = true;
David Howells38355ee2020-04-08 16:13:20 +010086 goto advance;
David Howells684b0f62018-05-10 21:51:47 +010087 }
88
David Howellsdd9fbcb2018-04-06 14:17:24 +010089 type = ntohl(xdr->type);
David Howellsdd9fbcb2018-04-06 14:17:24 +010090 switch (type) {
91 case AFS_FTYPE_FILE:
92 case AFS_FTYPE_DIR:
93 case AFS_FTYPE_SYMLINK:
David Howellsdd9fbcb2018-04-06 14:17:24 +010094 status->type = type;
95 break;
David Howellsdd9fbcb2018-04-06 14:17:24 +010096 default:
97 goto bad;
98 }
99
David Howellsa58823a2019-05-09 15:16:10 +0100100 status->nlink = ntohl(xdr->nlink);
101 status->author = ntohl(xdr->author);
102 status->owner = ntohl(xdr->owner);
103 status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */
104 status->anon_access = ntohl(xdr->anon_access);
105 status->mode = ntohl(xdr->mode) & S_IALLUGO;
106 status->group = ntohl(xdr->group);
107 status->lock_count = ntohl(xdr->lock_count);
David Howellsdd9fbcb2018-04-06 14:17:24 +0100108
David Howellsd4936802018-10-20 00:57:58 +0100109 status->mtime_client.tv_sec = ntohl(xdr->mtime_client);
110 status->mtime_client.tv_nsec = 0;
111 status->mtime_server.tv_sec = ntohl(xdr->mtime_server);
112 status->mtime_server.tv_nsec = 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100113
114 size = (u64)ntohl(xdr->size_lo);
115 size |= (u64)ntohl(xdr->size_hi) << 32;
David Howells63a46812018-04-06 14:17:25 +0100116 status->size = size;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100117
118 data_version = (u64)ntohl(xdr->data_version_lo);
119 data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
David Howellsa58823a2019-05-09 15:16:10 +0100120 status->data_version = data_version;
David Howellsa38a7552019-05-14 12:29:11 +0100121 scb->have_status = true;
David Howellsc72057b2020-04-08 16:13:20 +0100122advance:
David Howellsdd9fbcb2018-04-06 14:17:24 +0100123 *_bp = (const void *)*_bp + sizeof(*xdr);
David Howells38355ee2020-04-08 16:13:20 +0100124 return;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100125
126bad:
127 xdr_dump_bad(*_bp);
David Howells7126ead2020-04-08 16:49:08 +0100128 afs_protocol_error(call, afs_eproto_bad_status);
David Howellsc72057b2020-04-08 16:13:20 +0100129 goto advance;
David Howellsc875c762018-05-23 11:32:06 +0100130}
131
David Howells78107052019-05-09 17:56:53 +0100132static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
133{
134 return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry;
135}
136
David Howellsa58823a2019-05-09 15:16:10 +0100137static void xdr_decode_AFSCallBack(const __be32 **_bp,
138 struct afs_call *call,
139 struct afs_status_cb *scb)
David Howells78107052019-05-09 17:56:53 +0100140{
David Howellsa58823a2019-05-09 15:16:10 +0100141 struct afs_callback *cb = &scb->callback;
David Howells78107052019-05-09 17:56:53 +0100142 const __be32 *bp = *_bp;
143
David Howells7c712452019-05-14 15:35:44 +0100144 bp++; /* version */
David Howells78107052019-05-09 17:56:53 +0100145 cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++));
David Howells7c712452019-05-14 15:35:44 +0100146 bp++; /* type */
David Howellsa58823a2019-05-09 15:16:10 +0100147 scb->have_cb = true;
David Howells78107052019-05-09 17:56:53 +0100148 *_bp = bp;
149}
150
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151/*
David Howells08e0e7c2007-04-26 15:55:03 -0700152 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 */
David Howells08e0e7c2007-04-26 15:55:03 -0700154static void xdr_decode_AFSVolSync(const __be32 **_bp,
155 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156{
David Howells08e0e7c2007-04-26 15:55:03 -0700157 const __be32 *bp = *_bp;
David Howells30062bd2018-10-20 00:57:58 +0100158 u32 creation;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
David Howells30062bd2018-10-20 00:57:58 +0100160 creation = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -0700161 bp++; /* spare2 */
162 bp++; /* spare3 */
163 bp++; /* spare4 */
164 bp++; /* spare5 */
165 bp++; /* spare6 */
166 *_bp = bp;
David Howells30062bd2018-10-20 00:57:58 +0100167
168 if (volsync)
169 volsync->creation = creation;
David Howellsec268152007-04-26 15:49:28 -0700170}
David Howells08e0e7c2007-04-26 15:55:03 -0700171
172/*
David Howells31143d52007-05-09 02:33:46 -0700173 * encode the requested attributes into an AFSStoreStatus block
174 */
175static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
176{
177 __be32 *bp = *_bp;
178 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
179
180 mask = 0;
181 if (attr->ia_valid & ATTR_MTIME) {
182 mask |= AFS_SET_MTIME;
183 mtime = attr->ia_mtime.tv_sec;
184 }
185
186 if (attr->ia_valid & ATTR_UID) {
187 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800188 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700189 }
190
191 if (attr->ia_valid & ATTR_GID) {
192 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800193 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700194 }
195
196 if (attr->ia_valid & ATTR_MODE) {
197 mask |= AFS_SET_MODE;
198 mode = attr->ia_mode & S_IALLUGO;
199 }
200
201 *bp++ = htonl(mask);
202 *bp++ = htonl(mtime);
203 *bp++ = htonl(owner);
204 *bp++ = htonl(group);
205 *bp++ = htonl(mode);
206 *bp++ = 0; /* segment size */
207 *_bp = bp;
208}
209
210/*
David Howells45222b92007-05-10 22:22:20 -0700211 * decode an AFSFetchVolumeStatus block
212 */
213static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
214 struct afs_volume_status *vs)
215{
216 const __be32 *bp = *_bp;
217
218 vs->vid = ntohl(*bp++);
219 vs->parent_id = ntohl(*bp++);
220 vs->online = ntohl(*bp++);
221 vs->in_service = ntohl(*bp++);
222 vs->blessed = ntohl(*bp++);
223 vs->needs_salvage = ntohl(*bp++);
224 vs->type = ntohl(*bp++);
225 vs->min_quota = ntohl(*bp++);
226 vs->max_quota = ntohl(*bp++);
227 vs->blocks_in_use = ntohl(*bp++);
228 vs->part_blocks_avail = ntohl(*bp++);
229 vs->part_max_blocks = ntohl(*bp++);
David Howells30062bd2018-10-20 00:57:58 +0100230 vs->vol_copy_date = 0;
231 vs->vol_backup_date = 0;
David Howells45222b92007-05-10 22:22:20 -0700232 *_bp = bp;
233}
234
235/*
David Howells08e0e7c2007-04-26 15:55:03 -0700236 * deliver reply data to an FS.FetchStatus
237 */
David Howellse49c7b22020-04-10 20:51:51 +0100238static int afs_deliver_fs_fetch_status(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700239{
David Howellse49c7b22020-04-10 20:51:51 +0100240 struct afs_operation *op = call->op;
241 struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
David Howells08e0e7c2007-04-26 15:55:03 -0700242 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100243 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700244
David Howellsd0016482016-08-30 20:42:14 +0100245 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100246 if (ret < 0)
247 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700248
249 /* unmarshall the reply once we've received all of it */
250 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100251 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
252 xdr_decode_AFSCallBack(&bp, call, &vp->scb);
253 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells08e0e7c2007-04-26 15:55:03 -0700254
255 _leave(" = 0 [done]");
256 return 0;
257}
258
259/*
260 * FS.FetchStatus operation type
261 */
David Howellse49c7b22020-04-10 20:51:51 +0100262static const struct afs_call_type afs_RXFSFetchStatus = {
263 .name = "FS.FetchStatus",
David Howells025db802017-11-02 15:27:51 +0000264 .op = afs_FS_FetchStatus,
David Howellse49c7b22020-04-10 20:51:51 +0100265 .deliver = afs_deliver_fs_fetch_status,
David Howells08e0e7c2007-04-26 15:55:03 -0700266 .destructor = afs_flat_call_destructor,
267};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269/*
270 * fetch the status information for a file
271 */
David Howellse49c7b22020-04-10 20:51:51 +0100272void afs_fs_fetch_status(struct afs_operation *op)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273{
David Howellse49c7b22020-04-10 20:51:51 +0100274 struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
David Howells08e0e7c2007-04-26 15:55:03 -0700275 struct afs_call *call;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 __be32 *bp;
277
David Howells3b6492d2018-10-20 00:57:57 +0100278 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +0100279 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
David Howellse49c7b22020-04-10 20:51:51 +0100281 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100282 16, (21 + 3 + 6) * 4);
David Howellse49c7b22020-04-10 20:51:51 +0100283 if (!call)
284 return afs_op_nomem(op);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700287 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 bp[0] = htonl(FSFETCHSTATUS);
David Howellse49c7b22020-04-10 20:51:51 +0100289 bp[1] = htonl(vp->fid.vid);
290 bp[2] = htonl(vp->fid.vnode);
291 bp[3] = htonl(vp->fid.unique);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
David Howellse49c7b22020-04-10 20:51:51 +0100293 trace_afs_make_fs_call(call, &vp->fid);
294 afs_make_op_call(op, call, GFP_NOFS);
David Howellsec268152007-04-26 15:49:28 -0700295}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297/*
David Howells08e0e7c2007-04-26 15:55:03 -0700298 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 */
David Howellsd0016482016-08-30 20:42:14 +0100300static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
David Howellse49c7b22020-04-10 20:51:51 +0100302 struct afs_operation *op = call->op;
303 struct afs_vnode_param *vp = &op->file[0];
304 struct afs_read *req = op->fetch.req;
David Howells08e0e7c2007-04-26 15:55:03 -0700305 const __be32 *bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700307
David Howellsf105da12020-02-06 14:22:28 +0000308 _enter("{%u,%zu,%zu/%llu}",
309 call->unmarshall, call->iov_len, iov_iter_count(call->iter),
310 req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700311
312 switch (call->unmarshall) {
313 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000314 req->actual_len = 0;
David Howells08e0e7c2007-04-26 15:55:03 -0700315 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +0100316 if (call->operation_ID == FSFETCHDATA64) {
317 afs_extract_to_tmp64(call);
318 } else {
319 call->tmp_u = htonl(0);
320 afs_extract_to_tmp(call);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700321 }
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500322 fallthrough;
David Howells08e0e7c2007-04-26 15:55:03 -0700323
David Howellsc4508462020-02-06 14:22:28 +0000324 /* Extract the returned data length into
325 * ->actual_len. This may indicate more or less data than was
326 * requested will be returned.
327 */
David Howells12bdcf32018-10-20 00:57:56 +0100328 case 1:
David Howells08e0e7c2007-04-26 15:55:03 -0700329 _debug("extract data length");
David Howells12bdcf32018-10-20 00:57:56 +0100330 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +0100331 if (ret < 0)
332 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700333
David Howells12bdcf32018-10-20 00:57:56 +0100334 req->actual_len = be64_to_cpu(call->tmp64);
David Howells196ee9c2017-01-05 10:38:34 +0000335 _debug("DATA length: %llu", req->actual_len);
David Howellsc4508462020-02-06 14:22:28 +0000336
337 if (req->actual_len == 0)
David Howells196ee9c2017-01-05 10:38:34 +0000338 goto no_more_data;
David Howells12bdcf32018-10-20 00:57:56 +0100339
David Howellsc4508462020-02-06 14:22:28 +0000340 call->iter = req->iter;
341 call->iov_len = min(req->actual_len, req->len);
David Howells08e0e7c2007-04-26 15:55:03 -0700342 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500343 fallthrough;
David Howells196ee9c2017-01-05 10:38:34 +0000344
Gustavo A. R. Silva29881602019-05-19 18:43:53 -0500345 /* extract the returned data */
David Howells12bdcf32018-10-20 00:57:56 +0100346 case 2:
347 _debug("extract data %zu/%llu",
David Howellsc4508462020-02-06 14:22:28 +0000348 iov_iter_count(call->iter), req->actual_len);
David Howells196ee9c2017-01-05 10:38:34 +0000349
David Howells12bdcf32018-10-20 00:57:56 +0100350 ret = afs_extract_data(call, true);
David Howells196ee9c2017-01-05 10:38:34 +0000351 if (ret < 0)
352 return ret;
David Howells12bdcf32018-10-20 00:57:56 +0100353
David Howellsc4508462020-02-06 14:22:28 +0000354 call->iter = &call->def_iter;
David Howells12bdcf32018-10-20 00:57:56 +0100355 if (req->actual_len <= req->len)
356 goto no_more_data;
David Howells6db3ac32017-03-16 16:27:44 +0000357
358 /* Discard any excess data the server gave us */
David Howells23a28912019-08-20 09:22:38 +0100359 afs_extract_discard(call, req->actual_len - req->len);
David Howells12bdcf32018-10-20 00:57:56 +0100360 call->unmarshall = 3;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500361 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -0500362
David Howells12bdcf32018-10-20 00:57:56 +0100363 case 3:
364 _debug("extract discard %zu/%llu",
David Howellsfc276122019-11-21 09:12:17 +0000365 iov_iter_count(call->iter), req->actual_len - req->len);
David Howells6db3ac32017-03-16 16:27:44 +0000366
David Howells12bdcf32018-10-20 00:57:56 +0100367 ret = afs_extract_data(call, true);
David Howells6db3ac32017-03-16 16:27:44 +0000368 if (ret < 0)
369 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700370
David Howells196ee9c2017-01-05 10:38:34 +0000371 no_more_data:
David Howells12bdcf32018-10-20 00:57:56 +0100372 call->unmarshall = 4;
373 afs_extract_to_buf(call, (21 + 3 + 6) * 4);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500374 fallthrough;
David Howells08e0e7c2007-04-26 15:55:03 -0700375
Gustavo A. R. Silva29881602019-05-19 18:43:53 -0500376 /* extract the metadata */
David Howells12bdcf32018-10-20 00:57:56 +0100377 case 4:
378 ret = afs_extract_data(call, false);
David Howells372ee162016-08-03 14:11:40 +0100379 if (ret < 0)
380 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700381
382 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100383 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
384 xdr_decode_AFSCallBack(&bp, call, &vp->scb);
385 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells08e0e7c2007-04-26 15:55:03 -0700386
David Howellse49c7b22020-04-10 20:51:51 +0100387 req->data_version = vp->scb.status.data_version;
388 req->file_size = vp->scb.status.size;
David Howellsa58823a2019-05-09 15:16:10 +0100389
David Howells08e0e7c2007-04-26 15:55:03 -0700390 call->unmarshall++;
Gustavo A. R. Silvab2db6c32021-05-25 15:40:22 +0100391 fallthrough;
David Howells08e0e7c2007-04-26 15:55:03 -0700392
David Howells12bdcf32018-10-20 00:57:56 +0100393 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700394 break;
395 }
396
David Howells08e0e7c2007-04-26 15:55:03 -0700397 _leave(" = 0 [done]");
398 return 0;
399}
400
401/*
402 * FS.FetchData operation type
403 */
404static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700405 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000406 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700407 .deliver = afs_deliver_fs_fetch_data,
David Howellse49c7b22020-04-10 20:51:51 +0100408 .destructor = afs_flat_call_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700409};
410
David Howellsb9b1f8d2007-05-10 03:15:21 -0700411static const struct afs_call_type afs_RXFSFetchData64 = {
412 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000413 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700414 .deliver = afs_deliver_fs_fetch_data,
David Howellse49c7b22020-04-10 20:51:51 +0100415 .destructor = afs_flat_call_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700416};
417
418/*
419 * fetch data from a very large file
420 */
David Howellse49c7b22020-04-10 20:51:51 +0100421static void afs_fs_fetch_data64(struct afs_operation *op)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700422{
David Howellse49c7b22020-04-10 20:51:51 +0100423 struct afs_vnode_param *vp = &op->file[0];
424 struct afs_read *req = op->fetch.req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700425 struct afs_call *call;
426 __be32 *bp;
427
428 _enter("");
429
David Howellse49c7b22020-04-10 20:51:51 +0100430 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700431 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100432 return afs_op_nomem(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700433
434 /* marshall the parameters */
435 bp = call->request;
436 bp[0] = htonl(FSFETCHDATA64);
David Howellse49c7b22020-04-10 20:51:51 +0100437 bp[1] = htonl(vp->fid.vid);
438 bp[2] = htonl(vp->fid.vnode);
439 bp[3] = htonl(vp->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000440 bp[4] = htonl(upper_32_bits(req->pos));
441 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700442 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000443 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700444
David Howellse49c7b22020-04-10 20:51:51 +0100445 trace_afs_make_fs_call(call, &vp->fid);
446 afs_make_op_call(op, call, GFP_NOFS);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700447}
448
David Howells08e0e7c2007-04-26 15:55:03 -0700449/*
450 * fetch data from a file
451 */
David Howellse49c7b22020-04-10 20:51:51 +0100452void afs_fs_fetch_data(struct afs_operation *op)
David Howells08e0e7c2007-04-26 15:55:03 -0700453{
David Howellse49c7b22020-04-10 20:51:51 +0100454 struct afs_vnode_param *vp = &op->file[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700455 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +0100456 struct afs_read *req = op->fetch.req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 __be32 *bp;
458
David Howellsb537a3c22021-09-10 00:01:52 +0100459 if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
David Howellse49c7b22020-04-10 20:51:51 +0100460 return afs_fs_fetch_data64(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700461
David Howells08e0e7c2007-04-26 15:55:03 -0700462 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
David Howellse49c7b22020-04-10 20:51:51 +0100464 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700465 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100466 return afs_op_nomem(op);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467
David Howellsc4508462020-02-06 14:22:28 +0000468 req->call_debug_id = call->debug_id;
469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700471 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 bp[0] = htonl(FSFETCHDATA);
David Howellse49c7b22020-04-10 20:51:51 +0100473 bp[1] = htonl(vp->fid.vid);
474 bp[2] = htonl(vp->fid.vnode);
475 bp[3] = htonl(vp->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000476 bp[4] = htonl(lower_32_bits(req->pos));
477 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
David Howellse49c7b22020-04-10 20:51:51 +0100479 trace_afs_make_fs_call(call, &vp->fid);
480 afs_make_op_call(op, call, GFP_NOFS);
David Howellsec268152007-04-26 15:49:28 -0700481}
David Howells260a9802007-04-26 15:59:35 -0700482
483/*
484 * deliver reply data to an FS.CreateFile or an FS.MakeDir
485 */
David Howellsd0016482016-08-30 20:42:14 +0100486static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700487{
David Howellse49c7b22020-04-10 20:51:51 +0100488 struct afs_operation *op = call->op;
489 struct afs_vnode_param *dvp = &op->file[0];
490 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700491 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100492 int ret;
David Howells260a9802007-04-26 15:59:35 -0700493
David Howellsd0016482016-08-30 20:42:14 +0100494 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100495 if (ret < 0)
496 return ret;
David Howells260a9802007-04-26 15:59:35 -0700497
498 /* unmarshall the reply once we've received all of it */
499 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100500 xdr_decode_AFSFid(&bp, &op->file[1].fid);
501 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
502 xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
503 xdr_decode_AFSCallBack(&bp, call, &vp->scb);
504 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700505
506 _leave(" = 0 [done]");
507 return 0;
508}
509
510/*
511 * FS.CreateFile and FS.MakeDir operation type
512 */
David Howells025db802017-11-02 15:27:51 +0000513static const struct afs_call_type afs_RXFSCreateFile = {
514 .name = "FS.CreateFile",
515 .op = afs_FS_CreateFile,
516 .deliver = afs_deliver_fs_create_vnode,
517 .destructor = afs_flat_call_destructor,
518};
519
David Howellse49c7b22020-04-10 20:51:51 +0100520/*
521 * Create a file.
522 */
523void afs_fs_create_file(struct afs_operation *op)
524{
525 const struct qstr *name = &op->dentry->d_name;
526 struct afs_vnode_param *dvp = &op->file[0];
527 struct afs_call *call;
528 size_t namesz, reqsz, padsz;
529 __be32 *bp;
530
531 _enter("");
532
533 namesz = name->len;
534 padsz = (4 - (namesz & 3)) & 3;
535 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
536
537 call = afs_alloc_flat_call(op->net, &afs_RXFSCreateFile,
538 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
539 if (!call)
540 return afs_op_nomem(op);
541
542 /* marshall the parameters */
543 bp = call->request;
544 *bp++ = htonl(FSCREATEFILE);
545 *bp++ = htonl(dvp->fid.vid);
546 *bp++ = htonl(dvp->fid.vnode);
547 *bp++ = htonl(dvp->fid.unique);
548 *bp++ = htonl(namesz);
549 memcpy(bp, name->name, namesz);
550 bp = (void *) bp + namesz;
551 if (padsz > 0) {
552 memset(bp, 0, padsz);
553 bp = (void *) bp + padsz;
554 }
555 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
556 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
557 *bp++ = 0; /* owner */
558 *bp++ = 0; /* group */
559 *bp++ = htonl(op->create.mode & S_IALLUGO); /* unix mode */
560 *bp++ = 0; /* segment size */
561
562 trace_afs_make_fs_call1(call, &dvp->fid, name);
563 afs_make_op_call(op, call, GFP_NOFS);
564}
565
David Howells025db802017-11-02 15:27:51 +0000566static const struct afs_call_type afs_RXFSMakeDir = {
567 .name = "FS.MakeDir",
568 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700569 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700570 .destructor = afs_flat_call_destructor,
571};
572
573/*
David Howellse49c7b22020-04-10 20:51:51 +0100574 * Create a new directory
David Howells260a9802007-04-26 15:59:35 -0700575 */
David Howellse49c7b22020-04-10 20:51:51 +0100576void afs_fs_make_dir(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700577{
David Howellse49c7b22020-04-10 20:51:51 +0100578 const struct qstr *name = &op->dentry->d_name;
579 struct afs_vnode_param *dvp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700580 struct afs_call *call;
581 size_t namesz, reqsz, padsz;
582 __be32 *bp;
583
584 _enter("");
585
David Howellse49c7b22020-04-10 20:51:51 +0100586 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700587 padsz = (4 - (namesz & 3)) & 3;
588 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
589
David Howellse49c7b22020-04-10 20:51:51 +0100590 call = afs_alloc_flat_call(op->net, &afs_RXFSMakeDir,
591 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700592 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100593 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700594
595 /* marshall the parameters */
596 bp = call->request;
David Howellse49c7b22020-04-10 20:51:51 +0100597 *bp++ = htonl(FSMAKEDIR);
598 *bp++ = htonl(dvp->fid.vid);
599 *bp++ = htonl(dvp->fid.vnode);
600 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700601 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100602 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700603 bp = (void *) bp + namesz;
604 if (padsz > 0) {
605 memset(bp, 0, padsz);
606 bp = (void *) bp + padsz;
607 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000608 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
David Howellse49c7b22020-04-10 20:51:51 +0100609 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700610 *bp++ = 0; /* owner */
611 *bp++ = 0; /* group */
David Howellse49c7b22020-04-10 20:51:51 +0100612 *bp++ = htonl(op->create.mode & S_IALLUGO); /* unix mode */
David Howells260a9802007-04-26 15:59:35 -0700613 *bp++ = 0; /* segment size */
614
David Howellse49c7b22020-04-10 20:51:51 +0100615 trace_afs_make_fs_call1(call, &dvp->fid, name);
616 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700617}
618
619/*
David Howellse49c7b22020-04-10 20:51:51 +0100620 * Deliver reply data to any operation that returns status and volume sync.
David Howells260a9802007-04-26 15:59:35 -0700621 */
David Howellse49c7b22020-04-10 20:51:51 +0100622static int afs_deliver_fs_file_status_and_vol(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700623{
David Howellse49c7b22020-04-10 20:51:51 +0100624 struct afs_operation *op = call->op;
625 struct afs_vnode_param *vp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700626 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100627 int ret;
David Howells260a9802007-04-26 15:59:35 -0700628
David Howellsd0016482016-08-30 20:42:14 +0100629 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100630 if (ret < 0)
631 return ret;
David Howells260a9802007-04-26 15:59:35 -0700632
633 /* unmarshall the reply once we've received all of it */
634 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100635 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
636 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700637
638 _leave(" = 0 [done]");
639 return 0;
640}
641
642/*
David Howellse49c7b22020-04-10 20:51:51 +0100643 * FS.RemoveFile operation type
David Howells260a9802007-04-26 15:59:35 -0700644 */
David Howells025db802017-11-02 15:27:51 +0000645static const struct afs_call_type afs_RXFSRemoveFile = {
646 .name = "FS.RemoveFile",
647 .op = afs_FS_RemoveFile,
David Howellse49c7b22020-04-10 20:51:51 +0100648 .deliver = afs_deliver_fs_file_status_and_vol,
David Howells260a9802007-04-26 15:59:35 -0700649 .destructor = afs_flat_call_destructor,
650};
651
652/*
David Howellse49c7b22020-04-10 20:51:51 +0100653 * Remove a file.
David Howells260a9802007-04-26 15:59:35 -0700654 */
David Howellse49c7b22020-04-10 20:51:51 +0100655void afs_fs_remove_file(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700656{
David Howellse49c7b22020-04-10 20:51:51 +0100657 const struct qstr *name = &op->dentry->d_name;
658 struct afs_vnode_param *dvp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700659 struct afs_call *call;
660 size_t namesz, reqsz, padsz;
661 __be32 *bp;
662
663 _enter("");
664
David Howellse49c7b22020-04-10 20:51:51 +0100665 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700666 padsz = (4 - (namesz & 3)) & 3;
667 reqsz = (5 * 4) + namesz + padsz;
668
David Howellse49c7b22020-04-10 20:51:51 +0100669 call = afs_alloc_flat_call(op->net, &afs_RXFSRemoveFile,
670 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700671 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100672 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700673
674 /* marshall the parameters */
675 bp = call->request;
David Howellse49c7b22020-04-10 20:51:51 +0100676 *bp++ = htonl(FSREMOVEFILE);
677 *bp++ = htonl(dvp->fid.vid);
678 *bp++ = htonl(dvp->fid.vnode);
679 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700680 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100681 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700682 bp = (void *) bp + namesz;
683 if (padsz > 0) {
684 memset(bp, 0, padsz);
685 bp = (void *) bp + padsz;
686 }
687
David Howellse49c7b22020-04-10 20:51:51 +0100688 trace_afs_make_fs_call1(call, &dvp->fid, name);
689 afs_make_op_call(op, call, GFP_NOFS);
690}
691
692static const struct afs_call_type afs_RXFSRemoveDir = {
693 .name = "FS.RemoveDir",
694 .op = afs_FS_RemoveDir,
695 .deliver = afs_deliver_fs_file_status_and_vol,
696 .destructor = afs_flat_call_destructor,
697};
698
699/*
700 * Remove a directory.
701 */
702void afs_fs_remove_dir(struct afs_operation *op)
703{
704 const struct qstr *name = &op->dentry->d_name;
705 struct afs_vnode_param *dvp = &op->file[0];
706 struct afs_call *call;
707 size_t namesz, reqsz, padsz;
708 __be32 *bp;
709
710 _enter("");
711
712 namesz = name->len;
713 padsz = (4 - (namesz & 3)) & 3;
714 reqsz = (5 * 4) + namesz + padsz;
715
716 call = afs_alloc_flat_call(op->net, &afs_RXFSRemoveDir,
717 reqsz, (21 + 6) * 4);
718 if (!call)
719 return afs_op_nomem(op);
720
721 /* marshall the parameters */
722 bp = call->request;
723 *bp++ = htonl(FSREMOVEDIR);
724 *bp++ = htonl(dvp->fid.vid);
725 *bp++ = htonl(dvp->fid.vnode);
726 *bp++ = htonl(dvp->fid.unique);
727 *bp++ = htonl(namesz);
728 memcpy(bp, name->name, namesz);
729 bp = (void *) bp + namesz;
730 if (padsz > 0) {
731 memset(bp, 0, padsz);
732 bp = (void *) bp + padsz;
733 }
734
735 trace_afs_make_fs_call1(call, &dvp->fid, name);
736 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700737}
738
739/*
740 * deliver reply data to an FS.Link
741 */
David Howellsd0016482016-08-30 20:42:14 +0100742static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700743{
David Howellse49c7b22020-04-10 20:51:51 +0100744 struct afs_operation *op = call->op;
745 struct afs_vnode_param *dvp = &op->file[0];
746 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700747 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100748 int ret;
David Howells260a9802007-04-26 15:59:35 -0700749
David Howellsd0016482016-08-30 20:42:14 +0100750 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700751
David Howellsd0016482016-08-30 20:42:14 +0100752 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100753 if (ret < 0)
754 return ret;
David Howells260a9802007-04-26 15:59:35 -0700755
756 /* unmarshall the reply once we've received all of it */
757 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100758 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
759 xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
760 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700761
762 _leave(" = 0 [done]");
763 return 0;
764}
765
766/*
767 * FS.Link operation type
768 */
769static const struct afs_call_type afs_RXFSLink = {
770 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000771 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700772 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700773 .destructor = afs_flat_call_destructor,
774};
775
776/*
777 * make a hard link
778 */
David Howellse49c7b22020-04-10 20:51:51 +0100779void afs_fs_link(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700780{
David Howellse49c7b22020-04-10 20:51:51 +0100781 const struct qstr *name = &op->dentry->d_name;
782 struct afs_vnode_param *dvp = &op->file[0];
783 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700784 struct afs_call *call;
785 size_t namesz, reqsz, padsz;
786 __be32 *bp;
787
788 _enter("");
789
David Howellse49c7b22020-04-10 20:51:51 +0100790 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700791 padsz = (4 - (namesz & 3)) & 3;
792 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
793
David Howellse49c7b22020-04-10 20:51:51 +0100794 call = afs_alloc_flat_call(op->net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700795 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100796 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700797
798 /* marshall the parameters */
799 bp = call->request;
800 *bp++ = htonl(FSLINK);
David Howellse49c7b22020-04-10 20:51:51 +0100801 *bp++ = htonl(dvp->fid.vid);
802 *bp++ = htonl(dvp->fid.vnode);
803 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700804 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100805 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700806 bp = (void *) bp + namesz;
807 if (padsz > 0) {
808 memset(bp, 0, padsz);
809 bp = (void *) bp + padsz;
810 }
David Howellse49c7b22020-04-10 20:51:51 +0100811 *bp++ = htonl(vp->fid.vid);
812 *bp++ = htonl(vp->fid.vnode);
813 *bp++ = htonl(vp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700814
David Howellse49c7b22020-04-10 20:51:51 +0100815 trace_afs_make_fs_call1(call, &vp->fid, name);
816 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700817}
818
819/*
820 * deliver reply data to an FS.Symlink
821 */
David Howellsd0016482016-08-30 20:42:14 +0100822static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700823{
David Howellse49c7b22020-04-10 20:51:51 +0100824 struct afs_operation *op = call->op;
825 struct afs_vnode_param *dvp = &op->file[0];
826 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700827 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100828 int ret;
David Howells260a9802007-04-26 15:59:35 -0700829
David Howellsd0016482016-08-30 20:42:14 +0100830 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700831
David Howellsd0016482016-08-30 20:42:14 +0100832 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100833 if (ret < 0)
834 return ret;
David Howells260a9802007-04-26 15:59:35 -0700835
836 /* unmarshall the reply once we've received all of it */
837 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100838 xdr_decode_AFSFid(&bp, &vp->fid);
839 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
840 xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
841 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700842
843 _leave(" = 0 [done]");
844 return 0;
845}
846
847/*
848 * FS.Symlink operation type
849 */
850static const struct afs_call_type afs_RXFSSymlink = {
851 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +0000852 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -0700853 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700854 .destructor = afs_flat_call_destructor,
855};
856
857/*
858 * create a symbolic link
859 */
David Howellse49c7b22020-04-10 20:51:51 +0100860void afs_fs_symlink(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700861{
David Howellse49c7b22020-04-10 20:51:51 +0100862 const struct qstr *name = &op->dentry->d_name;
863 struct afs_vnode_param *dvp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700864 struct afs_call *call;
865 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
866 __be32 *bp;
867
868 _enter("");
869
David Howellse49c7b22020-04-10 20:51:51 +0100870 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700871 padsz = (4 - (namesz & 3)) & 3;
872
David Howellse49c7b22020-04-10 20:51:51 +0100873 c_namesz = strlen(op->create.symlink);
David Howells260a9802007-04-26 15:59:35 -0700874 c_padsz = (4 - (c_namesz & 3)) & 3;
875
876 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
877
David Howellse49c7b22020-04-10 20:51:51 +0100878 call = afs_alloc_flat_call(op->net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700879 (3 + 21 + 21 + 6) * 4);
880 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100881 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700882
883 /* marshall the parameters */
884 bp = call->request;
885 *bp++ = htonl(FSSYMLINK);
David Howellse49c7b22020-04-10 20:51:51 +0100886 *bp++ = htonl(dvp->fid.vid);
887 *bp++ = htonl(dvp->fid.vnode);
888 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700889 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100890 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700891 bp = (void *) bp + namesz;
892 if (padsz > 0) {
893 memset(bp, 0, padsz);
894 bp = (void *) bp + padsz;
895 }
896 *bp++ = htonl(c_namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100897 memcpy(bp, op->create.symlink, c_namesz);
David Howells260a9802007-04-26 15:59:35 -0700898 bp = (void *) bp + c_namesz;
899 if (c_padsz > 0) {
900 memset(bp, 0, c_padsz);
901 bp = (void *) bp + c_padsz;
902 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000903 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
David Howellse49c7b22020-04-10 20:51:51 +0100904 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700905 *bp++ = 0; /* owner */
906 *bp++ = 0; /* group */
907 *bp++ = htonl(S_IRWXUGO); /* unix mode */
908 *bp++ = 0; /* segment size */
909
David Howellse49c7b22020-04-10 20:51:51 +0100910 trace_afs_make_fs_call1(call, &dvp->fid, name);
911 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700912}
913
914/*
915 * deliver reply data to an FS.Rename
916 */
David Howellsd0016482016-08-30 20:42:14 +0100917static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700918{
David Howellse49c7b22020-04-10 20:51:51 +0100919 struct afs_operation *op = call->op;
920 struct afs_vnode_param *orig_dvp = &op->file[0];
921 struct afs_vnode_param *new_dvp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700922 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100923 int ret;
David Howells260a9802007-04-26 15:59:35 -0700924
David Howellsd0016482016-08-30 20:42:14 +0100925 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100926 if (ret < 0)
927 return ret;
David Howells260a9802007-04-26 15:59:35 -0700928
David Howells38355ee2020-04-08 16:13:20 +0100929 bp = call->buffer;
David Howellsb98f0ec2020-04-08 20:56:20 +0100930 /* If the two dirs are the same, we have two copies of the same status
931 * report, so we just decode it twice.
932 */
David Howellse49c7b22020-04-10 20:51:51 +0100933 xdr_decode_AFSFetchStatus(&bp, call, &orig_dvp->scb);
934 xdr_decode_AFSFetchStatus(&bp, call, &new_dvp->scb);
935 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700936
937 _leave(" = 0 [done]");
938 return 0;
939}
940
941/*
942 * FS.Rename operation type
943 */
944static const struct afs_call_type afs_RXFSRename = {
945 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +0000946 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -0700947 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -0700948 .destructor = afs_flat_call_destructor,
949};
950
951/*
David Howellsa58823a2019-05-09 15:16:10 +0100952 * Rename/move a file or directory.
David Howells260a9802007-04-26 15:59:35 -0700953 */
David Howellse49c7b22020-04-10 20:51:51 +0100954void afs_fs_rename(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700955{
David Howellse49c7b22020-04-10 20:51:51 +0100956 struct afs_vnode_param *orig_dvp = &op->file[0];
957 struct afs_vnode_param *new_dvp = &op->file[1];
958 const struct qstr *orig_name = &op->dentry->d_name;
959 const struct qstr *new_name = &op->dentry_2->d_name;
David Howells260a9802007-04-26 15:59:35 -0700960 struct afs_call *call;
961 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
962 __be32 *bp;
963
964 _enter("");
965
David Howellse49c7b22020-04-10 20:51:51 +0100966 o_namesz = orig_name->len;
David Howells260a9802007-04-26 15:59:35 -0700967 o_padsz = (4 - (o_namesz & 3)) & 3;
968
David Howellse49c7b22020-04-10 20:51:51 +0100969 n_namesz = new_name->len;
David Howells260a9802007-04-26 15:59:35 -0700970 n_padsz = (4 - (n_namesz & 3)) & 3;
971
972 reqsz = (4 * 4) +
973 4 + o_namesz + o_padsz +
974 (3 * 4) +
975 4 + n_namesz + n_padsz;
976
David Howellse49c7b22020-04-10 20:51:51 +0100977 call = afs_alloc_flat_call(op->net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700978 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100979 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700980
981 /* marshall the parameters */
982 bp = call->request;
983 *bp++ = htonl(FSRENAME);
David Howellse49c7b22020-04-10 20:51:51 +0100984 *bp++ = htonl(orig_dvp->fid.vid);
985 *bp++ = htonl(orig_dvp->fid.vnode);
986 *bp++ = htonl(orig_dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700987 *bp++ = htonl(o_namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100988 memcpy(bp, orig_name->name, o_namesz);
David Howells260a9802007-04-26 15:59:35 -0700989 bp = (void *) bp + o_namesz;
990 if (o_padsz > 0) {
991 memset(bp, 0, o_padsz);
992 bp = (void *) bp + o_padsz;
993 }
994
David Howellse49c7b22020-04-10 20:51:51 +0100995 *bp++ = htonl(new_dvp->fid.vid);
996 *bp++ = htonl(new_dvp->fid.vnode);
997 *bp++ = htonl(new_dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700998 *bp++ = htonl(n_namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100999 memcpy(bp, new_name->name, n_namesz);
David Howells260a9802007-04-26 15:59:35 -07001000 bp = (void *) bp + n_namesz;
1001 if (n_padsz > 0) {
1002 memset(bp, 0, n_padsz);
1003 bp = (void *) bp + n_padsz;
1004 }
1005
David Howellse49c7b22020-04-10 20:51:51 +01001006 trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name);
1007 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -07001008}
David Howells31143d52007-05-09 02:33:46 -07001009
1010/*
David Howellse49c7b22020-04-10 20:51:51 +01001011 * Deliver reply data to FS.StoreData or FS.StoreStatus
David Howells31143d52007-05-09 02:33:46 -07001012 */
David Howellsd0016482016-08-30 20:42:14 +01001013static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001014{
David Howellse49c7b22020-04-10 20:51:51 +01001015 struct afs_operation *op = call->op;
1016 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001017 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001018 int ret;
David Howells31143d52007-05-09 02:33:46 -07001019
David Howellsd0016482016-08-30 20:42:14 +01001020 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001021
David Howellsd0016482016-08-30 20:42:14 +01001022 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001023 if (ret < 0)
1024 return ret;
David Howells31143d52007-05-09 02:33:46 -07001025
1026 /* unmarshall the reply once we've received all of it */
1027 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001028 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
1029 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells31143d52007-05-09 02:33:46 -07001030
David Howells31143d52007-05-09 02:33:46 -07001031 _leave(" = 0 [done]");
1032 return 0;
1033}
1034
1035/*
1036 * FS.StoreData operation type
1037 */
1038static const struct afs_call_type afs_RXFSStoreData = {
1039 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001040 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001041 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001042 .destructor = afs_flat_call_destructor,
1043};
1044
David Howellsb9b1f8d2007-05-10 03:15:21 -07001045static const struct afs_call_type afs_RXFSStoreData64 = {
1046 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001047 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001048 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001049 .destructor = afs_flat_call_destructor,
1050};
1051
1052/*
1053 * store a set of pages to a very large file
1054 */
David Howellsbd80d8a2020-02-06 14:22:28 +00001055static void afs_fs_store_data64(struct afs_operation *op)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001056{
David Howellse49c7b22020-04-10 20:51:51 +01001057 struct afs_vnode_param *vp = &op->file[0];
David Howellsb9b1f8d2007-05-10 03:15:21 -07001058 struct afs_call *call;
1059 __be32 *bp;
1060
David Howells3b6492d2018-10-20 00:57:57 +01001061 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001062 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001063
David Howellse49c7b22020-04-10 20:51:51 +01001064 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001065 (4 + 6 + 3 * 2) * 4,
1066 (21 + 6) * 4);
1067 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001068 return afs_op_nomem(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001069
David Howellsbd80d8a2020-02-06 14:22:28 +00001070 call->write_iter = op->store.write_iter;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001071
1072 /* marshall the parameters */
1073 bp = call->request;
1074 *bp++ = htonl(FSSTOREDATA64);
David Howellse49c7b22020-04-10 20:51:51 +01001075 *bp++ = htonl(vp->fid.vid);
1076 *bp++ = htonl(vp->fid.vnode);
1077 *bp++ = htonl(vp->fid.unique);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001078
Marc Dionneab94f5d2017-03-16 16:27:47 +00001079 *bp++ = htonl(AFS_SET_MTIME); /* mask */
David Howellse49c7b22020-04-10 20:51:51 +01001080 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001081 *bp++ = 0; /* owner */
1082 *bp++ = 0; /* group */
1083 *bp++ = 0; /* unix mode */
1084 *bp++ = 0; /* segment size */
1085
David Howellsbd80d8a2020-02-06 14:22:28 +00001086 *bp++ = htonl(upper_32_bits(op->store.pos));
1087 *bp++ = htonl(lower_32_bits(op->store.pos));
1088 *bp++ = htonl(upper_32_bits(op->store.size));
1089 *bp++ = htonl(lower_32_bits(op->store.size));
1090 *bp++ = htonl(upper_32_bits(op->store.i_size));
1091 *bp++ = htonl(lower_32_bits(op->store.i_size));
David Howellsb9b1f8d2007-05-10 03:15:21 -07001092
David Howellse49c7b22020-04-10 20:51:51 +01001093 trace_afs_make_fs_call(call, &vp->fid);
1094 afs_make_op_call(op, call, GFP_NOFS);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001095}
1096
David Howells31143d52007-05-09 02:33:46 -07001097/*
David Howellsbd80d8a2020-02-06 14:22:28 +00001098 * Write data to a file on the server.
David Howells31143d52007-05-09 02:33:46 -07001099 */
David Howellse49c7b22020-04-10 20:51:51 +01001100void afs_fs_store_data(struct afs_operation *op)
David Howells31143d52007-05-09 02:33:46 -07001101{
David Howellse49c7b22020-04-10 20:51:51 +01001102 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001103 struct afs_call *call;
David Howells31143d52007-05-09 02:33:46 -07001104 __be32 *bp;
1105
David Howells3b6492d2018-10-20 00:57:57 +01001106 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001107 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001108
David Howells31143d52007-05-09 02:33:46 -07001109 _debug("size %llx, at %llx, i_size %llx",
David Howellsbd80d8a2020-02-06 14:22:28 +00001110 (unsigned long long)op->store.size,
1111 (unsigned long long)op->store.pos,
1112 (unsigned long long)op->store.i_size);
David Howells31143d52007-05-09 02:33:46 -07001113
David Howellsb537a3c22021-09-10 00:01:52 +01001114 if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
David Howellsbd80d8a2020-02-06 14:22:28 +00001115 return afs_fs_store_data64(op);
David Howells31143d52007-05-09 02:33:46 -07001116
David Howellse49c7b22020-04-10 20:51:51 +01001117 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001118 (4 + 6 + 3) * 4,
1119 (21 + 6) * 4);
1120 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001121 return afs_op_nomem(op);
David Howells31143d52007-05-09 02:33:46 -07001122
David Howellsbd80d8a2020-02-06 14:22:28 +00001123 call->write_iter = op->store.write_iter;
David Howells31143d52007-05-09 02:33:46 -07001124
1125 /* marshall the parameters */
1126 bp = call->request;
1127 *bp++ = htonl(FSSTOREDATA);
David Howellse49c7b22020-04-10 20:51:51 +01001128 *bp++ = htonl(vp->fid.vid);
1129 *bp++ = htonl(vp->fid.vnode);
1130 *bp++ = htonl(vp->fid.unique);
David Howells31143d52007-05-09 02:33:46 -07001131
Marc Dionneab94f5d2017-03-16 16:27:47 +00001132 *bp++ = htonl(AFS_SET_MTIME); /* mask */
David Howellse49c7b22020-04-10 20:51:51 +01001133 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001134 *bp++ = 0; /* owner */
1135 *bp++ = 0; /* group */
1136 *bp++ = 0; /* unix mode */
1137 *bp++ = 0; /* segment size */
1138
David Howellsbd80d8a2020-02-06 14:22:28 +00001139 *bp++ = htonl(lower_32_bits(op->store.pos));
1140 *bp++ = htonl(lower_32_bits(op->store.size));
1141 *bp++ = htonl(lower_32_bits(op->store.i_size));
David Howells31143d52007-05-09 02:33:46 -07001142
David Howellse49c7b22020-04-10 20:51:51 +01001143 trace_afs_make_fs_call(call, &vp->fid);
1144 afs_make_op_call(op, call, GFP_NOFS);
David Howells31143d52007-05-09 02:33:46 -07001145}
1146
1147/*
1148 * FS.StoreStatus operation type
1149 */
1150static const struct afs_call_type afs_RXFSStoreStatus = {
1151 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001152 .op = afs_FS_StoreStatus,
David Howellse49c7b22020-04-10 20:51:51 +01001153 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001154 .destructor = afs_flat_call_destructor,
1155};
1156
1157static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1158 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001159 .op = afs_FS_StoreData,
David Howellse49c7b22020-04-10 20:51:51 +01001160 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001161 .destructor = afs_flat_call_destructor,
1162};
1163
David Howellsb9b1f8d2007-05-10 03:15:21 -07001164static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1165 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001166 .op = afs_FS_StoreData64,
David Howellse49c7b22020-04-10 20:51:51 +01001167 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001168 .destructor = afs_flat_call_destructor,
1169};
1170
1171/*
1172 * set the attributes on a very large file, using FS.StoreData rather than
1173 * FS.StoreStatus so as to alter the file size also
1174 */
David Howellse49c7b22020-04-10 20:51:51 +01001175static void afs_fs_setattr_size64(struct afs_operation *op)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001176{
David Howellse49c7b22020-04-10 20:51:51 +01001177 struct afs_vnode_param *vp = &op->file[0];
David Howellsb9b1f8d2007-05-10 03:15:21 -07001178 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01001179 struct iattr *attr = op->setattr.attr;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001180 __be32 *bp;
1181
David Howells3b6492d2018-10-20 00:57:57 +01001182 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001183 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001184
1185 ASSERT(attr->ia_valid & ATTR_SIZE);
1186
David Howellse49c7b22020-04-10 20:51:51 +01001187 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001188 (4 + 6 + 3 * 2) * 4,
1189 (21 + 6) * 4);
1190 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001191 return afs_op_nomem(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001192
1193 /* marshall the parameters */
1194 bp = call->request;
1195 *bp++ = htonl(FSSTOREDATA64);
David Howellse49c7b22020-04-10 20:51:51 +01001196 *bp++ = htonl(vp->fid.vid);
1197 *bp++ = htonl(vp->fid.vnode);
1198 *bp++ = htonl(vp->fid.unique);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001199
1200 xdr_encode_AFS_StoreStatus(&bp, attr);
1201
David Howellse49c7b22020-04-10 20:51:51 +01001202 *bp++ = htonl(upper_32_bits(attr->ia_size)); /* position of start of write */
1203 *bp++ = htonl(lower_32_bits(attr->ia_size));
1204 *bp++ = 0; /* size of write */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001205 *bp++ = 0;
David Howellse49c7b22020-04-10 20:51:51 +01001206 *bp++ = htonl(upper_32_bits(attr->ia_size)); /* new file length */
1207 *bp++ = htonl(lower_32_bits(attr->ia_size));
David Howellsb9b1f8d2007-05-10 03:15:21 -07001208
David Howellse49c7b22020-04-10 20:51:51 +01001209 trace_afs_make_fs_call(call, &vp->fid);
1210 afs_make_op_call(op, call, GFP_NOFS);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001211}
1212
David Howells31143d52007-05-09 02:33:46 -07001213/*
1214 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1215 * so as to alter the file size also
1216 */
David Howellse49c7b22020-04-10 20:51:51 +01001217static void afs_fs_setattr_size(struct afs_operation *op)
David Howells31143d52007-05-09 02:33:46 -07001218{
David Howellse49c7b22020-04-10 20:51:51 +01001219 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001220 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01001221 struct iattr *attr = op->setattr.attr;
David Howells31143d52007-05-09 02:33:46 -07001222 __be32 *bp;
1223
David Howells3b6492d2018-10-20 00:57:57 +01001224 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001225 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001226
1227 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb537a3c22021-09-10 00:01:52 +01001228 if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
David Howellse49c7b22020-04-10 20:51:51 +01001229 return afs_fs_setattr_size64(op);
David Howells31143d52007-05-09 02:33:46 -07001230
David Howellse49c7b22020-04-10 20:51:51 +01001231 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001232 (4 + 6 + 3) * 4,
1233 (21 + 6) * 4);
1234 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001235 return afs_op_nomem(op);
David Howells31143d52007-05-09 02:33:46 -07001236
1237 /* marshall the parameters */
1238 bp = call->request;
1239 *bp++ = htonl(FSSTOREDATA);
David Howellse49c7b22020-04-10 20:51:51 +01001240 *bp++ = htonl(vp->fid.vid);
1241 *bp++ = htonl(vp->fid.vnode);
1242 *bp++ = htonl(vp->fid.unique);
David Howells31143d52007-05-09 02:33:46 -07001243
1244 xdr_encode_AFS_StoreStatus(&bp, attr);
1245
David Howells8c7ae382019-03-27 22:48:02 +00001246 *bp++ = htonl(attr->ia_size); /* position of start of write */
David Howells31143d52007-05-09 02:33:46 -07001247 *bp++ = 0; /* size of write */
1248 *bp++ = htonl(attr->ia_size); /* new file length */
1249
David Howellse49c7b22020-04-10 20:51:51 +01001250 trace_afs_make_fs_call(call, &vp->fid);
1251 afs_make_op_call(op, call, GFP_NOFS);
David Howells31143d52007-05-09 02:33:46 -07001252}
1253
1254/*
1255 * set the attributes on a file, using FS.StoreData if there's a change in file
1256 * size, and FS.StoreStatus otherwise
1257 */
David Howellse49c7b22020-04-10 20:51:51 +01001258void afs_fs_setattr(struct afs_operation *op)
David Howells31143d52007-05-09 02:33:46 -07001259{
David Howellse49c7b22020-04-10 20:51:51 +01001260 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001261 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01001262 struct iattr *attr = op->setattr.attr;
David Howells31143d52007-05-09 02:33:46 -07001263 __be32 *bp;
1264
1265 if (attr->ia_valid & ATTR_SIZE)
David Howellse49c7b22020-04-10 20:51:51 +01001266 return afs_fs_setattr_size(op);
David Howells31143d52007-05-09 02:33:46 -07001267
David Howells3b6492d2018-10-20 00:57:57 +01001268 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001269 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001270
David Howellse49c7b22020-04-10 20:51:51 +01001271 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001272 (4 + 6) * 4,
1273 (21 + 6) * 4);
1274 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001275 return afs_op_nomem(op);
David Howells31143d52007-05-09 02:33:46 -07001276
1277 /* marshall the parameters */
1278 bp = call->request;
1279 *bp++ = htonl(FSSTORESTATUS);
David Howellse49c7b22020-04-10 20:51:51 +01001280 *bp++ = htonl(vp->fid.vid);
1281 *bp++ = htonl(vp->fid.vnode);
1282 *bp++ = htonl(vp->fid.unique);
David Howells31143d52007-05-09 02:33:46 -07001283
David Howellse49c7b22020-04-10 20:51:51 +01001284 xdr_encode_AFS_StoreStatus(&bp, op->setattr.attr);
David Howells31143d52007-05-09 02:33:46 -07001285
David Howellse49c7b22020-04-10 20:51:51 +01001286 trace_afs_make_fs_call(call, &vp->fid);
1287 afs_make_op_call(op, call, GFP_NOFS);
David Howells31143d52007-05-09 02:33:46 -07001288}
David Howells45222b92007-05-10 22:22:20 -07001289
1290/*
1291 * deliver reply data to an FS.GetVolumeStatus
1292 */
David Howellsd0016482016-08-30 20:42:14 +01001293static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001294{
David Howellse49c7b22020-04-10 20:51:51 +01001295 struct afs_operation *op = call->op;
David Howells45222b92007-05-10 22:22:20 -07001296 const __be32 *bp;
1297 char *p;
David Howells12bdcf32018-10-20 00:57:56 +01001298 u32 size;
David Howells45222b92007-05-10 22:22:20 -07001299 int ret;
1300
David Howellsd0016482016-08-30 20:42:14 +01001301 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001302
1303 switch (call->unmarshall) {
1304 case 0:
David Howells45222b92007-05-10 22:22:20 -07001305 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001306 afs_extract_to_buf(call, 12 * 4);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001307 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001308
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001309 /* extract the returned status record */
David Howells45222b92007-05-10 22:22:20 -07001310 case 1:
1311 _debug("extract status");
David Howells12bdcf32018-10-20 00:57:56 +01001312 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001313 if (ret < 0)
1314 return ret;
David Howells45222b92007-05-10 22:22:20 -07001315
1316 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001317 xdr_decode_AFSFetchVolumeStatus(&bp, &op->volstatus.vs);
David Howells45222b92007-05-10 22:22:20 -07001318 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001319 afs_extract_to_tmp(call);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001320 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001321
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001322 /* extract the volume name length */
David Howells45222b92007-05-10 22:22:20 -07001323 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001324 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001325 if (ret < 0)
1326 return ret;
David Howells45222b92007-05-10 22:22:20 -07001327
1328 call->count = ntohl(call->tmp);
1329 _debug("volname length: %u", call->count);
1330 if (call->count >= AFSNAMEMAX)
David Howells7126ead2020-04-08 16:49:08 +01001331 return afs_protocol_error(call, afs_eproto_volname_len);
David Howells12bdcf32018-10-20 00:57:56 +01001332 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001333 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001334 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001335 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001336
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001337 /* extract the volume name */
David Howells45222b92007-05-10 22:22:20 -07001338 case 3:
1339 _debug("extract volname");
David Howells12bdcf32018-10-20 00:57:56 +01001340 ret = afs_extract_data(call, true);
1341 if (ret < 0)
1342 return ret;
David Howells45222b92007-05-10 22:22:20 -07001343
David Howellsffba7182019-05-09 22:22:50 +01001344 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001345 p[call->count] = 0;
1346 _debug("volname '%s'", p);
David Howells12bdcf32018-10-20 00:57:56 +01001347 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001348 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001349 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001350
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001351 /* extract the offline message length */
David Howells12bdcf32018-10-20 00:57:56 +01001352 case 4:
1353 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001354 if (ret < 0)
1355 return ret;
David Howells45222b92007-05-10 22:22:20 -07001356
1357 call->count = ntohl(call->tmp);
1358 _debug("offline msg length: %u", call->count);
1359 if (call->count >= AFSNAMEMAX)
David Howells7126ead2020-04-08 16:49:08 +01001360 return afs_protocol_error(call, afs_eproto_offline_msg_len);
David Howells12bdcf32018-10-20 00:57:56 +01001361 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001362 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001363 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001364 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001365
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001366 /* extract the offline message */
David Howells12bdcf32018-10-20 00:57:56 +01001367 case 5:
David Howells45222b92007-05-10 22:22:20 -07001368 _debug("extract offline");
David Howells12bdcf32018-10-20 00:57:56 +01001369 ret = afs_extract_data(call, true);
1370 if (ret < 0)
1371 return ret;
David Howells45222b92007-05-10 22:22:20 -07001372
David Howellsffba7182019-05-09 22:22:50 +01001373 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001374 p[call->count] = 0;
1375 _debug("offline '%s'", p);
1376
David Howells12bdcf32018-10-20 00:57:56 +01001377 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001378 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001379 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001380
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001381 /* extract the message of the day length */
David Howells12bdcf32018-10-20 00:57:56 +01001382 case 6:
1383 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001384 if (ret < 0)
1385 return ret;
David Howells45222b92007-05-10 22:22:20 -07001386
1387 call->count = ntohl(call->tmp);
1388 _debug("motd length: %u", call->count);
1389 if (call->count >= AFSNAMEMAX)
David Howells7126ead2020-04-08 16:49:08 +01001390 return afs_protocol_error(call, afs_eproto_motd_len);
David Howells12bdcf32018-10-20 00:57:56 +01001391 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001392 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001393 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001394 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001395
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001396 /* extract the message of the day */
David Howells12bdcf32018-10-20 00:57:56 +01001397 case 7:
David Howells45222b92007-05-10 22:22:20 -07001398 _debug("extract motd");
David Howells12bdcf32018-10-20 00:57:56 +01001399 ret = afs_extract_data(call, false);
1400 if (ret < 0)
1401 return ret;
David Howells45222b92007-05-10 22:22:20 -07001402
David Howellsffba7182019-05-09 22:22:50 +01001403 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001404 p[call->count] = 0;
1405 _debug("motd '%s'", p);
1406
David Howells45222b92007-05-10 22:22:20 -07001407 call->unmarshall++;
Gustavo A. R. Silvab2db6c32021-05-25 15:40:22 +01001408 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001409
David Howells12bdcf32018-10-20 00:57:56 +01001410 case 8:
David Howells45222b92007-05-10 22:22:20 -07001411 break;
1412 }
1413
David Howells45222b92007-05-10 22:22:20 -07001414 _leave(" = 0 [done]");
1415 return 0;
1416}
1417
1418/*
David Howells45222b92007-05-10 22:22:20 -07001419 * FS.GetVolumeStatus operation type
1420 */
1421static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1422 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001423 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001424 .deliver = afs_deliver_fs_get_volume_status,
David Howellsffba7182019-05-09 22:22:50 +01001425 .destructor = afs_flat_call_destructor,
David Howells45222b92007-05-10 22:22:20 -07001426};
1427
1428/*
1429 * fetch the status of a volume
1430 */
David Howellse49c7b22020-04-10 20:51:51 +01001431void afs_fs_get_volume_status(struct afs_operation *op)
David Howells45222b92007-05-10 22:22:20 -07001432{
David Howellse49c7b22020-04-10 20:51:51 +01001433 struct afs_vnode_param *vp = &op->file[0];
David Howells45222b92007-05-10 22:22:20 -07001434 struct afs_call *call;
1435 __be32 *bp;
David Howells45222b92007-05-10 22:22:20 -07001436
1437 _enter("");
1438
David Howellse49c7b22020-04-10 20:51:51 +01001439 call = afs_alloc_flat_call(op->net, &afs_RXFSGetVolumeStatus, 2 * 4,
David Howellsffba7182019-05-09 22:22:50 +01001440 max(12 * 4, AFSOPAQUEMAX + 1));
1441 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001442 return afs_op_nomem(op);
David Howells45222b92007-05-10 22:22:20 -07001443
1444 /* marshall the parameters */
1445 bp = call->request;
1446 bp[0] = htonl(FSGETVOLUMESTATUS);
David Howellse49c7b22020-04-10 20:51:51 +01001447 bp[1] = htonl(vp->fid.vid);
David Howells45222b92007-05-10 22:22:20 -07001448
David Howellse49c7b22020-04-10 20:51:51 +01001449 trace_afs_make_fs_call(call, &vp->fid);
1450 afs_make_op_call(op, call, GFP_NOFS);
David Howells45222b92007-05-10 22:22:20 -07001451}
David Howellse8d6c552007-07-15 23:40:12 -07001452
1453/*
1454 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1455 */
David Howellsd0016482016-08-30 20:42:14 +01001456static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001457{
David Howellse49c7b22020-04-10 20:51:51 +01001458 struct afs_operation *op = call->op;
David Howellse8d6c552007-07-15 23:40:12 -07001459 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001460 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001461
David Howellsd0016482016-08-30 20:42:14 +01001462 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001463
David Howellsd0016482016-08-30 20:42:14 +01001464 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001465 if (ret < 0)
1466 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001467
1468 /* unmarshall the reply once we've received all of it */
1469 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001470 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howellse8d6c552007-07-15 23:40:12 -07001471
1472 _leave(" = 0 [done]");
1473 return 0;
1474}
1475
1476/*
1477 * FS.SetLock operation type
1478 */
1479static const struct afs_call_type afs_RXFSSetLock = {
1480 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001481 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001482 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001483 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001484 .destructor = afs_flat_call_destructor,
1485};
1486
1487/*
1488 * FS.ExtendLock operation type
1489 */
1490static const struct afs_call_type afs_RXFSExtendLock = {
1491 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001492 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001493 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001494 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001495 .destructor = afs_flat_call_destructor,
1496};
1497
1498/*
1499 * FS.ReleaseLock operation type
1500 */
1501static const struct afs_call_type afs_RXFSReleaseLock = {
1502 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001503 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001504 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001505 .destructor = afs_flat_call_destructor,
1506};
1507
1508/*
David Howellsd2ddc772017-11-02 15:27:50 +00001509 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001510 */
David Howellse49c7b22020-04-10 20:51:51 +01001511void afs_fs_set_lock(struct afs_operation *op)
David Howellse8d6c552007-07-15 23:40:12 -07001512{
David Howellse49c7b22020-04-10 20:51:51 +01001513 struct afs_vnode_param *vp = &op->file[0];
David Howellse8d6c552007-07-15 23:40:12 -07001514 struct afs_call *call;
1515 __be32 *bp;
1516
1517 _enter("");
1518
David Howellse49c7b22020-04-10 20:51:51 +01001519 call = afs_alloc_flat_call(op->net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001520 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001521 return afs_op_nomem(op);
David Howellse8d6c552007-07-15 23:40:12 -07001522
1523 /* marshall the parameters */
1524 bp = call->request;
1525 *bp++ = htonl(FSSETLOCK);
David Howellse49c7b22020-04-10 20:51:51 +01001526 *bp++ = htonl(vp->fid.vid);
1527 *bp++ = htonl(vp->fid.vnode);
1528 *bp++ = htonl(vp->fid.unique);
1529 *bp++ = htonl(op->lock.type);
David Howellse8d6c552007-07-15 23:40:12 -07001530
David Howellse49c7b22020-04-10 20:51:51 +01001531 trace_afs_make_fs_calli(call, &vp->fid, op->lock.type);
1532 afs_make_op_call(op, call, GFP_NOFS);
David Howellse8d6c552007-07-15 23:40:12 -07001533}
1534
1535/*
1536 * extend a lock on a file
1537 */
David Howellse49c7b22020-04-10 20:51:51 +01001538void afs_fs_extend_lock(struct afs_operation *op)
David Howellse8d6c552007-07-15 23:40:12 -07001539{
David Howellse49c7b22020-04-10 20:51:51 +01001540 struct afs_vnode_param *vp = &op->file[0];
David Howellse8d6c552007-07-15 23:40:12 -07001541 struct afs_call *call;
1542 __be32 *bp;
1543
1544 _enter("");
1545
David Howellse49c7b22020-04-10 20:51:51 +01001546 call = afs_alloc_flat_call(op->net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001547 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001548 return afs_op_nomem(op);
David Howellse8d6c552007-07-15 23:40:12 -07001549
1550 /* marshall the parameters */
1551 bp = call->request;
1552 *bp++ = htonl(FSEXTENDLOCK);
David Howellse49c7b22020-04-10 20:51:51 +01001553 *bp++ = htonl(vp->fid.vid);
1554 *bp++ = htonl(vp->fid.vnode);
1555 *bp++ = htonl(vp->fid.unique);
David Howellse8d6c552007-07-15 23:40:12 -07001556
David Howellse49c7b22020-04-10 20:51:51 +01001557 trace_afs_make_fs_call(call, &vp->fid);
1558 afs_make_op_call(op, call, GFP_NOFS);
David Howellse8d6c552007-07-15 23:40:12 -07001559}
1560
1561/*
1562 * release a lock on a file
1563 */
David Howellse49c7b22020-04-10 20:51:51 +01001564void afs_fs_release_lock(struct afs_operation *op)
David Howellse8d6c552007-07-15 23:40:12 -07001565{
David Howellse49c7b22020-04-10 20:51:51 +01001566 struct afs_vnode_param *vp = &op->file[0];
David Howellse8d6c552007-07-15 23:40:12 -07001567 struct afs_call *call;
1568 __be32 *bp;
1569
1570 _enter("");
1571
David Howellse49c7b22020-04-10 20:51:51 +01001572 call = afs_alloc_flat_call(op->net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001573 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001574 return afs_op_nomem(op);
David Howellse8d6c552007-07-15 23:40:12 -07001575
1576 /* marshall the parameters */
1577 bp = call->request;
1578 *bp++ = htonl(FSRELEASELOCK);
David Howellse49c7b22020-04-10 20:51:51 +01001579 *bp++ = htonl(vp->fid.vid);
1580 *bp++ = htonl(vp->fid.vnode);
1581 *bp++ = htonl(vp->fid.unique);
David Howellse8d6c552007-07-15 23:40:12 -07001582
David Howellse49c7b22020-04-10 20:51:51 +01001583 trace_afs_make_fs_call(call, &vp->fid);
1584 afs_make_op_call(op, call, GFP_NOFS);
David Howellsc435ee32017-11-02 15:27:49 +00001585}
1586
1587/*
1588 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1589 */
1590static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1591{
1592 return afs_transfer_reply(call);
1593}
1594
1595/*
1596 * FS.GiveUpAllCallBacks operation type
1597 */
1598static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1599 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001600 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001601 .deliver = afs_deliver_fs_give_up_all_callbacks,
1602 .destructor = afs_flat_call_destructor,
1603};
1604
1605/*
1606 * Flush all the callbacks we have on a server.
1607 */
David Howellsd2ddc772017-11-02 15:27:50 +00001608int afs_fs_give_up_all_callbacks(struct afs_net *net,
1609 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001610 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001611 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001612{
1613 struct afs_call *call;
1614 __be32 *bp;
1615
1616 _enter("");
1617
David Howellsd2ddc772017-11-02 15:27:50 +00001618 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001619 if (!call)
1620 return -ENOMEM;
1621
1622 call->key = key;
1623
1624 /* marshall the parameters */
1625 bp = call->request;
1626 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1627
David Howells977e5f82020-04-17 17:31:26 +01001628 call->server = afs_use_server(server, afs_server_trace_give_up_cb);
David Howells0b9bf382019-04-25 14:26:50 +01001629 afs_make_call(ac, call, GFP_NOFS);
1630 return afs_wait_for_call_to_complete(call, ac);
David Howellsd2ddc772017-11-02 15:27:50 +00001631}
1632
1633/*
1634 * Deliver reply data to an FS.GetCapabilities operation.
1635 */
1636static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1637{
1638 u32 count;
1639 int ret;
1640
David Howellsfc276122019-11-21 09:12:17 +00001641 _enter("{%u,%zu}", call->unmarshall, iov_iter_count(call->iter));
David Howellsd2ddc772017-11-02 15:27:50 +00001642
David Howellsd2ddc772017-11-02 15:27:50 +00001643 switch (call->unmarshall) {
1644 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01001645 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00001646 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001647 fallthrough;
David Howellsd2ddc772017-11-02 15:27:50 +00001648
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001649 /* Extract the capabilities word count */
David Howellsd2ddc772017-11-02 15:27:50 +00001650 case 1:
David Howells12bdcf32018-10-20 00:57:56 +01001651 ret = afs_extract_data(call, true);
David Howellsd2ddc772017-11-02 15:27:50 +00001652 if (ret < 0)
1653 return ret;
1654
1655 count = ntohl(call->tmp);
David Howellsd2ddc772017-11-02 15:27:50 +00001656 call->count = count;
1657 call->count2 = count;
David Howellsb537a3c22021-09-10 00:01:52 +01001658 if (count == 0) {
1659 call->unmarshall = 4;
1660 call->tmp = 0;
1661 break;
1662 }
1663
1664 /* Extract the first word of the capabilities to call->tmp */
1665 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00001666 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001667 fallthrough;
David Howellsd2ddc772017-11-02 15:27:50 +00001668
David Howellsd2ddc772017-11-02 15:27:50 +00001669 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001670 ret = afs_extract_data(call, false);
David Howellsd2ddc772017-11-02 15:27:50 +00001671 if (ret < 0)
1672 return ret;
1673
David Howellsb537a3c22021-09-10 00:01:52 +01001674 afs_extract_discard(call, (count - 1) * sizeof(__be32));
1675 call->unmarshall++;
1676 fallthrough;
1677
1678 /* Extract remaining capabilities words */
1679 case 3:
1680 ret = afs_extract_data(call, false);
1681 if (ret < 0)
1682 return ret;
David Howellsd2ddc772017-11-02 15:27:50 +00001683
David Howellsd2ddc772017-11-02 15:27:50 +00001684 call->unmarshall++;
1685 break;
1686 }
1687
1688 _leave(" = 0 [done]");
1689 return 0;
1690}
1691
1692/*
1693 * FS.GetCapabilities operation type
1694 */
1695static const struct afs_call_type afs_RXFSGetCapabilities = {
1696 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001697 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001698 .deliver = afs_deliver_fs_get_capabilities,
David Howells3bf0fb62018-10-20 00:57:59 +01001699 .done = afs_fileserver_probe_result,
David Howellsffba7182019-05-09 22:22:50 +01001700 .destructor = afs_flat_call_destructor,
David Howellsd2ddc772017-11-02 15:27:50 +00001701};
1702
1703/*
David Howellsf6cbb362020-04-24 15:10:00 +01001704 * Probe a fileserver for the capabilities that it supports. This RPC can
1705 * reply with up to 196 words. The operation is asynchronous and if we managed
1706 * to allocate a call, true is returned the result is delivered through the
1707 * ->done() - otherwise we return false to indicate we didn't even try.
David Howellsd2ddc772017-11-02 15:27:50 +00001708 */
David Howellsf6cbb362020-04-24 15:10:00 +01001709bool afs_fs_get_capabilities(struct afs_net *net, struct afs_server *server,
1710 struct afs_addr_cursor *ac, struct key *key)
David Howellsd2ddc772017-11-02 15:27:50 +00001711{
1712 struct afs_call *call;
1713 __be32 *bp;
1714
1715 _enter("");
1716
1717 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1718 if (!call)
David Howellsf6cbb362020-04-24 15:10:00 +01001719 return false;
David Howellsd2ddc772017-11-02 15:27:50 +00001720
1721 call->key = key;
David Howells977e5f82020-04-17 17:31:26 +01001722 call->server = afs_use_server(server, afs_server_trace_get_caps);
David Howells30062bd2018-10-20 00:57:58 +01001723 call->upgrade = true;
David Howells0b9bf382019-04-25 14:26:50 +01001724 call->async = true;
David Howells94f699c2019-05-16 13:21:59 +01001725 call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
David Howellsd2ddc772017-11-02 15:27:50 +00001726
1727 /* marshall the parameters */
1728 bp = call->request;
1729 *bp++ = htonl(FSGETCAPABILITIES);
1730
David Howells025db802017-11-02 15:27:51 +00001731 trace_afs_make_fs_call(call, NULL);
David Howells0b9bf382019-04-25 14:26:50 +01001732 afs_make_call(ac, call, GFP_NOFS);
David Howellsf6cbb362020-04-24 15:10:00 +01001733 afs_put_call(call);
1734 return true;
David Howellse8d6c552007-07-15 23:40:12 -07001735}
David Howells5cf9dd52018-04-09 21:12:31 +01001736
1737/*
David Howells5cf9dd52018-04-09 21:12:31 +01001738 * Deliver reply data to an FS.InlineBulkStatus call
1739 */
1740static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
1741{
David Howellse49c7b22020-04-10 20:51:51 +01001742 struct afs_operation *op = call->op;
David Howells87182752019-05-09 16:17:05 +01001743 struct afs_status_cb *scb;
David Howells5cf9dd52018-04-09 21:12:31 +01001744 const __be32 *bp;
1745 u32 tmp;
1746 int ret;
1747
1748 _enter("{%u}", call->unmarshall);
1749
1750 switch (call->unmarshall) {
1751 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01001752 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01001753 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001754 fallthrough;
David Howells5cf9dd52018-04-09 21:12:31 +01001755
1756 /* Extract the file status count and array in two steps */
1757 case 1:
1758 _debug("extract status count");
David Howells12bdcf32018-10-20 00:57:56 +01001759 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001760 if (ret < 0)
1761 return ret;
1762
1763 tmp = ntohl(call->tmp);
David Howellse49c7b22020-04-10 20:51:51 +01001764 _debug("status count: %u/%u", tmp, op->nr_files);
1765 if (tmp != op->nr_files)
David Howells7126ead2020-04-08 16:49:08 +01001766 return afs_protocol_error(call, afs_eproto_ibulkst_count);
David Howells5cf9dd52018-04-09 21:12:31 +01001767
1768 call->count = 0;
1769 call->unmarshall++;
1770 more_counts:
David Howells12bdcf32018-10-20 00:57:56 +01001771 afs_extract_to_buf(call, 21 * sizeof(__be32));
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001772 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001773
David Howells5cf9dd52018-04-09 21:12:31 +01001774 case 2:
1775 _debug("extract status array %u", call->count);
David Howells12bdcf32018-10-20 00:57:56 +01001776 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001777 if (ret < 0)
1778 return ret;
1779
David Howellse49c7b22020-04-10 20:51:51 +01001780 switch (call->count) {
1781 case 0:
1782 scb = &op->file[0].scb;
1783 break;
1784 case 1:
1785 scb = &op->file[1].scb;
1786 break;
1787 default:
1788 scb = &op->more_files[call->count - 2].scb;
1789 break;
1790 }
1791
David Howells5cf9dd52018-04-09 21:12:31 +01001792 bp = call->buffer;
David Howells38355ee2020-04-08 16:13:20 +01001793 xdr_decode_AFSFetchStatus(&bp, call, scb);
David Howellse49c7b22020-04-10 20:51:51 +01001794
David Howells5cf9dd52018-04-09 21:12:31 +01001795 call->count++;
David Howellse49c7b22020-04-10 20:51:51 +01001796 if (call->count < op->nr_files)
David Howells5cf9dd52018-04-09 21:12:31 +01001797 goto more_counts;
1798
1799 call->count = 0;
1800 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001801 afs_extract_to_tmp(call);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001802 fallthrough;
David Howells5cf9dd52018-04-09 21:12:31 +01001803
1804 /* Extract the callback count and array in two steps */
1805 case 3:
1806 _debug("extract CB count");
David Howells12bdcf32018-10-20 00:57:56 +01001807 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001808 if (ret < 0)
1809 return ret;
1810
1811 tmp = ntohl(call->tmp);
1812 _debug("CB count: %u", tmp);
David Howellse49c7b22020-04-10 20:51:51 +01001813 if (tmp != op->nr_files)
David Howells7126ead2020-04-08 16:49:08 +01001814 return afs_protocol_error(call, afs_eproto_ibulkst_cb_count);
David Howells5cf9dd52018-04-09 21:12:31 +01001815 call->count = 0;
1816 call->unmarshall++;
1817 more_cbs:
David Howells12bdcf32018-10-20 00:57:56 +01001818 afs_extract_to_buf(call, 3 * sizeof(__be32));
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001819 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001820
David Howells5cf9dd52018-04-09 21:12:31 +01001821 case 4:
1822 _debug("extract CB array");
David Howells12bdcf32018-10-20 00:57:56 +01001823 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001824 if (ret < 0)
1825 return ret;
1826
1827 _debug("unmarshall CB array");
David Howellse49c7b22020-04-10 20:51:51 +01001828 switch (call->count) {
1829 case 0:
1830 scb = &op->file[0].scb;
1831 break;
1832 case 1:
1833 scb = &op->file[1].scb;
1834 break;
1835 default:
1836 scb = &op->more_files[call->count - 2].scb;
1837 break;
1838 }
1839
David Howells5cf9dd52018-04-09 21:12:31 +01001840 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +01001841 xdr_decode_AFSCallBack(&bp, call, scb);
David Howells5cf9dd52018-04-09 21:12:31 +01001842 call->count++;
David Howellse49c7b22020-04-10 20:51:51 +01001843 if (call->count < op->nr_files)
David Howells5cf9dd52018-04-09 21:12:31 +01001844 goto more_cbs;
1845
David Howells12bdcf32018-10-20 00:57:56 +01001846 afs_extract_to_buf(call, 6 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01001847 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001848 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001849
David Howells5cf9dd52018-04-09 21:12:31 +01001850 case 5:
David Howells12bdcf32018-10-20 00:57:56 +01001851 ret = afs_extract_data(call, false);
David Howells5cf9dd52018-04-09 21:12:31 +01001852 if (ret < 0)
1853 return ret;
1854
1855 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001856 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells5cf9dd52018-04-09 21:12:31 +01001857
David Howells5cf9dd52018-04-09 21:12:31 +01001858 call->unmarshall++;
Gustavo A. R. Silvab2db6c32021-05-25 15:40:22 +01001859 fallthrough;
David Howells5cf9dd52018-04-09 21:12:31 +01001860
1861 case 6:
1862 break;
1863 }
1864
1865 _leave(" = 0 [done]");
1866 return 0;
1867}
1868
David Howellse49c7b22020-04-10 20:51:51 +01001869static void afs_done_fs_inline_bulk_status(struct afs_call *call)
1870{
1871 if (call->error == -ECONNABORTED &&
David Howells20325962020-04-30 01:03:49 +01001872 call->abort_code == RX_INVALID_OPERATION) {
David Howellse49c7b22020-04-10 20:51:51 +01001873 set_bit(AFS_SERVER_FL_NO_IBULK, &call->server->flags);
David Howells20325962020-04-30 01:03:49 +01001874 if (call->op)
1875 set_bit(AFS_VOLUME_MAYBE_NO_IBULK, &call->op->volume->flags);
1876 }
David Howellse49c7b22020-04-10 20:51:51 +01001877}
1878
David Howells5cf9dd52018-04-09 21:12:31 +01001879/*
1880 * FS.InlineBulkStatus operation type
1881 */
1882static const struct afs_call_type afs_RXFSInlineBulkStatus = {
1883 .name = "FS.InlineBulkStatus",
1884 .op = afs_FS_InlineBulkStatus,
1885 .deliver = afs_deliver_fs_inline_bulk_status,
David Howellse49c7b22020-04-10 20:51:51 +01001886 .done = afs_done_fs_inline_bulk_status,
David Howells5cf9dd52018-04-09 21:12:31 +01001887 .destructor = afs_flat_call_destructor,
1888};
1889
1890/*
1891 * Fetch the status information for up to 50 files
1892 */
David Howellse49c7b22020-04-10 20:51:51 +01001893void afs_fs_inline_bulk_status(struct afs_operation *op)
David Howells5cf9dd52018-04-09 21:12:31 +01001894{
David Howellse49c7b22020-04-10 20:51:51 +01001895 struct afs_vnode_param *dvp = &op->file[0];
1896 struct afs_vnode_param *vp = &op->file[1];
David Howells5cf9dd52018-04-09 21:12:31 +01001897 struct afs_call *call;
1898 __be32 *bp;
1899 int i;
1900
David Howells20325962020-04-30 01:03:49 +01001901 if (test_bit(AFS_SERVER_FL_NO_IBULK, &op->server->flags)) {
David Howellse49c7b22020-04-10 20:51:51 +01001902 op->error = -ENOTSUPP;
1903 return;
David Howells5cf9dd52018-04-09 21:12:31 +01001904 }
1905
David Howellse49c7b22020-04-10 20:51:51 +01001906 _enter(",%x,{%llx:%llu},%u",
1907 key_serial(op->key), vp->fid.vid, vp->fid.vnode, op->nr_files);
1908
1909 call = afs_alloc_flat_call(op->net, &afs_RXFSInlineBulkStatus,
1910 (2 + op->nr_files * 3) * 4,
1911 21 * 4);
1912 if (!call)
1913 return afs_op_nomem(op);
David Howells5cf9dd52018-04-09 21:12:31 +01001914
1915 /* marshall the parameters */
1916 bp = call->request;
1917 *bp++ = htonl(FSINLINEBULKSTATUS);
David Howellse49c7b22020-04-10 20:51:51 +01001918 *bp++ = htonl(op->nr_files);
1919 *bp++ = htonl(dvp->fid.vid);
1920 *bp++ = htonl(dvp->fid.vnode);
1921 *bp++ = htonl(dvp->fid.unique);
1922 *bp++ = htonl(vp->fid.vid);
1923 *bp++ = htonl(vp->fid.vnode);
1924 *bp++ = htonl(vp->fid.unique);
1925 for (i = 0; i < op->nr_files - 2; i++) {
1926 *bp++ = htonl(op->more_files[i].fid.vid);
1927 *bp++ = htonl(op->more_files[i].fid.vnode);
1928 *bp++ = htonl(op->more_files[i].fid.unique);
David Howells5cf9dd52018-04-09 21:12:31 +01001929 }
1930
David Howellse49c7b22020-04-10 20:51:51 +01001931 trace_afs_make_fs_call(call, &vp->fid);
1932 afs_make_op_call(op, call, GFP_NOFS);
David Howells5cf9dd52018-04-09 21:12:31 +01001933}
David Howells260f0822019-04-25 14:26:52 +01001934
1935/*
1936 * deliver reply data to an FS.FetchACL
1937 */
1938static int afs_deliver_fs_fetch_acl(struct afs_call *call)
1939{
David Howellse49c7b22020-04-10 20:51:51 +01001940 struct afs_operation *op = call->op;
1941 struct afs_vnode_param *vp = &op->file[0];
David Howells260f0822019-04-25 14:26:52 +01001942 struct afs_acl *acl;
1943 const __be32 *bp;
1944 unsigned int size;
1945 int ret;
1946
1947 _enter("{%u}", call->unmarshall);
1948
1949 switch (call->unmarshall) {
1950 case 0:
1951 afs_extract_to_tmp(call);
1952 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001953 fallthrough;
David Howells260f0822019-04-25 14:26:52 +01001954
1955 /* extract the returned data length */
1956 case 1:
1957 ret = afs_extract_data(call, true);
1958 if (ret < 0)
1959 return ret;
1960
1961 size = call->count2 = ntohl(call->tmp);
1962 size = round_up(size, 4);
1963
1964 acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
1965 if (!acl)
1966 return -ENOMEM;
David Howellse49c7b22020-04-10 20:51:51 +01001967 op->acl = acl;
David Howells260f0822019-04-25 14:26:52 +01001968 acl->size = call->count2;
1969 afs_extract_begin(call, acl->data, size);
1970 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001971 fallthrough;
David Howells260f0822019-04-25 14:26:52 +01001972
1973 /* extract the returned data */
1974 case 2:
1975 ret = afs_extract_data(call, true);
1976 if (ret < 0)
1977 return ret;
1978
1979 afs_extract_to_buf(call, (21 + 6) * 4);
1980 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001981 fallthrough;
David Howells260f0822019-04-25 14:26:52 +01001982
1983 /* extract the metadata */
1984 case 3:
1985 ret = afs_extract_data(call, false);
1986 if (ret < 0)
1987 return ret;
1988
1989 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001990 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
1991 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260f0822019-04-25 14:26:52 +01001992
1993 call->unmarshall++;
Gustavo A. R. Silvab2db6c32021-05-25 15:40:22 +01001994 fallthrough;
David Howells260f0822019-04-25 14:26:52 +01001995
1996 case 4:
1997 break;
1998 }
1999
2000 _leave(" = 0 [done]");
2001 return 0;
2002}
2003
David Howells260f0822019-04-25 14:26:52 +01002004/*
2005 * FS.FetchACL operation type
2006 */
2007static const struct afs_call_type afs_RXFSFetchACL = {
2008 .name = "FS.FetchACL",
2009 .op = afs_FS_FetchACL,
2010 .deliver = afs_deliver_fs_fetch_acl,
David Howells260f0822019-04-25 14:26:52 +01002011};
2012
2013/*
2014 * Fetch the ACL for a file.
2015 */
David Howellse49c7b22020-04-10 20:51:51 +01002016void afs_fs_fetch_acl(struct afs_operation *op)
David Howells260f0822019-04-25 14:26:52 +01002017{
David Howellse49c7b22020-04-10 20:51:51 +01002018 struct afs_vnode_param *vp = &op->file[0];
David Howells260f0822019-04-25 14:26:52 +01002019 struct afs_call *call;
David Howells260f0822019-04-25 14:26:52 +01002020 __be32 *bp;
2021
2022 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01002023 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells260f0822019-04-25 14:26:52 +01002024
David Howellse49c7b22020-04-10 20:51:51 +01002025 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchACL, 16, (21 + 6) * 4);
2026 if (!call)
2027 return afs_op_nomem(op);
David Howells260f0822019-04-25 14:26:52 +01002028
2029 /* marshall the parameters */
2030 bp = call->request;
2031 bp[0] = htonl(FSFETCHACL);
David Howellse49c7b22020-04-10 20:51:51 +01002032 bp[1] = htonl(vp->fid.vid);
2033 bp[2] = htonl(vp->fid.vnode);
2034 bp[3] = htonl(vp->fid.unique);
David Howells260f0822019-04-25 14:26:52 +01002035
David Howellse49c7b22020-04-10 20:51:51 +01002036 trace_afs_make_fs_call(call, &vp->fid);
2037 afs_make_op_call(op, call, GFP_KERNEL);
David Howellsffba7182019-05-09 22:22:50 +01002038}
2039
2040/*
Joe Gorseb10494a2019-04-25 14:26:52 +01002041 * FS.StoreACL operation type
2042 */
2043static const struct afs_call_type afs_RXFSStoreACL = {
2044 .name = "FS.StoreACL",
2045 .op = afs_FS_StoreACL,
David Howellsffba7182019-05-09 22:22:50 +01002046 .deliver = afs_deliver_fs_file_status_and_vol,
Joe Gorseb10494a2019-04-25 14:26:52 +01002047 .destructor = afs_flat_call_destructor,
2048};
2049
2050/*
2051 * Fetch the ACL for a file.
2052 */
David Howellse49c7b22020-04-10 20:51:51 +01002053void afs_fs_store_acl(struct afs_operation *op)
Joe Gorseb10494a2019-04-25 14:26:52 +01002054{
David Howellse49c7b22020-04-10 20:51:51 +01002055 struct afs_vnode_param *vp = &op->file[0];
Joe Gorseb10494a2019-04-25 14:26:52 +01002056 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01002057 const struct afs_acl *acl = op->acl;
Joe Gorseb10494a2019-04-25 14:26:52 +01002058 size_t size;
2059 __be32 *bp;
2060
2061 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01002062 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
Joe Gorseb10494a2019-04-25 14:26:52 +01002063
2064 size = round_up(acl->size, 4);
David Howellse49c7b22020-04-10 20:51:51 +01002065 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreACL,
Joe Gorseb10494a2019-04-25 14:26:52 +01002066 5 * 4 + size, (21 + 6) * 4);
David Howellse49c7b22020-04-10 20:51:51 +01002067 if (!call)
2068 return afs_op_nomem(op);
Joe Gorseb10494a2019-04-25 14:26:52 +01002069
2070 /* marshall the parameters */
2071 bp = call->request;
2072 bp[0] = htonl(FSSTOREACL);
David Howellse49c7b22020-04-10 20:51:51 +01002073 bp[1] = htonl(vp->fid.vid);
2074 bp[2] = htonl(vp->fid.vnode);
2075 bp[3] = htonl(vp->fid.unique);
Joe Gorseb10494a2019-04-25 14:26:52 +01002076 bp[4] = htonl(acl->size);
2077 memcpy(&bp[5], acl->data, acl->size);
2078 if (acl->size != size)
2079 memset((void *)&bp[5] + acl->size, 0, size - acl->size);
2080
David Howellse49c7b22020-04-10 20:51:51 +01002081 trace_afs_make_fs_call(call, &vp->fid);
2082 afs_make_op_call(op, call, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083}