blob: 897b37301851b8d0bcded974a18b7ab5bb258a50 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070014#include "afs_fs.h"
David Howellsdd9fbcb2018-04-06 14:17:24 +010015#include "xdr_fs.h"
David Howellsc435ee32017-11-02 15:27:49 +000016
David Howells6db3ac32017-03-16 16:27:44 +000017/*
David Howells260a9802007-04-26 15:59:35 -070018 * decode an AFSFid block
19 */
20static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
21{
22 const __be32 *bp = *_bp;
23
24 fid->vid = ntohl(*bp++);
25 fid->vnode = ntohl(*bp++);
26 fid->unique = ntohl(*bp++);
27 *_bp = bp;
28}
29
30/*
David Howells888b3382018-04-06 14:17:24 +010031 * Dump a bad file status record.
32 */
33static void xdr_dump_bad(const __be32 *bp)
34{
35 __be32 x[4];
36 int i;
37
38 pr_notice("AFS XDR: Bad status record\n");
39 for (i = 0; i < 5 * 4 * 4; i += 16) {
40 memcpy(x, bp, 16);
41 bp += 4;
42 pr_notice("%03x: %08x %08x %08x %08x\n",
43 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
44 }
45
46 memcpy(x, bp, 4);
47 pr_notice("0x50: %08x\n", ntohl(x[0]));
48}
49
50/*
David Howellsdd9fbcb2018-04-06 14:17:24 +010051 * decode an AFSFetchStatus block
52 */
David Howells38355ee2020-04-08 16:13:20 +010053static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
54 struct afs_call *call,
55 struct afs_status_cb *scb)
David Howellsdd9fbcb2018-04-06 14:17:24 +010056{
57 const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
David Howellsa58823a2019-05-09 15:16:10 +010058 struct afs_file_status *status = &scb->status;
David Howells684b0f62018-05-10 21:51:47 +010059 bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
David Howellsdd9fbcb2018-04-06 14:17:24 +010060 u64 data_version, size;
61 u32 type, abort_code;
David Howellsdd9fbcb2018-04-06 14:17:24 +010062
David Howells684b0f62018-05-10 21:51:47 +010063 abort_code = ntohl(xdr->abort_code);
64
David Howellsdd9fbcb2018-04-06 14:17:24 +010065 if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
David Howells684b0f62018-05-10 21:51:47 +010066 if (xdr->if_version == htonl(0) &&
67 abort_code != 0 &&
68 inline_error) {
69 /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
70 * whereby it doesn't set the interface version in the error
71 * case.
72 */
73 status->abort_code = abort_code;
David Howellsa38a7552019-05-14 12:29:11 +010074 scb->have_error = true;
David Howells38355ee2020-04-08 16:13:20 +010075 goto advance;
David Howells684b0f62018-05-10 21:51:47 +010076 }
77
David Howellsdd9fbcb2018-04-06 14:17:24 +010078 pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
79 goto bad;
80 }
81
David Howells684b0f62018-05-10 21:51:47 +010082 if (abort_code != 0 && inline_error) {
83 status->abort_code = abort_code;
David Howells3e0d9892020-04-08 17:32:10 +010084 scb->have_error = true;
David Howells38355ee2020-04-08 16:13:20 +010085 goto advance;
David Howells684b0f62018-05-10 21:51:47 +010086 }
87
David Howellsdd9fbcb2018-04-06 14:17:24 +010088 type = ntohl(xdr->type);
David Howellsdd9fbcb2018-04-06 14:17:24 +010089 switch (type) {
90 case AFS_FTYPE_FILE:
91 case AFS_FTYPE_DIR:
92 case AFS_FTYPE_SYMLINK:
David Howellsdd9fbcb2018-04-06 14:17:24 +010093 status->type = type;
94 break;
David Howellsdd9fbcb2018-04-06 14:17:24 +010095 default:
96 goto bad;
97 }
98
David Howellsa58823a2019-05-09 15:16:10 +010099 status->nlink = ntohl(xdr->nlink);
100 status->author = ntohl(xdr->author);
101 status->owner = ntohl(xdr->owner);
102 status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */
103 status->anon_access = ntohl(xdr->anon_access);
104 status->mode = ntohl(xdr->mode) & S_IALLUGO;
105 status->group = ntohl(xdr->group);
106 status->lock_count = ntohl(xdr->lock_count);
David Howellsdd9fbcb2018-04-06 14:17:24 +0100107
David Howellsd4936802018-10-20 00:57:58 +0100108 status->mtime_client.tv_sec = ntohl(xdr->mtime_client);
109 status->mtime_client.tv_nsec = 0;
110 status->mtime_server.tv_sec = ntohl(xdr->mtime_server);
111 status->mtime_server.tv_nsec = 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100112
113 size = (u64)ntohl(xdr->size_lo);
114 size |= (u64)ntohl(xdr->size_hi) << 32;
David Howells63a46812018-04-06 14:17:25 +0100115 status->size = size;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100116
117 data_version = (u64)ntohl(xdr->data_version_lo);
118 data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
David Howellsa58823a2019-05-09 15:16:10 +0100119 status->data_version = data_version;
David Howellsa38a7552019-05-14 12:29:11 +0100120 scb->have_status = true;
David Howellsc72057b2020-04-08 16:13:20 +0100121advance:
David Howellsdd9fbcb2018-04-06 14:17:24 +0100122 *_bp = (const void *)*_bp + sizeof(*xdr);
David Howells38355ee2020-04-08 16:13:20 +0100123 return;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100124
125bad:
126 xdr_dump_bad(*_bp);
David Howells7126ead2020-04-08 16:49:08 +0100127 afs_protocol_error(call, afs_eproto_bad_status);
David Howellsc72057b2020-04-08 16:13:20 +0100128 goto advance;
David Howellsc875c762018-05-23 11:32:06 +0100129}
130
David Howells78107052019-05-09 17:56:53 +0100131static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
132{
133 return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry;
134}
135
David Howellsa58823a2019-05-09 15:16:10 +0100136static void xdr_decode_AFSCallBack(const __be32 **_bp,
137 struct afs_call *call,
138 struct afs_status_cb *scb)
David Howells78107052019-05-09 17:56:53 +0100139{
David Howellsa58823a2019-05-09 15:16:10 +0100140 struct afs_callback *cb = &scb->callback;
David Howells78107052019-05-09 17:56:53 +0100141 const __be32 *bp = *_bp;
142
David Howells7c712452019-05-14 15:35:44 +0100143 bp++; /* version */
David Howells78107052019-05-09 17:56:53 +0100144 cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++));
David Howells7c712452019-05-14 15:35:44 +0100145 bp++; /* type */
David Howellsa58823a2019-05-09 15:16:10 +0100146 scb->have_cb = true;
David Howells78107052019-05-09 17:56:53 +0100147 *_bp = bp;
148}
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150/*
David Howells08e0e7c2007-04-26 15:55:03 -0700151 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 */
David Howells08e0e7c2007-04-26 15:55:03 -0700153static void xdr_decode_AFSVolSync(const __be32 **_bp,
154 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
David Howells08e0e7c2007-04-26 15:55:03 -0700156 const __be32 *bp = *_bp;
David Howells30062bd2018-10-20 00:57:58 +0100157 u32 creation;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
David Howells30062bd2018-10-20 00:57:58 +0100159 creation = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -0700160 bp++; /* spare2 */
161 bp++; /* spare3 */
162 bp++; /* spare4 */
163 bp++; /* spare5 */
164 bp++; /* spare6 */
165 *_bp = bp;
David Howells30062bd2018-10-20 00:57:58 +0100166
167 if (volsync)
168 volsync->creation = creation;
David Howellsec268152007-04-26 15:49:28 -0700169}
David Howells08e0e7c2007-04-26 15:55:03 -0700170
171/*
David Howells31143d52007-05-09 02:33:46 -0700172 * encode the requested attributes into an AFSStoreStatus block
173 */
174static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
175{
176 __be32 *bp = *_bp;
177 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
178
179 mask = 0;
180 if (attr->ia_valid & ATTR_MTIME) {
181 mask |= AFS_SET_MTIME;
182 mtime = attr->ia_mtime.tv_sec;
183 }
184
185 if (attr->ia_valid & ATTR_UID) {
186 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800187 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700188 }
189
190 if (attr->ia_valid & ATTR_GID) {
191 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800192 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700193 }
194
195 if (attr->ia_valid & ATTR_MODE) {
196 mask |= AFS_SET_MODE;
197 mode = attr->ia_mode & S_IALLUGO;
198 }
199
200 *bp++ = htonl(mask);
201 *bp++ = htonl(mtime);
202 *bp++ = htonl(owner);
203 *bp++ = htonl(group);
204 *bp++ = htonl(mode);
205 *bp++ = 0; /* segment size */
206 *_bp = bp;
207}
208
209/*
David Howells45222b92007-05-10 22:22:20 -0700210 * decode an AFSFetchVolumeStatus block
211 */
212static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
213 struct afs_volume_status *vs)
214{
215 const __be32 *bp = *_bp;
216
217 vs->vid = ntohl(*bp++);
218 vs->parent_id = ntohl(*bp++);
219 vs->online = ntohl(*bp++);
220 vs->in_service = ntohl(*bp++);
221 vs->blessed = ntohl(*bp++);
222 vs->needs_salvage = ntohl(*bp++);
223 vs->type = ntohl(*bp++);
224 vs->min_quota = ntohl(*bp++);
225 vs->max_quota = ntohl(*bp++);
226 vs->blocks_in_use = ntohl(*bp++);
227 vs->part_blocks_avail = ntohl(*bp++);
228 vs->part_max_blocks = ntohl(*bp++);
David Howells30062bd2018-10-20 00:57:58 +0100229 vs->vol_copy_date = 0;
230 vs->vol_backup_date = 0;
David Howells45222b92007-05-10 22:22:20 -0700231 *_bp = bp;
232}
233
234/*
David Howells08e0e7c2007-04-26 15:55:03 -0700235 * deliver reply data to an FS.FetchStatus
236 */
David Howellse49c7b22020-04-10 20:51:51 +0100237static int afs_deliver_fs_fetch_status(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700238{
David Howellse49c7b22020-04-10 20:51:51 +0100239 struct afs_operation *op = call->op;
240 struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
David Howells08e0e7c2007-04-26 15:55:03 -0700241 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100242 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700243
David Howellsd0016482016-08-30 20:42:14 +0100244 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100245 if (ret < 0)
246 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700247
248 /* unmarshall the reply once we've received all of it */
249 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100250 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
251 xdr_decode_AFSCallBack(&bp, call, &vp->scb);
252 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells08e0e7c2007-04-26 15:55:03 -0700253
254 _leave(" = 0 [done]");
255 return 0;
256}
257
258/*
259 * FS.FetchStatus operation type
260 */
David Howellse49c7b22020-04-10 20:51:51 +0100261static const struct afs_call_type afs_RXFSFetchStatus = {
262 .name = "FS.FetchStatus",
David Howells025db802017-11-02 15:27:51 +0000263 .op = afs_FS_FetchStatus,
David Howellse49c7b22020-04-10 20:51:51 +0100264 .deliver = afs_deliver_fs_fetch_status,
David Howells08e0e7c2007-04-26 15:55:03 -0700265 .destructor = afs_flat_call_destructor,
266};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268/*
269 * fetch the status information for a file
270 */
David Howellse49c7b22020-04-10 20:51:51 +0100271void afs_fs_fetch_status(struct afs_operation *op)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272{
David Howellse49c7b22020-04-10 20:51:51 +0100273 struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
David Howells08e0e7c2007-04-26 15:55:03 -0700274 struct afs_call *call;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 __be32 *bp;
276
David Howells3b6492d2018-10-20 00:57:57 +0100277 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +0100278 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
David Howellse49c7b22020-04-10 20:51:51 +0100280 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100281 16, (21 + 3 + 6) * 4);
David Howellse49c7b22020-04-10 20:51:51 +0100282 if (!call)
283 return afs_op_nomem(op);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
285 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700286 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 bp[0] = htonl(FSFETCHSTATUS);
David Howellse49c7b22020-04-10 20:51:51 +0100288 bp[1] = htonl(vp->fid.vid);
289 bp[2] = htonl(vp->fid.vnode);
290 bp[3] = htonl(vp->fid.unique);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
David Howellse49c7b22020-04-10 20:51:51 +0100292 trace_afs_make_fs_call(call, &vp->fid);
293 afs_make_op_call(op, call, GFP_NOFS);
David Howellsec268152007-04-26 15:49:28 -0700294}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296/*
David Howells08e0e7c2007-04-26 15:55:03 -0700297 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 */
David Howellsd0016482016-08-30 20:42:14 +0100299static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300{
David Howellse49c7b22020-04-10 20:51:51 +0100301 struct afs_operation *op = call->op;
302 struct afs_vnode_param *vp = &op->file[0];
303 struct afs_read *req = op->fetch.req;
David Howells08e0e7c2007-04-26 15:55:03 -0700304 const __be32 *bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700306
David Howellsf105da12020-02-06 14:22:28 +0000307 _enter("{%u,%zu,%zu/%llu}",
308 call->unmarshall, call->iov_len, iov_iter_count(call->iter),
309 req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700310
311 switch (call->unmarshall) {
312 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000313 req->actual_len = 0;
David Howells08e0e7c2007-04-26 15:55:03 -0700314 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +0100315 if (call->operation_ID == FSFETCHDATA64) {
316 afs_extract_to_tmp64(call);
317 } else {
318 call->tmp_u = htonl(0);
319 afs_extract_to_tmp(call);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700320 }
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500321 fallthrough;
David Howells08e0e7c2007-04-26 15:55:03 -0700322
David Howellsc4508462020-02-06 14:22:28 +0000323 /* Extract the returned data length into
324 * ->actual_len. This may indicate more or less data than was
325 * requested will be returned.
326 */
David Howells12bdcf32018-10-20 00:57:56 +0100327 case 1:
David Howells08e0e7c2007-04-26 15:55:03 -0700328 _debug("extract data length");
David Howells12bdcf32018-10-20 00:57:56 +0100329 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +0100330 if (ret < 0)
331 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700332
David Howells12bdcf32018-10-20 00:57:56 +0100333 req->actual_len = be64_to_cpu(call->tmp64);
David Howells196ee9c2017-01-05 10:38:34 +0000334 _debug("DATA length: %llu", req->actual_len);
David Howellsc4508462020-02-06 14:22:28 +0000335
336 if (req->actual_len == 0)
David Howells196ee9c2017-01-05 10:38:34 +0000337 goto no_more_data;
David Howells12bdcf32018-10-20 00:57:56 +0100338
David Howellsc4508462020-02-06 14:22:28 +0000339 call->iter = req->iter;
340 call->iov_len = min(req->actual_len, req->len);
David Howells08e0e7c2007-04-26 15:55:03 -0700341 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500342 fallthrough;
David Howells196ee9c2017-01-05 10:38:34 +0000343
Gustavo A. R. Silva29881602019-05-19 18:43:53 -0500344 /* extract the returned data */
David Howells12bdcf32018-10-20 00:57:56 +0100345 case 2:
346 _debug("extract data %zu/%llu",
David Howellsc4508462020-02-06 14:22:28 +0000347 iov_iter_count(call->iter), req->actual_len);
David Howells196ee9c2017-01-05 10:38:34 +0000348
David Howells12bdcf32018-10-20 00:57:56 +0100349 ret = afs_extract_data(call, true);
David Howells196ee9c2017-01-05 10:38:34 +0000350 if (ret < 0)
351 return ret;
David Howells12bdcf32018-10-20 00:57:56 +0100352
David Howellsc4508462020-02-06 14:22:28 +0000353 call->iter = &call->def_iter;
David Howells12bdcf32018-10-20 00:57:56 +0100354 if (req->actual_len <= req->len)
355 goto no_more_data;
David Howells6db3ac32017-03-16 16:27:44 +0000356
357 /* Discard any excess data the server gave us */
David Howells23a28912019-08-20 09:22:38 +0100358 afs_extract_discard(call, req->actual_len - req->len);
David Howells12bdcf32018-10-20 00:57:56 +0100359 call->unmarshall = 3;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500360 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -0500361
David Howells12bdcf32018-10-20 00:57:56 +0100362 case 3:
363 _debug("extract discard %zu/%llu",
David Howellsfc276122019-11-21 09:12:17 +0000364 iov_iter_count(call->iter), req->actual_len - req->len);
David Howells6db3ac32017-03-16 16:27:44 +0000365
David Howells12bdcf32018-10-20 00:57:56 +0100366 ret = afs_extract_data(call, true);
David Howells6db3ac32017-03-16 16:27:44 +0000367 if (ret < 0)
368 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700369
David Howells196ee9c2017-01-05 10:38:34 +0000370 no_more_data:
David Howells12bdcf32018-10-20 00:57:56 +0100371 call->unmarshall = 4;
372 afs_extract_to_buf(call, (21 + 3 + 6) * 4);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500373 fallthrough;
David Howells08e0e7c2007-04-26 15:55:03 -0700374
Gustavo A. R. Silva29881602019-05-19 18:43:53 -0500375 /* extract the metadata */
David Howells12bdcf32018-10-20 00:57:56 +0100376 case 4:
377 ret = afs_extract_data(call, false);
David Howells372ee162016-08-03 14:11:40 +0100378 if (ret < 0)
379 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700380
381 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100382 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
383 xdr_decode_AFSCallBack(&bp, call, &vp->scb);
384 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells08e0e7c2007-04-26 15:55:03 -0700385
David Howellse49c7b22020-04-10 20:51:51 +0100386 req->data_version = vp->scb.status.data_version;
387 req->file_size = vp->scb.status.size;
David Howellsa58823a2019-05-09 15:16:10 +0100388
David Howells08e0e7c2007-04-26 15:55:03 -0700389 call->unmarshall++;
390
David Howells12bdcf32018-10-20 00:57:56 +0100391 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700392 break;
393 }
394
David Howellsc4508462020-02-06 14:22:28 +0000395 if (req->done)
396 req->done(req);
David Howells9d1be4f2020-05-17 21:21:05 +0100397
David Howells08e0e7c2007-04-26 15:55:03 -0700398 _leave(" = 0 [done]");
399 return 0;
400}
401
402/*
403 * FS.FetchData operation type
404 */
405static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700406 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000407 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700408 .deliver = afs_deliver_fs_fetch_data,
David Howellse49c7b22020-04-10 20:51:51 +0100409 .destructor = afs_flat_call_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700410};
411
David Howellsb9b1f8d2007-05-10 03:15:21 -0700412static const struct afs_call_type afs_RXFSFetchData64 = {
413 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000414 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700415 .deliver = afs_deliver_fs_fetch_data,
David Howellse49c7b22020-04-10 20:51:51 +0100416 .destructor = afs_flat_call_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700417};
418
419/*
420 * fetch data from a very large file
421 */
David Howellse49c7b22020-04-10 20:51:51 +0100422static void afs_fs_fetch_data64(struct afs_operation *op)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700423{
David Howellse49c7b22020-04-10 20:51:51 +0100424 struct afs_vnode_param *vp = &op->file[0];
425 struct afs_read *req = op->fetch.req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700426 struct afs_call *call;
427 __be32 *bp;
428
429 _enter("");
430
David Howellse49c7b22020-04-10 20:51:51 +0100431 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700432 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100433 return afs_op_nomem(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700434
435 /* marshall the parameters */
436 bp = call->request;
437 bp[0] = htonl(FSFETCHDATA64);
David Howellse49c7b22020-04-10 20:51:51 +0100438 bp[1] = htonl(vp->fid.vid);
439 bp[2] = htonl(vp->fid.vnode);
440 bp[3] = htonl(vp->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000441 bp[4] = htonl(upper_32_bits(req->pos));
442 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700443 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000444 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700445
David Howellse49c7b22020-04-10 20:51:51 +0100446 trace_afs_make_fs_call(call, &vp->fid);
447 afs_make_op_call(op, call, GFP_NOFS);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700448}
449
David Howells08e0e7c2007-04-26 15:55:03 -0700450/*
451 * fetch data from a file
452 */
David Howellse49c7b22020-04-10 20:51:51 +0100453void afs_fs_fetch_data(struct afs_operation *op)
David Howells08e0e7c2007-04-26 15:55:03 -0700454{
David Howellse49c7b22020-04-10 20:51:51 +0100455 struct afs_vnode_param *vp = &op->file[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700456 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +0100457 struct afs_read *req = op->fetch.req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 __be32 *bp;
459
David Howells196ee9c2017-01-05 10:38:34 +0000460 if (upper_32_bits(req->pos) ||
461 upper_32_bits(req->len) ||
462 upper_32_bits(req->pos + req->len))
David Howellse49c7b22020-04-10 20:51:51 +0100463 return afs_fs_fetch_data64(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700464
David Howells08e0e7c2007-04-26 15:55:03 -0700465 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
David Howellse49c7b22020-04-10 20:51:51 +0100467 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700468 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100469 return afs_op_nomem(op);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
David Howellsc4508462020-02-06 14:22:28 +0000471 req->call_debug_id = call->debug_id;
472
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700474 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 bp[0] = htonl(FSFETCHDATA);
David Howellse49c7b22020-04-10 20:51:51 +0100476 bp[1] = htonl(vp->fid.vid);
477 bp[2] = htonl(vp->fid.vnode);
478 bp[3] = htonl(vp->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000479 bp[4] = htonl(lower_32_bits(req->pos));
480 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
David Howellse49c7b22020-04-10 20:51:51 +0100482 trace_afs_make_fs_call(call, &vp->fid);
483 afs_make_op_call(op, call, GFP_NOFS);
David Howellsec268152007-04-26 15:49:28 -0700484}
David Howells260a9802007-04-26 15:59:35 -0700485
486/*
487 * deliver reply data to an FS.CreateFile or an FS.MakeDir
488 */
David Howellsd0016482016-08-30 20:42:14 +0100489static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700490{
David Howellse49c7b22020-04-10 20:51:51 +0100491 struct afs_operation *op = call->op;
492 struct afs_vnode_param *dvp = &op->file[0];
493 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700494 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100495 int ret;
David Howells260a9802007-04-26 15:59:35 -0700496
David Howellsd0016482016-08-30 20:42:14 +0100497 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100498 if (ret < 0)
499 return ret;
David Howells260a9802007-04-26 15:59:35 -0700500
501 /* unmarshall the reply once we've received all of it */
502 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100503 xdr_decode_AFSFid(&bp, &op->file[1].fid);
504 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
505 xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
506 xdr_decode_AFSCallBack(&bp, call, &vp->scb);
507 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700508
509 _leave(" = 0 [done]");
510 return 0;
511}
512
513/*
514 * FS.CreateFile and FS.MakeDir operation type
515 */
David Howells025db802017-11-02 15:27:51 +0000516static const struct afs_call_type afs_RXFSCreateFile = {
517 .name = "FS.CreateFile",
518 .op = afs_FS_CreateFile,
519 .deliver = afs_deliver_fs_create_vnode,
520 .destructor = afs_flat_call_destructor,
521};
522
David Howellse49c7b22020-04-10 20:51:51 +0100523/*
524 * Create a file.
525 */
526void afs_fs_create_file(struct afs_operation *op)
527{
528 const struct qstr *name = &op->dentry->d_name;
529 struct afs_vnode_param *dvp = &op->file[0];
530 struct afs_call *call;
531 size_t namesz, reqsz, padsz;
532 __be32 *bp;
533
534 _enter("");
535
536 namesz = name->len;
537 padsz = (4 - (namesz & 3)) & 3;
538 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
539
540 call = afs_alloc_flat_call(op->net, &afs_RXFSCreateFile,
541 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
542 if (!call)
543 return afs_op_nomem(op);
544
545 /* marshall the parameters */
546 bp = call->request;
547 *bp++ = htonl(FSCREATEFILE);
548 *bp++ = htonl(dvp->fid.vid);
549 *bp++ = htonl(dvp->fid.vnode);
550 *bp++ = htonl(dvp->fid.unique);
551 *bp++ = htonl(namesz);
552 memcpy(bp, name->name, namesz);
553 bp = (void *) bp + namesz;
554 if (padsz > 0) {
555 memset(bp, 0, padsz);
556 bp = (void *) bp + padsz;
557 }
558 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
559 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
560 *bp++ = 0; /* owner */
561 *bp++ = 0; /* group */
562 *bp++ = htonl(op->create.mode & S_IALLUGO); /* unix mode */
563 *bp++ = 0; /* segment size */
564
565 trace_afs_make_fs_call1(call, &dvp->fid, name);
566 afs_make_op_call(op, call, GFP_NOFS);
567}
568
David Howells025db802017-11-02 15:27:51 +0000569static const struct afs_call_type afs_RXFSMakeDir = {
570 .name = "FS.MakeDir",
571 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700572 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700573 .destructor = afs_flat_call_destructor,
574};
575
576/*
David Howellse49c7b22020-04-10 20:51:51 +0100577 * Create a new directory
David Howells260a9802007-04-26 15:59:35 -0700578 */
David Howellse49c7b22020-04-10 20:51:51 +0100579void afs_fs_make_dir(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700580{
David Howellse49c7b22020-04-10 20:51:51 +0100581 const struct qstr *name = &op->dentry->d_name;
582 struct afs_vnode_param *dvp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700583 struct afs_call *call;
584 size_t namesz, reqsz, padsz;
585 __be32 *bp;
586
587 _enter("");
588
David Howellse49c7b22020-04-10 20:51:51 +0100589 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700590 padsz = (4 - (namesz & 3)) & 3;
591 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
592
David Howellse49c7b22020-04-10 20:51:51 +0100593 call = afs_alloc_flat_call(op->net, &afs_RXFSMakeDir,
594 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700595 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100596 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700597
598 /* marshall the parameters */
599 bp = call->request;
David Howellse49c7b22020-04-10 20:51:51 +0100600 *bp++ = htonl(FSMAKEDIR);
601 *bp++ = htonl(dvp->fid.vid);
602 *bp++ = htonl(dvp->fid.vnode);
603 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700604 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100605 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700606 bp = (void *) bp + namesz;
607 if (padsz > 0) {
608 memset(bp, 0, padsz);
609 bp = (void *) bp + padsz;
610 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000611 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
David Howellse49c7b22020-04-10 20:51:51 +0100612 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700613 *bp++ = 0; /* owner */
614 *bp++ = 0; /* group */
David Howellse49c7b22020-04-10 20:51:51 +0100615 *bp++ = htonl(op->create.mode & S_IALLUGO); /* unix mode */
David Howells260a9802007-04-26 15:59:35 -0700616 *bp++ = 0; /* segment size */
617
David Howellse49c7b22020-04-10 20:51:51 +0100618 trace_afs_make_fs_call1(call, &dvp->fid, name);
619 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700620}
621
622/*
David Howellse49c7b22020-04-10 20:51:51 +0100623 * Deliver reply data to any operation that returns status and volume sync.
David Howells260a9802007-04-26 15:59:35 -0700624 */
David Howellse49c7b22020-04-10 20:51:51 +0100625static int afs_deliver_fs_file_status_and_vol(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700626{
David Howellse49c7b22020-04-10 20:51:51 +0100627 struct afs_operation *op = call->op;
628 struct afs_vnode_param *vp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700629 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100630 int ret;
David Howells260a9802007-04-26 15:59:35 -0700631
David Howellsd0016482016-08-30 20:42:14 +0100632 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100633 if (ret < 0)
634 return ret;
David Howells260a9802007-04-26 15:59:35 -0700635
636 /* unmarshall the reply once we've received all of it */
637 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100638 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
639 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700640
641 _leave(" = 0 [done]");
642 return 0;
643}
644
645/*
David Howellse49c7b22020-04-10 20:51:51 +0100646 * FS.RemoveFile operation type
David Howells260a9802007-04-26 15:59:35 -0700647 */
David Howells025db802017-11-02 15:27:51 +0000648static const struct afs_call_type afs_RXFSRemoveFile = {
649 .name = "FS.RemoveFile",
650 .op = afs_FS_RemoveFile,
David Howellse49c7b22020-04-10 20:51:51 +0100651 .deliver = afs_deliver_fs_file_status_and_vol,
David Howells260a9802007-04-26 15:59:35 -0700652 .destructor = afs_flat_call_destructor,
653};
654
655/*
David Howellse49c7b22020-04-10 20:51:51 +0100656 * Remove a file.
David Howells260a9802007-04-26 15:59:35 -0700657 */
David Howellse49c7b22020-04-10 20:51:51 +0100658void afs_fs_remove_file(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700659{
David Howellse49c7b22020-04-10 20:51:51 +0100660 const struct qstr *name = &op->dentry->d_name;
661 struct afs_vnode_param *dvp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700662 struct afs_call *call;
663 size_t namesz, reqsz, padsz;
664 __be32 *bp;
665
666 _enter("");
667
David Howellse49c7b22020-04-10 20:51:51 +0100668 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700669 padsz = (4 - (namesz & 3)) & 3;
670 reqsz = (5 * 4) + namesz + padsz;
671
David Howellse49c7b22020-04-10 20:51:51 +0100672 call = afs_alloc_flat_call(op->net, &afs_RXFSRemoveFile,
673 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700674 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100675 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700676
677 /* marshall the parameters */
678 bp = call->request;
David Howellse49c7b22020-04-10 20:51:51 +0100679 *bp++ = htonl(FSREMOVEFILE);
680 *bp++ = htonl(dvp->fid.vid);
681 *bp++ = htonl(dvp->fid.vnode);
682 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700683 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100684 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700685 bp = (void *) bp + namesz;
686 if (padsz > 0) {
687 memset(bp, 0, padsz);
688 bp = (void *) bp + padsz;
689 }
690
David Howellse49c7b22020-04-10 20:51:51 +0100691 trace_afs_make_fs_call1(call, &dvp->fid, name);
692 afs_make_op_call(op, call, GFP_NOFS);
693}
694
695static const struct afs_call_type afs_RXFSRemoveDir = {
696 .name = "FS.RemoveDir",
697 .op = afs_FS_RemoveDir,
698 .deliver = afs_deliver_fs_file_status_and_vol,
699 .destructor = afs_flat_call_destructor,
700};
701
702/*
703 * Remove a directory.
704 */
705void afs_fs_remove_dir(struct afs_operation *op)
706{
707 const struct qstr *name = &op->dentry->d_name;
708 struct afs_vnode_param *dvp = &op->file[0];
709 struct afs_call *call;
710 size_t namesz, reqsz, padsz;
711 __be32 *bp;
712
713 _enter("");
714
715 namesz = name->len;
716 padsz = (4 - (namesz & 3)) & 3;
717 reqsz = (5 * 4) + namesz + padsz;
718
719 call = afs_alloc_flat_call(op->net, &afs_RXFSRemoveDir,
720 reqsz, (21 + 6) * 4);
721 if (!call)
722 return afs_op_nomem(op);
723
724 /* marshall the parameters */
725 bp = call->request;
726 *bp++ = htonl(FSREMOVEDIR);
727 *bp++ = htonl(dvp->fid.vid);
728 *bp++ = htonl(dvp->fid.vnode);
729 *bp++ = htonl(dvp->fid.unique);
730 *bp++ = htonl(namesz);
731 memcpy(bp, name->name, namesz);
732 bp = (void *) bp + namesz;
733 if (padsz > 0) {
734 memset(bp, 0, padsz);
735 bp = (void *) bp + padsz;
736 }
737
738 trace_afs_make_fs_call1(call, &dvp->fid, name);
739 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700740}
741
742/*
743 * deliver reply data to an FS.Link
744 */
David Howellsd0016482016-08-30 20:42:14 +0100745static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700746{
David Howellse49c7b22020-04-10 20:51:51 +0100747 struct afs_operation *op = call->op;
748 struct afs_vnode_param *dvp = &op->file[0];
749 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700750 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100751 int ret;
David Howells260a9802007-04-26 15:59:35 -0700752
David Howellsd0016482016-08-30 20:42:14 +0100753 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700754
David Howellsd0016482016-08-30 20:42:14 +0100755 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100756 if (ret < 0)
757 return ret;
David Howells260a9802007-04-26 15:59:35 -0700758
759 /* unmarshall the reply once we've received all of it */
760 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100761 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
762 xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
763 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700764
765 _leave(" = 0 [done]");
766 return 0;
767}
768
769/*
770 * FS.Link operation type
771 */
772static const struct afs_call_type afs_RXFSLink = {
773 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000774 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700775 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700776 .destructor = afs_flat_call_destructor,
777};
778
779/*
780 * make a hard link
781 */
David Howellse49c7b22020-04-10 20:51:51 +0100782void afs_fs_link(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700783{
David Howellse49c7b22020-04-10 20:51:51 +0100784 const struct qstr *name = &op->dentry->d_name;
785 struct afs_vnode_param *dvp = &op->file[0];
786 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700787 struct afs_call *call;
788 size_t namesz, reqsz, padsz;
789 __be32 *bp;
790
791 _enter("");
792
David Howellse49c7b22020-04-10 20:51:51 +0100793 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700794 padsz = (4 - (namesz & 3)) & 3;
795 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
796
David Howellse49c7b22020-04-10 20:51:51 +0100797 call = afs_alloc_flat_call(op->net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700798 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100799 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700800
801 /* marshall the parameters */
802 bp = call->request;
803 *bp++ = htonl(FSLINK);
David Howellse49c7b22020-04-10 20:51:51 +0100804 *bp++ = htonl(dvp->fid.vid);
805 *bp++ = htonl(dvp->fid.vnode);
806 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700807 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100808 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700809 bp = (void *) bp + namesz;
810 if (padsz > 0) {
811 memset(bp, 0, padsz);
812 bp = (void *) bp + padsz;
813 }
David Howellse49c7b22020-04-10 20:51:51 +0100814 *bp++ = htonl(vp->fid.vid);
815 *bp++ = htonl(vp->fid.vnode);
816 *bp++ = htonl(vp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700817
David Howellse49c7b22020-04-10 20:51:51 +0100818 trace_afs_make_fs_call1(call, &vp->fid, name);
819 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700820}
821
822/*
823 * deliver reply data to an FS.Symlink
824 */
David Howellsd0016482016-08-30 20:42:14 +0100825static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700826{
David Howellse49c7b22020-04-10 20:51:51 +0100827 struct afs_operation *op = call->op;
828 struct afs_vnode_param *dvp = &op->file[0];
829 struct afs_vnode_param *vp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700830 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100831 int ret;
David Howells260a9802007-04-26 15:59:35 -0700832
David Howellsd0016482016-08-30 20:42:14 +0100833 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700834
David Howellsd0016482016-08-30 20:42:14 +0100835 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100836 if (ret < 0)
837 return ret;
David Howells260a9802007-04-26 15:59:35 -0700838
839 /* unmarshall the reply once we've received all of it */
840 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +0100841 xdr_decode_AFSFid(&bp, &vp->fid);
842 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
843 xdr_decode_AFSFetchStatus(&bp, call, &dvp->scb);
844 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700845
846 _leave(" = 0 [done]");
847 return 0;
848}
849
850/*
851 * FS.Symlink operation type
852 */
853static const struct afs_call_type afs_RXFSSymlink = {
854 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +0000855 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -0700856 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700857 .destructor = afs_flat_call_destructor,
858};
859
860/*
861 * create a symbolic link
862 */
David Howellse49c7b22020-04-10 20:51:51 +0100863void afs_fs_symlink(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700864{
David Howellse49c7b22020-04-10 20:51:51 +0100865 const struct qstr *name = &op->dentry->d_name;
866 struct afs_vnode_param *dvp = &op->file[0];
David Howells260a9802007-04-26 15:59:35 -0700867 struct afs_call *call;
868 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
869 __be32 *bp;
870
871 _enter("");
872
David Howellse49c7b22020-04-10 20:51:51 +0100873 namesz = name->len;
David Howells260a9802007-04-26 15:59:35 -0700874 padsz = (4 - (namesz & 3)) & 3;
875
David Howellse49c7b22020-04-10 20:51:51 +0100876 c_namesz = strlen(op->create.symlink);
David Howells260a9802007-04-26 15:59:35 -0700877 c_padsz = (4 - (c_namesz & 3)) & 3;
878
879 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
880
David Howellse49c7b22020-04-10 20:51:51 +0100881 call = afs_alloc_flat_call(op->net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700882 (3 + 21 + 21 + 6) * 4);
883 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100884 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700885
886 /* marshall the parameters */
887 bp = call->request;
888 *bp++ = htonl(FSSYMLINK);
David Howellse49c7b22020-04-10 20:51:51 +0100889 *bp++ = htonl(dvp->fid.vid);
890 *bp++ = htonl(dvp->fid.vnode);
891 *bp++ = htonl(dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700892 *bp++ = htonl(namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100893 memcpy(bp, name->name, namesz);
David Howells260a9802007-04-26 15:59:35 -0700894 bp = (void *) bp + namesz;
895 if (padsz > 0) {
896 memset(bp, 0, padsz);
897 bp = (void *) bp + padsz;
898 }
899 *bp++ = htonl(c_namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100900 memcpy(bp, op->create.symlink, c_namesz);
David Howells260a9802007-04-26 15:59:35 -0700901 bp = (void *) bp + c_namesz;
902 if (c_padsz > 0) {
903 memset(bp, 0, c_padsz);
904 bp = (void *) bp + c_padsz;
905 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000906 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
David Howellse49c7b22020-04-10 20:51:51 +0100907 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700908 *bp++ = 0; /* owner */
909 *bp++ = 0; /* group */
910 *bp++ = htonl(S_IRWXUGO); /* unix mode */
911 *bp++ = 0; /* segment size */
912
David Howellse49c7b22020-04-10 20:51:51 +0100913 trace_afs_make_fs_call1(call, &dvp->fid, name);
914 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -0700915}
916
917/*
918 * deliver reply data to an FS.Rename
919 */
David Howellsd0016482016-08-30 20:42:14 +0100920static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700921{
David Howellse49c7b22020-04-10 20:51:51 +0100922 struct afs_operation *op = call->op;
923 struct afs_vnode_param *orig_dvp = &op->file[0];
924 struct afs_vnode_param *new_dvp = &op->file[1];
David Howells260a9802007-04-26 15:59:35 -0700925 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100926 int ret;
David Howells260a9802007-04-26 15:59:35 -0700927
David Howellsd0016482016-08-30 20:42:14 +0100928 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100929 if (ret < 0)
930 return ret;
David Howells260a9802007-04-26 15:59:35 -0700931
David Howells38355ee2020-04-08 16:13:20 +0100932 bp = call->buffer;
David Howellsb98f0ec2020-04-08 20:56:20 +0100933 /* If the two dirs are the same, we have two copies of the same status
934 * report, so we just decode it twice.
935 */
David Howellse49c7b22020-04-10 20:51:51 +0100936 xdr_decode_AFSFetchStatus(&bp, call, &orig_dvp->scb);
937 xdr_decode_AFSFetchStatus(&bp, call, &new_dvp->scb);
938 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells260a9802007-04-26 15:59:35 -0700939
940 _leave(" = 0 [done]");
941 return 0;
942}
943
944/*
945 * FS.Rename operation type
946 */
947static const struct afs_call_type afs_RXFSRename = {
948 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +0000949 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -0700950 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -0700951 .destructor = afs_flat_call_destructor,
952};
953
954/*
David Howellsa58823a2019-05-09 15:16:10 +0100955 * Rename/move a file or directory.
David Howells260a9802007-04-26 15:59:35 -0700956 */
David Howellse49c7b22020-04-10 20:51:51 +0100957void afs_fs_rename(struct afs_operation *op)
David Howells260a9802007-04-26 15:59:35 -0700958{
David Howellse49c7b22020-04-10 20:51:51 +0100959 struct afs_vnode_param *orig_dvp = &op->file[0];
960 struct afs_vnode_param *new_dvp = &op->file[1];
961 const struct qstr *orig_name = &op->dentry->d_name;
962 const struct qstr *new_name = &op->dentry_2->d_name;
David Howells260a9802007-04-26 15:59:35 -0700963 struct afs_call *call;
964 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
965 __be32 *bp;
966
967 _enter("");
968
David Howellse49c7b22020-04-10 20:51:51 +0100969 o_namesz = orig_name->len;
David Howells260a9802007-04-26 15:59:35 -0700970 o_padsz = (4 - (o_namesz & 3)) & 3;
971
David Howellse49c7b22020-04-10 20:51:51 +0100972 n_namesz = new_name->len;
David Howells260a9802007-04-26 15:59:35 -0700973 n_padsz = (4 - (n_namesz & 3)) & 3;
974
975 reqsz = (4 * 4) +
976 4 + o_namesz + o_padsz +
977 (3 * 4) +
978 4 + n_namesz + n_padsz;
979
David Howellse49c7b22020-04-10 20:51:51 +0100980 call = afs_alloc_flat_call(op->net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700981 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +0100982 return afs_op_nomem(op);
David Howells260a9802007-04-26 15:59:35 -0700983
984 /* marshall the parameters */
985 bp = call->request;
986 *bp++ = htonl(FSRENAME);
David Howellse49c7b22020-04-10 20:51:51 +0100987 *bp++ = htonl(orig_dvp->fid.vid);
988 *bp++ = htonl(orig_dvp->fid.vnode);
989 *bp++ = htonl(orig_dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700990 *bp++ = htonl(o_namesz);
David Howellse49c7b22020-04-10 20:51:51 +0100991 memcpy(bp, orig_name->name, o_namesz);
David Howells260a9802007-04-26 15:59:35 -0700992 bp = (void *) bp + o_namesz;
993 if (o_padsz > 0) {
994 memset(bp, 0, o_padsz);
995 bp = (void *) bp + o_padsz;
996 }
997
David Howellse49c7b22020-04-10 20:51:51 +0100998 *bp++ = htonl(new_dvp->fid.vid);
999 *bp++ = htonl(new_dvp->fid.vnode);
1000 *bp++ = htonl(new_dvp->fid.unique);
David Howells260a9802007-04-26 15:59:35 -07001001 *bp++ = htonl(n_namesz);
David Howellse49c7b22020-04-10 20:51:51 +01001002 memcpy(bp, new_name->name, n_namesz);
David Howells260a9802007-04-26 15:59:35 -07001003 bp = (void *) bp + n_namesz;
1004 if (n_padsz > 0) {
1005 memset(bp, 0, n_padsz);
1006 bp = (void *) bp + n_padsz;
1007 }
1008
David Howellse49c7b22020-04-10 20:51:51 +01001009 trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name);
1010 afs_make_op_call(op, call, GFP_NOFS);
David Howells260a9802007-04-26 15:59:35 -07001011}
David Howells31143d52007-05-09 02:33:46 -07001012
1013/*
David Howellse49c7b22020-04-10 20:51:51 +01001014 * Deliver reply data to FS.StoreData or FS.StoreStatus
David Howells31143d52007-05-09 02:33:46 -07001015 */
David Howellsd0016482016-08-30 20:42:14 +01001016static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001017{
David Howellse49c7b22020-04-10 20:51:51 +01001018 struct afs_operation *op = call->op;
1019 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001020 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001021 int ret;
David Howells31143d52007-05-09 02:33:46 -07001022
David Howellsd0016482016-08-30 20:42:14 +01001023 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001024
David Howellsd0016482016-08-30 20:42:14 +01001025 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001026 if (ret < 0)
1027 return ret;
David Howells31143d52007-05-09 02:33:46 -07001028
1029 /* unmarshall the reply once we've received all of it */
1030 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001031 xdr_decode_AFSFetchStatus(&bp, call, &vp->scb);
1032 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells31143d52007-05-09 02:33:46 -07001033
David Howells31143d52007-05-09 02:33:46 -07001034 _leave(" = 0 [done]");
1035 return 0;
1036}
1037
1038/*
1039 * FS.StoreData operation type
1040 */
1041static const struct afs_call_type afs_RXFSStoreData = {
1042 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001043 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001044 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001045 .destructor = afs_flat_call_destructor,
1046};
1047
David Howellsb9b1f8d2007-05-10 03:15:21 -07001048static const struct afs_call_type afs_RXFSStoreData64 = {
1049 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001050 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001051 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001052 .destructor = afs_flat_call_destructor,
1053};
1054
1055/*
1056 * store a set of pages to a very large file
1057 */
David Howellse49c7b22020-04-10 20:51:51 +01001058static void afs_fs_store_data64(struct afs_operation *op,
1059 loff_t pos, loff_t size, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001060{
David Howellse49c7b22020-04-10 20:51:51 +01001061 struct afs_vnode_param *vp = &op->file[0];
David Howellsb9b1f8d2007-05-10 03:15:21 -07001062 struct afs_call *call;
1063 __be32 *bp;
1064
David Howells3b6492d2018-10-20 00:57:57 +01001065 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001066 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001067
David Howellse49c7b22020-04-10 20:51:51 +01001068 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001069 (4 + 6 + 3 * 2) * 4,
1070 (21 + 6) * 4);
1071 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001072 return afs_op_nomem(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001073
David Howellsb9b1f8d2007-05-10 03:15:21 -07001074 call->send_pages = true;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001075
1076 /* marshall the parameters */
1077 bp = call->request;
1078 *bp++ = htonl(FSSTOREDATA64);
David Howellse49c7b22020-04-10 20:51:51 +01001079 *bp++ = htonl(vp->fid.vid);
1080 *bp++ = htonl(vp->fid.vnode);
1081 *bp++ = htonl(vp->fid.unique);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001082
Marc Dionneab94f5d2017-03-16 16:27:47 +00001083 *bp++ = htonl(AFS_SET_MTIME); /* mask */
David Howellse49c7b22020-04-10 20:51:51 +01001084 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001085 *bp++ = 0; /* owner */
1086 *bp++ = 0; /* group */
1087 *bp++ = 0; /* unix mode */
1088 *bp++ = 0; /* segment size */
1089
David Howellse49c7b22020-04-10 20:51:51 +01001090 *bp++ = htonl(upper_32_bits(pos));
1091 *bp++ = htonl(lower_32_bits(pos));
1092 *bp++ = htonl(upper_32_bits(size));
1093 *bp++ = htonl(lower_32_bits(size));
1094 *bp++ = htonl(upper_32_bits(i_size));
1095 *bp++ = htonl(lower_32_bits(i_size));
David Howellsb9b1f8d2007-05-10 03:15:21 -07001096
David Howellse49c7b22020-04-10 20:51:51 +01001097 trace_afs_make_fs_call(call, &vp->fid);
1098 afs_make_op_call(op, call, GFP_NOFS);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001099}
1100
David Howells31143d52007-05-09 02:33:46 -07001101/*
1102 * store a set of pages
1103 */
David Howellse49c7b22020-04-10 20:51:51 +01001104void afs_fs_store_data(struct afs_operation *op)
David Howells31143d52007-05-09 02:33:46 -07001105{
David Howellse49c7b22020-04-10 20:51:51 +01001106 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001107 struct afs_call *call;
1108 loff_t size, pos, i_size;
1109 __be32 *bp;
1110
David Howells3b6492d2018-10-20 00:57:57 +01001111 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001112 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001113
David Howellse49c7b22020-04-10 20:51:51 +01001114 size = (loff_t)op->store.last_to - (loff_t)op->store.first_offset;
1115 if (op->store.first != op->store.last)
1116 size += (loff_t)(op->store.last - op->store.first) << PAGE_SHIFT;
1117 pos = (loff_t)op->store.first << PAGE_SHIFT;
1118 pos += op->store.first_offset;
David Howells31143d52007-05-09 02:33:46 -07001119
David Howellse49c7b22020-04-10 20:51:51 +01001120 i_size = i_size_read(&vp->vnode->vfs_inode);
David Howells31143d52007-05-09 02:33:46 -07001121 if (pos + size > i_size)
1122 i_size = size + pos;
1123
1124 _debug("size %llx, at %llx, i_size %llx",
1125 (unsigned long long) size, (unsigned long long) pos,
1126 (unsigned long long) i_size);
1127
David Howellse49c7b22020-04-10 20:51:51 +01001128 if (upper_32_bits(pos) || upper_32_bits(i_size) || upper_32_bits(size) ||
1129 upper_32_bits(pos + size))
1130 return afs_fs_store_data64(op, pos, size, i_size);
David Howells31143d52007-05-09 02:33:46 -07001131
David Howellse49c7b22020-04-10 20:51:51 +01001132 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001133 (4 + 6 + 3) * 4,
1134 (21 + 6) * 4);
1135 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001136 return afs_op_nomem(op);
David Howells31143d52007-05-09 02:33:46 -07001137
David Howells31143d52007-05-09 02:33:46 -07001138 call->send_pages = true;
David Howells31143d52007-05-09 02:33:46 -07001139
1140 /* marshall the parameters */
1141 bp = call->request;
1142 *bp++ = htonl(FSSTOREDATA);
David Howellse49c7b22020-04-10 20:51:51 +01001143 *bp++ = htonl(vp->fid.vid);
1144 *bp++ = htonl(vp->fid.vnode);
1145 *bp++ = htonl(vp->fid.unique);
David Howells31143d52007-05-09 02:33:46 -07001146
Marc Dionneab94f5d2017-03-16 16:27:47 +00001147 *bp++ = htonl(AFS_SET_MTIME); /* mask */
David Howellse49c7b22020-04-10 20:51:51 +01001148 *bp++ = htonl(op->mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001149 *bp++ = 0; /* owner */
1150 *bp++ = 0; /* group */
1151 *bp++ = 0; /* unix mode */
1152 *bp++ = 0; /* segment size */
1153
David Howellse49c7b22020-04-10 20:51:51 +01001154 *bp++ = htonl(lower_32_bits(pos));
1155 *bp++ = htonl(lower_32_bits(size));
1156 *bp++ = htonl(lower_32_bits(i_size));
David Howells31143d52007-05-09 02:33:46 -07001157
David Howellse49c7b22020-04-10 20:51:51 +01001158 trace_afs_make_fs_call(call, &vp->fid);
1159 afs_make_op_call(op, call, GFP_NOFS);
David Howells31143d52007-05-09 02:33:46 -07001160}
1161
1162/*
1163 * FS.StoreStatus operation type
1164 */
1165static const struct afs_call_type afs_RXFSStoreStatus = {
1166 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001167 .op = afs_FS_StoreStatus,
David Howellse49c7b22020-04-10 20:51:51 +01001168 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001169 .destructor = afs_flat_call_destructor,
1170};
1171
1172static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1173 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001174 .op = afs_FS_StoreData,
David Howellse49c7b22020-04-10 20:51:51 +01001175 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001176 .destructor = afs_flat_call_destructor,
1177};
1178
David Howellsb9b1f8d2007-05-10 03:15:21 -07001179static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1180 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001181 .op = afs_FS_StoreData64,
David Howellse49c7b22020-04-10 20:51:51 +01001182 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001183 .destructor = afs_flat_call_destructor,
1184};
1185
1186/*
1187 * set the attributes on a very large file, using FS.StoreData rather than
1188 * FS.StoreStatus so as to alter the file size also
1189 */
David Howellse49c7b22020-04-10 20:51:51 +01001190static void afs_fs_setattr_size64(struct afs_operation *op)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001191{
David Howellse49c7b22020-04-10 20:51:51 +01001192 struct afs_vnode_param *vp = &op->file[0];
David Howellsb9b1f8d2007-05-10 03:15:21 -07001193 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01001194 struct iattr *attr = op->setattr.attr;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001195 __be32 *bp;
1196
David Howells3b6492d2018-10-20 00:57:57 +01001197 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001198 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001199
1200 ASSERT(attr->ia_valid & ATTR_SIZE);
1201
David Howellse49c7b22020-04-10 20:51:51 +01001202 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001203 (4 + 6 + 3 * 2) * 4,
1204 (21 + 6) * 4);
1205 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001206 return afs_op_nomem(op);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001207
1208 /* marshall the parameters */
1209 bp = call->request;
1210 *bp++ = htonl(FSSTOREDATA64);
David Howellse49c7b22020-04-10 20:51:51 +01001211 *bp++ = htonl(vp->fid.vid);
1212 *bp++ = htonl(vp->fid.vnode);
1213 *bp++ = htonl(vp->fid.unique);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001214
1215 xdr_encode_AFS_StoreStatus(&bp, attr);
1216
David Howellse49c7b22020-04-10 20:51:51 +01001217 *bp++ = htonl(upper_32_bits(attr->ia_size)); /* position of start of write */
1218 *bp++ = htonl(lower_32_bits(attr->ia_size));
1219 *bp++ = 0; /* size of write */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001220 *bp++ = 0;
David Howellse49c7b22020-04-10 20:51:51 +01001221 *bp++ = htonl(upper_32_bits(attr->ia_size)); /* new file length */
1222 *bp++ = htonl(lower_32_bits(attr->ia_size));
David Howellsb9b1f8d2007-05-10 03:15:21 -07001223
David Howellse49c7b22020-04-10 20:51:51 +01001224 trace_afs_make_fs_call(call, &vp->fid);
1225 afs_make_op_call(op, call, GFP_NOFS);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001226}
1227
David Howells31143d52007-05-09 02:33:46 -07001228/*
1229 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1230 * so as to alter the file size also
1231 */
David Howellse49c7b22020-04-10 20:51:51 +01001232static void afs_fs_setattr_size(struct afs_operation *op)
David Howells31143d52007-05-09 02:33:46 -07001233{
David Howellse49c7b22020-04-10 20:51:51 +01001234 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001235 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01001236 struct iattr *attr = op->setattr.attr;
David Howells31143d52007-05-09 02:33:46 -07001237 __be32 *bp;
1238
David Howells3b6492d2018-10-20 00:57:57 +01001239 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001240 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001241
1242 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellse49c7b22020-04-10 20:51:51 +01001243 if (upper_32_bits(attr->ia_size))
1244 return afs_fs_setattr_size64(op);
David Howells31143d52007-05-09 02:33:46 -07001245
David Howellse49c7b22020-04-10 20:51:51 +01001246 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001247 (4 + 6 + 3) * 4,
1248 (21 + 6) * 4);
1249 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001250 return afs_op_nomem(op);
David Howells31143d52007-05-09 02:33:46 -07001251
1252 /* marshall the parameters */
1253 bp = call->request;
1254 *bp++ = htonl(FSSTOREDATA);
David Howellse49c7b22020-04-10 20:51:51 +01001255 *bp++ = htonl(vp->fid.vid);
1256 *bp++ = htonl(vp->fid.vnode);
1257 *bp++ = htonl(vp->fid.unique);
David Howells31143d52007-05-09 02:33:46 -07001258
1259 xdr_encode_AFS_StoreStatus(&bp, attr);
1260
David Howells8c7ae382019-03-27 22:48:02 +00001261 *bp++ = htonl(attr->ia_size); /* position of start of write */
David Howells31143d52007-05-09 02:33:46 -07001262 *bp++ = 0; /* size of write */
1263 *bp++ = htonl(attr->ia_size); /* new file length */
1264
David Howellse49c7b22020-04-10 20:51:51 +01001265 trace_afs_make_fs_call(call, &vp->fid);
1266 afs_make_op_call(op, call, GFP_NOFS);
David Howells31143d52007-05-09 02:33:46 -07001267}
1268
1269/*
1270 * set the attributes on a file, using FS.StoreData if there's a change in file
1271 * size, and FS.StoreStatus otherwise
1272 */
David Howellse49c7b22020-04-10 20:51:51 +01001273void afs_fs_setattr(struct afs_operation *op)
David Howells31143d52007-05-09 02:33:46 -07001274{
David Howellse49c7b22020-04-10 20:51:51 +01001275 struct afs_vnode_param *vp = &op->file[0];
David Howells31143d52007-05-09 02:33:46 -07001276 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01001277 struct iattr *attr = op->setattr.attr;
David Howells31143d52007-05-09 02:33:46 -07001278 __be32 *bp;
1279
1280 if (attr->ia_valid & ATTR_SIZE)
David Howellse49c7b22020-04-10 20:51:51 +01001281 return afs_fs_setattr_size(op);
David Howells31143d52007-05-09 02:33:46 -07001282
David Howells3b6492d2018-10-20 00:57:57 +01001283 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01001284 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001285
David Howellse49c7b22020-04-10 20:51:51 +01001286 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001287 (4 + 6) * 4,
1288 (21 + 6) * 4);
1289 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001290 return afs_op_nomem(op);
David Howells31143d52007-05-09 02:33:46 -07001291
1292 /* marshall the parameters */
1293 bp = call->request;
1294 *bp++ = htonl(FSSTORESTATUS);
David Howellse49c7b22020-04-10 20:51:51 +01001295 *bp++ = htonl(vp->fid.vid);
1296 *bp++ = htonl(vp->fid.vnode);
1297 *bp++ = htonl(vp->fid.unique);
David Howells31143d52007-05-09 02:33:46 -07001298
David Howellse49c7b22020-04-10 20:51:51 +01001299 xdr_encode_AFS_StoreStatus(&bp, op->setattr.attr);
David Howells31143d52007-05-09 02:33:46 -07001300
David Howellse49c7b22020-04-10 20:51:51 +01001301 trace_afs_make_fs_call(call, &vp->fid);
1302 afs_make_op_call(op, call, GFP_NOFS);
David Howells31143d52007-05-09 02:33:46 -07001303}
David Howells45222b92007-05-10 22:22:20 -07001304
1305/*
1306 * deliver reply data to an FS.GetVolumeStatus
1307 */
David Howellsd0016482016-08-30 20:42:14 +01001308static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001309{
David Howellse49c7b22020-04-10 20:51:51 +01001310 struct afs_operation *op = call->op;
David Howells45222b92007-05-10 22:22:20 -07001311 const __be32 *bp;
1312 char *p;
David Howells12bdcf32018-10-20 00:57:56 +01001313 u32 size;
David Howells45222b92007-05-10 22:22:20 -07001314 int ret;
1315
David Howellsd0016482016-08-30 20:42:14 +01001316 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001317
1318 switch (call->unmarshall) {
1319 case 0:
David Howells45222b92007-05-10 22:22:20 -07001320 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001321 afs_extract_to_buf(call, 12 * 4);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001322 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001323
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001324 /* extract the returned status record */
David Howells45222b92007-05-10 22:22:20 -07001325 case 1:
1326 _debug("extract status");
David Howells12bdcf32018-10-20 00:57:56 +01001327 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001328 if (ret < 0)
1329 return ret;
David Howells45222b92007-05-10 22:22:20 -07001330
1331 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001332 xdr_decode_AFSFetchVolumeStatus(&bp, &op->volstatus.vs);
David Howells45222b92007-05-10 22:22:20 -07001333 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001334 afs_extract_to_tmp(call);
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 length */
David Howells45222b92007-05-10 22:22:20 -07001338 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001339 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001340 if (ret < 0)
1341 return ret;
David Howells45222b92007-05-10 22:22:20 -07001342
1343 call->count = ntohl(call->tmp);
1344 _debug("volname length: %u", call->count);
1345 if (call->count >= AFSNAMEMAX)
David Howells7126ead2020-04-08 16:49:08 +01001346 return afs_protocol_error(call, afs_eproto_volname_len);
David Howells12bdcf32018-10-20 00:57:56 +01001347 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001348 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001349 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001350 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001351
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001352 /* extract the volume name */
David Howells45222b92007-05-10 22:22:20 -07001353 case 3:
1354 _debug("extract volname");
David Howells12bdcf32018-10-20 00:57:56 +01001355 ret = afs_extract_data(call, true);
1356 if (ret < 0)
1357 return ret;
David Howells45222b92007-05-10 22:22:20 -07001358
David Howellsffba7182019-05-09 22:22:50 +01001359 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001360 p[call->count] = 0;
1361 _debug("volname '%s'", p);
David Howells12bdcf32018-10-20 00:57:56 +01001362 afs_extract_to_tmp(call);
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 length */
David Howells12bdcf32018-10-20 00:57:56 +01001367 case 4:
1368 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001369 if (ret < 0)
1370 return ret;
David Howells45222b92007-05-10 22:22:20 -07001371
1372 call->count = ntohl(call->tmp);
1373 _debug("offline msg length: %u", call->count);
1374 if (call->count >= AFSNAMEMAX)
David Howells7126ead2020-04-08 16:49:08 +01001375 return afs_protocol_error(call, afs_eproto_offline_msg_len);
David Howells12bdcf32018-10-20 00:57:56 +01001376 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001377 afs_extract_to_buf(call, size);
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 offline message */
David Howells12bdcf32018-10-20 00:57:56 +01001382 case 5:
David Howells45222b92007-05-10 22:22:20 -07001383 _debug("extract offline");
David Howells12bdcf32018-10-20 00:57:56 +01001384 ret = afs_extract_data(call, true);
1385 if (ret < 0)
1386 return ret;
David Howells45222b92007-05-10 22:22:20 -07001387
David Howellsffba7182019-05-09 22:22:50 +01001388 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001389 p[call->count] = 0;
1390 _debug("offline '%s'", p);
1391
David Howells12bdcf32018-10-20 00:57:56 +01001392 afs_extract_to_tmp(call);
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 length */
David Howells12bdcf32018-10-20 00:57:56 +01001397 case 6:
1398 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001399 if (ret < 0)
1400 return ret;
David Howells45222b92007-05-10 22:22:20 -07001401
1402 call->count = ntohl(call->tmp);
1403 _debug("motd length: %u", call->count);
1404 if (call->count >= AFSNAMEMAX)
David Howells7126ead2020-04-08 16:49:08 +01001405 return afs_protocol_error(call, afs_eproto_motd_len);
David Howells12bdcf32018-10-20 00:57:56 +01001406 size = (call->count + 3) & ~3; /* It's padded */
David Howellsffba7182019-05-09 22:22:50 +01001407 afs_extract_to_buf(call, size);
David Howells45222b92007-05-10 22:22:20 -07001408 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001409 fallthrough;
David Howells45222b92007-05-10 22:22:20 -07001410
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001411 /* extract the message of the day */
David Howells12bdcf32018-10-20 00:57:56 +01001412 case 7:
David Howells45222b92007-05-10 22:22:20 -07001413 _debug("extract motd");
David Howells12bdcf32018-10-20 00:57:56 +01001414 ret = afs_extract_data(call, false);
1415 if (ret < 0)
1416 return ret;
David Howells45222b92007-05-10 22:22:20 -07001417
David Howellsffba7182019-05-09 22:22:50 +01001418 p = call->buffer;
David Howells45222b92007-05-10 22:22:20 -07001419 p[call->count] = 0;
1420 _debug("motd '%s'", p);
1421
David Howells45222b92007-05-10 22:22:20 -07001422 call->unmarshall++;
1423
David Howells12bdcf32018-10-20 00:57:56 +01001424 case 8:
David Howells45222b92007-05-10 22:22:20 -07001425 break;
1426 }
1427
David Howells45222b92007-05-10 22:22:20 -07001428 _leave(" = 0 [done]");
1429 return 0;
1430}
1431
1432/*
David Howells45222b92007-05-10 22:22:20 -07001433 * FS.GetVolumeStatus operation type
1434 */
1435static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1436 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001437 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001438 .deliver = afs_deliver_fs_get_volume_status,
David Howellsffba7182019-05-09 22:22:50 +01001439 .destructor = afs_flat_call_destructor,
David Howells45222b92007-05-10 22:22:20 -07001440};
1441
1442/*
1443 * fetch the status of a volume
1444 */
David Howellse49c7b22020-04-10 20:51:51 +01001445void afs_fs_get_volume_status(struct afs_operation *op)
David Howells45222b92007-05-10 22:22:20 -07001446{
David Howellse49c7b22020-04-10 20:51:51 +01001447 struct afs_vnode_param *vp = &op->file[0];
David Howells45222b92007-05-10 22:22:20 -07001448 struct afs_call *call;
1449 __be32 *bp;
David Howells45222b92007-05-10 22:22:20 -07001450
1451 _enter("");
1452
David Howellse49c7b22020-04-10 20:51:51 +01001453 call = afs_alloc_flat_call(op->net, &afs_RXFSGetVolumeStatus, 2 * 4,
David Howellsffba7182019-05-09 22:22:50 +01001454 max(12 * 4, AFSOPAQUEMAX + 1));
1455 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001456 return afs_op_nomem(op);
David Howells45222b92007-05-10 22:22:20 -07001457
1458 /* marshall the parameters */
1459 bp = call->request;
1460 bp[0] = htonl(FSGETVOLUMESTATUS);
David Howellse49c7b22020-04-10 20:51:51 +01001461 bp[1] = htonl(vp->fid.vid);
David Howells45222b92007-05-10 22:22:20 -07001462
David Howellse49c7b22020-04-10 20:51:51 +01001463 trace_afs_make_fs_call(call, &vp->fid);
1464 afs_make_op_call(op, call, GFP_NOFS);
David Howells45222b92007-05-10 22:22:20 -07001465}
David Howellse8d6c552007-07-15 23:40:12 -07001466
1467/*
1468 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1469 */
David Howellsd0016482016-08-30 20:42:14 +01001470static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001471{
David Howellse49c7b22020-04-10 20:51:51 +01001472 struct afs_operation *op = call->op;
David Howellse8d6c552007-07-15 23:40:12 -07001473 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001474 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001475
David Howellsd0016482016-08-30 20:42:14 +01001476 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001477
David Howellsd0016482016-08-30 20:42:14 +01001478 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001479 if (ret < 0)
1480 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001481
1482 /* unmarshall the reply once we've received all of it */
1483 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001484 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howellse8d6c552007-07-15 23:40:12 -07001485
1486 _leave(" = 0 [done]");
1487 return 0;
1488}
1489
1490/*
1491 * FS.SetLock operation type
1492 */
1493static const struct afs_call_type afs_RXFSSetLock = {
1494 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001495 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001496 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001497 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001498 .destructor = afs_flat_call_destructor,
1499};
1500
1501/*
1502 * FS.ExtendLock operation type
1503 */
1504static const struct afs_call_type afs_RXFSExtendLock = {
1505 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001506 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001507 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001508 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001509 .destructor = afs_flat_call_destructor,
1510};
1511
1512/*
1513 * FS.ReleaseLock operation type
1514 */
1515static const struct afs_call_type afs_RXFSReleaseLock = {
1516 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001517 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001518 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001519 .destructor = afs_flat_call_destructor,
1520};
1521
1522/*
David Howellsd2ddc772017-11-02 15:27:50 +00001523 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001524 */
David Howellse49c7b22020-04-10 20:51:51 +01001525void afs_fs_set_lock(struct afs_operation *op)
David Howellse8d6c552007-07-15 23:40:12 -07001526{
David Howellse49c7b22020-04-10 20:51:51 +01001527 struct afs_vnode_param *vp = &op->file[0];
David Howellse8d6c552007-07-15 23:40:12 -07001528 struct afs_call *call;
1529 __be32 *bp;
1530
1531 _enter("");
1532
David Howellse49c7b22020-04-10 20:51:51 +01001533 call = afs_alloc_flat_call(op->net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001534 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001535 return afs_op_nomem(op);
David Howellse8d6c552007-07-15 23:40:12 -07001536
1537 /* marshall the parameters */
1538 bp = call->request;
1539 *bp++ = htonl(FSSETLOCK);
David Howellse49c7b22020-04-10 20:51:51 +01001540 *bp++ = htonl(vp->fid.vid);
1541 *bp++ = htonl(vp->fid.vnode);
1542 *bp++ = htonl(vp->fid.unique);
1543 *bp++ = htonl(op->lock.type);
David Howellse8d6c552007-07-15 23:40:12 -07001544
David Howellse49c7b22020-04-10 20:51:51 +01001545 trace_afs_make_fs_calli(call, &vp->fid, op->lock.type);
1546 afs_make_op_call(op, call, GFP_NOFS);
David Howellse8d6c552007-07-15 23:40:12 -07001547}
1548
1549/*
1550 * extend a lock on a file
1551 */
David Howellse49c7b22020-04-10 20:51:51 +01001552void afs_fs_extend_lock(struct afs_operation *op)
David Howellse8d6c552007-07-15 23:40:12 -07001553{
David Howellse49c7b22020-04-10 20:51:51 +01001554 struct afs_vnode_param *vp = &op->file[0];
David Howellse8d6c552007-07-15 23:40:12 -07001555 struct afs_call *call;
1556 __be32 *bp;
1557
1558 _enter("");
1559
David Howellse49c7b22020-04-10 20:51:51 +01001560 call = afs_alloc_flat_call(op->net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001561 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001562 return afs_op_nomem(op);
David Howellse8d6c552007-07-15 23:40:12 -07001563
1564 /* marshall the parameters */
1565 bp = call->request;
1566 *bp++ = htonl(FSEXTENDLOCK);
David Howellse49c7b22020-04-10 20:51:51 +01001567 *bp++ = htonl(vp->fid.vid);
1568 *bp++ = htonl(vp->fid.vnode);
1569 *bp++ = htonl(vp->fid.unique);
David Howellse8d6c552007-07-15 23:40:12 -07001570
David Howellse49c7b22020-04-10 20:51:51 +01001571 trace_afs_make_fs_call(call, &vp->fid);
1572 afs_make_op_call(op, call, GFP_NOFS);
David Howellse8d6c552007-07-15 23:40:12 -07001573}
1574
1575/*
1576 * release a lock on a file
1577 */
David Howellse49c7b22020-04-10 20:51:51 +01001578void afs_fs_release_lock(struct afs_operation *op)
David Howellse8d6c552007-07-15 23:40:12 -07001579{
David Howellse49c7b22020-04-10 20:51:51 +01001580 struct afs_vnode_param *vp = &op->file[0];
David Howellse8d6c552007-07-15 23:40:12 -07001581 struct afs_call *call;
1582 __be32 *bp;
1583
1584 _enter("");
1585
David Howellse49c7b22020-04-10 20:51:51 +01001586 call = afs_alloc_flat_call(op->net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001587 if (!call)
David Howellse49c7b22020-04-10 20:51:51 +01001588 return afs_op_nomem(op);
David Howellse8d6c552007-07-15 23:40:12 -07001589
1590 /* marshall the parameters */
1591 bp = call->request;
1592 *bp++ = htonl(FSRELEASELOCK);
David Howellse49c7b22020-04-10 20:51:51 +01001593 *bp++ = htonl(vp->fid.vid);
1594 *bp++ = htonl(vp->fid.vnode);
1595 *bp++ = htonl(vp->fid.unique);
David Howellse8d6c552007-07-15 23:40:12 -07001596
David Howellse49c7b22020-04-10 20:51:51 +01001597 trace_afs_make_fs_call(call, &vp->fid);
1598 afs_make_op_call(op, call, GFP_NOFS);
David Howellsc435ee32017-11-02 15:27:49 +00001599}
1600
1601/*
1602 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1603 */
1604static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1605{
1606 return afs_transfer_reply(call);
1607}
1608
1609/*
1610 * FS.GiveUpAllCallBacks operation type
1611 */
1612static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1613 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001614 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001615 .deliver = afs_deliver_fs_give_up_all_callbacks,
1616 .destructor = afs_flat_call_destructor,
1617};
1618
1619/*
1620 * Flush all the callbacks we have on a server.
1621 */
David Howellsd2ddc772017-11-02 15:27:50 +00001622int afs_fs_give_up_all_callbacks(struct afs_net *net,
1623 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001624 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001625 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001626{
1627 struct afs_call *call;
1628 __be32 *bp;
1629
1630 _enter("");
1631
David Howellsd2ddc772017-11-02 15:27:50 +00001632 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001633 if (!call)
1634 return -ENOMEM;
1635
1636 call->key = key;
1637
1638 /* marshall the parameters */
1639 bp = call->request;
1640 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1641
David Howells977e5f82020-04-17 17:31:26 +01001642 call->server = afs_use_server(server, afs_server_trace_give_up_cb);
David Howells0b9bf382019-04-25 14:26:50 +01001643 afs_make_call(ac, call, GFP_NOFS);
1644 return afs_wait_for_call_to_complete(call, ac);
David Howellsd2ddc772017-11-02 15:27:50 +00001645}
1646
1647/*
1648 * Deliver reply data to an FS.GetCapabilities operation.
1649 */
1650static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1651{
1652 u32 count;
1653 int ret;
1654
David Howellsfc276122019-11-21 09:12:17 +00001655 _enter("{%u,%zu}", call->unmarshall, iov_iter_count(call->iter));
David Howellsd2ddc772017-11-02 15:27:50 +00001656
David Howellsd2ddc772017-11-02 15:27:50 +00001657 switch (call->unmarshall) {
1658 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01001659 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00001660 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001661 fallthrough;
David Howellsd2ddc772017-11-02 15:27:50 +00001662
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001663 /* Extract the capabilities word count */
David Howellsd2ddc772017-11-02 15:27:50 +00001664 case 1:
David Howells12bdcf32018-10-20 00:57:56 +01001665 ret = afs_extract_data(call, true);
David Howellsd2ddc772017-11-02 15:27:50 +00001666 if (ret < 0)
1667 return ret;
1668
1669 count = ntohl(call->tmp);
1670
1671 call->count = count;
1672 call->count2 = count;
David Howells23a28912019-08-20 09:22:38 +01001673 afs_extract_discard(call, count * sizeof(__be32));
David Howellsd2ddc772017-11-02 15:27:50 +00001674 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001675 fallthrough;
David Howellsd2ddc772017-11-02 15:27:50 +00001676
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001677 /* Extract capabilities words */
David Howellsd2ddc772017-11-02 15:27:50 +00001678 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001679 ret = afs_extract_data(call, false);
David Howellsd2ddc772017-11-02 15:27:50 +00001680 if (ret < 0)
1681 return ret;
1682
1683 /* TODO: Examine capabilities */
1684
David Howellsd2ddc772017-11-02 15:27:50 +00001685 call->unmarshall++;
1686 break;
1687 }
1688
1689 _leave(" = 0 [done]");
1690 return 0;
1691}
1692
1693/*
1694 * FS.GetCapabilities operation type
1695 */
1696static const struct afs_call_type afs_RXFSGetCapabilities = {
1697 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001698 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001699 .deliver = afs_deliver_fs_get_capabilities,
David Howells3bf0fb62018-10-20 00:57:59 +01001700 .done = afs_fileserver_probe_result,
David Howellsffba7182019-05-09 22:22:50 +01001701 .destructor = afs_flat_call_destructor,
David Howellsd2ddc772017-11-02 15:27:50 +00001702};
1703
1704/*
David Howellsf6cbb362020-04-24 15:10:00 +01001705 * Probe a fileserver for the capabilities that it supports. This RPC can
1706 * reply with up to 196 words. The operation is asynchronous and if we managed
1707 * to allocate a call, true is returned the result is delivered through the
1708 * ->done() - otherwise we return false to indicate we didn't even try.
David Howellsd2ddc772017-11-02 15:27:50 +00001709 */
David Howellsf6cbb362020-04-24 15:10:00 +01001710bool afs_fs_get_capabilities(struct afs_net *net, struct afs_server *server,
1711 struct afs_addr_cursor *ac, struct key *key)
David Howellsd2ddc772017-11-02 15:27:50 +00001712{
1713 struct afs_call *call;
1714 __be32 *bp;
1715
1716 _enter("");
1717
1718 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1719 if (!call)
David Howellsf6cbb362020-04-24 15:10:00 +01001720 return false;
David Howellsd2ddc772017-11-02 15:27:50 +00001721
1722 call->key = key;
David Howells977e5f82020-04-17 17:31:26 +01001723 call->server = afs_use_server(server, afs_server_trace_get_caps);
David Howells30062bd2018-10-20 00:57:58 +01001724 call->upgrade = true;
David Howells0b9bf382019-04-25 14:26:50 +01001725 call->async = true;
David Howells94f699c2019-05-16 13:21:59 +01001726 call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
David Howellsd2ddc772017-11-02 15:27:50 +00001727
1728 /* marshall the parameters */
1729 bp = call->request;
1730 *bp++ = htonl(FSGETCAPABILITIES);
1731
David Howells025db802017-11-02 15:27:51 +00001732 trace_afs_make_fs_call(call, NULL);
David Howells0b9bf382019-04-25 14:26:50 +01001733 afs_make_call(ac, call, GFP_NOFS);
David Howellsf6cbb362020-04-24 15:10:00 +01001734 afs_put_call(call);
1735 return true;
David Howellse8d6c552007-07-15 23:40:12 -07001736}
David Howells5cf9dd52018-04-09 21:12:31 +01001737
1738/*
David Howells5cf9dd52018-04-09 21:12:31 +01001739 * Deliver reply data to an FS.InlineBulkStatus call
1740 */
1741static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
1742{
David Howellse49c7b22020-04-10 20:51:51 +01001743 struct afs_operation *op = call->op;
David Howells87182752019-05-09 16:17:05 +01001744 struct afs_status_cb *scb;
David Howells5cf9dd52018-04-09 21:12:31 +01001745 const __be32 *bp;
1746 u32 tmp;
1747 int ret;
1748
1749 _enter("{%u}", call->unmarshall);
1750
1751 switch (call->unmarshall) {
1752 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01001753 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01001754 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001755 fallthrough;
David Howells5cf9dd52018-04-09 21:12:31 +01001756
1757 /* Extract the file status count and array in two steps */
1758 case 1:
1759 _debug("extract status count");
David Howells12bdcf32018-10-20 00:57:56 +01001760 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001761 if (ret < 0)
1762 return ret;
1763
1764 tmp = ntohl(call->tmp);
David Howellse49c7b22020-04-10 20:51:51 +01001765 _debug("status count: %u/%u", tmp, op->nr_files);
1766 if (tmp != op->nr_files)
David Howells7126ead2020-04-08 16:49:08 +01001767 return afs_protocol_error(call, afs_eproto_ibulkst_count);
David Howells5cf9dd52018-04-09 21:12:31 +01001768
1769 call->count = 0;
1770 call->unmarshall++;
1771 more_counts:
David Howells12bdcf32018-10-20 00:57:56 +01001772 afs_extract_to_buf(call, 21 * sizeof(__be32));
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001773 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001774
David Howells5cf9dd52018-04-09 21:12:31 +01001775 case 2:
1776 _debug("extract status array %u", call->count);
David Howells12bdcf32018-10-20 00:57:56 +01001777 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001778 if (ret < 0)
1779 return ret;
1780
David Howellse49c7b22020-04-10 20:51:51 +01001781 switch (call->count) {
1782 case 0:
1783 scb = &op->file[0].scb;
1784 break;
1785 case 1:
1786 scb = &op->file[1].scb;
1787 break;
1788 default:
1789 scb = &op->more_files[call->count - 2].scb;
1790 break;
1791 }
1792
David Howells5cf9dd52018-04-09 21:12:31 +01001793 bp = call->buffer;
David Howells38355ee2020-04-08 16:13:20 +01001794 xdr_decode_AFSFetchStatus(&bp, call, scb);
David Howellse49c7b22020-04-10 20:51:51 +01001795
David Howells5cf9dd52018-04-09 21:12:31 +01001796 call->count++;
David Howellse49c7b22020-04-10 20:51:51 +01001797 if (call->count < op->nr_files)
David Howells5cf9dd52018-04-09 21:12:31 +01001798 goto more_counts;
1799
1800 call->count = 0;
1801 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001802 afs_extract_to_tmp(call);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001803 fallthrough;
David Howells5cf9dd52018-04-09 21:12:31 +01001804
1805 /* Extract the callback count and array in two steps */
1806 case 3:
1807 _debug("extract CB count");
David Howells12bdcf32018-10-20 00:57:56 +01001808 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001809 if (ret < 0)
1810 return ret;
1811
1812 tmp = ntohl(call->tmp);
1813 _debug("CB count: %u", tmp);
David Howellse49c7b22020-04-10 20:51:51 +01001814 if (tmp != op->nr_files)
David Howells7126ead2020-04-08 16:49:08 +01001815 return afs_protocol_error(call, afs_eproto_ibulkst_cb_count);
David Howells5cf9dd52018-04-09 21:12:31 +01001816 call->count = 0;
1817 call->unmarshall++;
1818 more_cbs:
David Howells12bdcf32018-10-20 00:57:56 +01001819 afs_extract_to_buf(call, 3 * sizeof(__be32));
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001820 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001821
David Howells5cf9dd52018-04-09 21:12:31 +01001822 case 4:
1823 _debug("extract CB array");
David Howells12bdcf32018-10-20 00:57:56 +01001824 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01001825 if (ret < 0)
1826 return ret;
1827
1828 _debug("unmarshall CB array");
David Howellse49c7b22020-04-10 20:51:51 +01001829 switch (call->count) {
1830 case 0:
1831 scb = &op->file[0].scb;
1832 break;
1833 case 1:
1834 scb = &op->file[1].scb;
1835 break;
1836 default:
1837 scb = &op->more_files[call->count - 2].scb;
1838 break;
1839 }
1840
David Howells5cf9dd52018-04-09 21:12:31 +01001841 bp = call->buffer;
David Howellsa58823a2019-05-09 15:16:10 +01001842 xdr_decode_AFSCallBack(&bp, call, scb);
David Howells5cf9dd52018-04-09 21:12:31 +01001843 call->count++;
David Howellse49c7b22020-04-10 20:51:51 +01001844 if (call->count < op->nr_files)
David Howells5cf9dd52018-04-09 21:12:31 +01001845 goto more_cbs;
1846
David Howells12bdcf32018-10-20 00:57:56 +01001847 afs_extract_to_buf(call, 6 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01001848 call->unmarshall++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001849 fallthrough;
Gustavo A. R. Silva29881602019-05-19 18:43:53 -05001850
David Howells5cf9dd52018-04-09 21:12:31 +01001851 case 5:
David Howells12bdcf32018-10-20 00:57:56 +01001852 ret = afs_extract_data(call, false);
David Howells5cf9dd52018-04-09 21:12:31 +01001853 if (ret < 0)
1854 return ret;
1855
1856 bp = call->buffer;
David Howellse49c7b22020-04-10 20:51:51 +01001857 xdr_decode_AFSVolSync(&bp, &op->volsync);
David Howells5cf9dd52018-04-09 21:12:31 +01001858
David Howells5cf9dd52018-04-09 21:12:31 +01001859 call->unmarshall++;
1860
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++;
1994
1995 case 4:
1996 break;
1997 }
1998
1999 _leave(" = 0 [done]");
2000 return 0;
2001}
2002
David Howells260f0822019-04-25 14:26:52 +01002003/*
2004 * FS.FetchACL operation type
2005 */
2006static const struct afs_call_type afs_RXFSFetchACL = {
2007 .name = "FS.FetchACL",
2008 .op = afs_FS_FetchACL,
2009 .deliver = afs_deliver_fs_fetch_acl,
David Howells260f0822019-04-25 14:26:52 +01002010};
2011
2012/*
2013 * Fetch the ACL for a file.
2014 */
David Howellse49c7b22020-04-10 20:51:51 +01002015void afs_fs_fetch_acl(struct afs_operation *op)
David Howells260f0822019-04-25 14:26:52 +01002016{
David Howellse49c7b22020-04-10 20:51:51 +01002017 struct afs_vnode_param *vp = &op->file[0];
David Howells260f0822019-04-25 14:26:52 +01002018 struct afs_call *call;
David Howells260f0822019-04-25 14:26:52 +01002019 __be32 *bp;
2020
2021 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01002022 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
David Howells260f0822019-04-25 14:26:52 +01002023
David Howellse49c7b22020-04-10 20:51:51 +01002024 call = afs_alloc_flat_call(op->net, &afs_RXFSFetchACL, 16, (21 + 6) * 4);
2025 if (!call)
2026 return afs_op_nomem(op);
David Howells260f0822019-04-25 14:26:52 +01002027
2028 /* marshall the parameters */
2029 bp = call->request;
2030 bp[0] = htonl(FSFETCHACL);
David Howellse49c7b22020-04-10 20:51:51 +01002031 bp[1] = htonl(vp->fid.vid);
2032 bp[2] = htonl(vp->fid.vnode);
2033 bp[3] = htonl(vp->fid.unique);
David Howells260f0822019-04-25 14:26:52 +01002034
David Howellse49c7b22020-04-10 20:51:51 +01002035 trace_afs_make_fs_call(call, &vp->fid);
2036 afs_make_op_call(op, call, GFP_KERNEL);
David Howellsffba7182019-05-09 22:22:50 +01002037}
2038
2039/*
Joe Gorseb10494a2019-04-25 14:26:52 +01002040 * FS.StoreACL operation type
2041 */
2042static const struct afs_call_type afs_RXFSStoreACL = {
2043 .name = "FS.StoreACL",
2044 .op = afs_FS_StoreACL,
David Howellsffba7182019-05-09 22:22:50 +01002045 .deliver = afs_deliver_fs_file_status_and_vol,
Joe Gorseb10494a2019-04-25 14:26:52 +01002046 .destructor = afs_flat_call_destructor,
2047};
2048
2049/*
2050 * Fetch the ACL for a file.
2051 */
David Howellse49c7b22020-04-10 20:51:51 +01002052void afs_fs_store_acl(struct afs_operation *op)
Joe Gorseb10494a2019-04-25 14:26:52 +01002053{
David Howellse49c7b22020-04-10 20:51:51 +01002054 struct afs_vnode_param *vp = &op->file[0];
Joe Gorseb10494a2019-04-25 14:26:52 +01002055 struct afs_call *call;
David Howellse49c7b22020-04-10 20:51:51 +01002056 const struct afs_acl *acl = op->acl;
Joe Gorseb10494a2019-04-25 14:26:52 +01002057 size_t size;
2058 __be32 *bp;
2059
2060 _enter(",%x,{%llx:%llu},,",
David Howellse49c7b22020-04-10 20:51:51 +01002061 key_serial(op->key), vp->fid.vid, vp->fid.vnode);
Joe Gorseb10494a2019-04-25 14:26:52 +01002062
2063 size = round_up(acl->size, 4);
David Howellse49c7b22020-04-10 20:51:51 +01002064 call = afs_alloc_flat_call(op->net, &afs_RXFSStoreACL,
Joe Gorseb10494a2019-04-25 14:26:52 +01002065 5 * 4 + size, (21 + 6) * 4);
David Howellse49c7b22020-04-10 20:51:51 +01002066 if (!call)
2067 return afs_op_nomem(op);
Joe Gorseb10494a2019-04-25 14:26:52 +01002068
2069 /* marshall the parameters */
2070 bp = call->request;
2071 bp[0] = htonl(FSSTOREACL);
David Howellse49c7b22020-04-10 20:51:51 +01002072 bp[1] = htonl(vp->fid.vid);
2073 bp[2] = htonl(vp->fid.vnode);
2074 bp[3] = htonl(vp->fid.unique);
Joe Gorseb10494a2019-04-25 14:26:52 +01002075 bp[4] = htonl(acl->size);
2076 memcpy(&bp[5], acl->data, acl->size);
2077 if (acl->size != size)
2078 memset((void *)&bp[5] + acl->size, 0, size - acl->size);
2079
David Howellse49c7b22020-04-10 20:51:51 +01002080 trace_afs_make_fs_call(call, &vp->fid);
2081 afs_make_op_call(op, call, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082}