blob: 5e3027f213909dc6864834c250d324c1ffae9877 [file] [log] [blame]
David Howells08e0e7c2007-04-26 15:55:03 -07001/* AFS File Server client stubs
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
David Howells08e0e7c2007-04-26 15:55:03 -07003 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/sched.h>
David Howells08e0e7c2007-04-26 15:55:03 -070015#include <linux/circ_buf.h>
Jeff Laytona01179e2017-12-11 06:35:11 -050016#include <linux/iversion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070018#include "afs_fs.h"
David Howellsdd9fbcb2018-04-06 14:17:24 +010019#include "xdr_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
David Howells025db802017-11-02 15:27:51 +000021static const struct afs_fid afs_zero_fid;
22
David Howellsd2ddc772017-11-02 15:27:50 +000023static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
David Howellsc435ee32017-11-02 15:27:49 +000024{
David Howellsd2ddc772017-11-02 15:27:50 +000025 call->cbi = afs_get_cb_interest(cbi);
David Howellsc435ee32017-11-02 15:27:49 +000026}
27
David Howells6db3ac32017-03-16 16:27:44 +000028/*
David Howells260a9802007-04-26 15:59:35 -070029 * decode an AFSFid block
30 */
31static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
32{
33 const __be32 *bp = *_bp;
34
35 fid->vid = ntohl(*bp++);
36 fid->vnode = ntohl(*bp++);
37 fid->unique = ntohl(*bp++);
38 *_bp = bp;
39}
40
41/*
David Howells888b3382018-04-06 14:17:24 +010042 * Dump a bad file status record.
43 */
44static void xdr_dump_bad(const __be32 *bp)
45{
46 __be32 x[4];
47 int i;
48
49 pr_notice("AFS XDR: Bad status record\n");
50 for (i = 0; i < 5 * 4 * 4; i += 16) {
51 memcpy(x, bp, 16);
52 bp += 4;
53 pr_notice("%03x: %08x %08x %08x %08x\n",
54 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
55 }
56
57 memcpy(x, bp, 4);
58 pr_notice("0x50: %08x\n", ntohl(x[0]));
59}
60
61/*
David Howellsdd9fbcb2018-04-06 14:17:24 +010062 * Update the core inode struct from a returned status record.
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 */
David Howellsdd9fbcb2018-04-06 14:17:24 +010064void afs_update_inode_from_status(struct afs_vnode *vnode,
65 struct afs_file_status *status,
66 const afs_dataversion_t *expected_version,
67 u8 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -070068{
Deepa Dinamani95582b02018-05-08 19:36:02 -070069 struct timespec64 t;
David Howells08e0e7c2007-04-26 15:55:03 -070070 umode_t mode;
David Howells08e0e7c2007-04-26 15:55:03 -070071
David Howellsdd9fbcb2018-04-06 14:17:24 +010072 t.tv_sec = status->mtime_client;
73 t.tv_nsec = 0;
74 vnode->vfs_inode.i_ctime = t;
75 vnode->vfs_inode.i_mtime = t;
76 vnode->vfs_inode.i_atime = t;
David Howellsc435ee32017-11-02 15:27:49 +000077
David Howellsdd9fbcb2018-04-06 14:17:24 +010078 if (flags & (AFS_VNODE_META_CHANGED | AFS_VNODE_NOT_YET_SET)) {
79 vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner);
80 vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group);
81 set_nlink(&vnode->vfs_inode, status->nlink);
David Howells08e0e7c2007-04-26 15:55:03 -070082
David Howellsdd9fbcb2018-04-06 14:17:24 +010083 mode = vnode->vfs_inode.i_mode;
84 mode &= ~S_IALLUGO;
85 mode |= status->mode;
86 barrier();
87 vnode->vfs_inode.i_mode = mode;
David Howells888b3382018-04-06 14:17:24 +010088 }
89
David Howellsdd9fbcb2018-04-06 14:17:24 +010090 if (!(flags & AFS_VNODE_NOT_YET_SET)) {
91 if (expected_version &&
92 *expected_version != status->data_version) {
David Howells3b6492d2018-10-20 00:57:57 +010093 _debug("vnode modified %llx on {%llx:%llu} [exp %llx]",
David Howellsdd9fbcb2018-04-06 14:17:24 +010094 (unsigned long long) status->data_version,
95 vnode->fid.vid, vnode->fid.vnode,
96 (unsigned long long) *expected_version);
David Howellsa4ff7402018-04-06 14:17:24 +010097 vnode->invalid_before = status->data_version;
David Howellsf3ddee82018-04-06 14:17:25 +010098 if (vnode->status.type == AFS_FTYPE_DIR) {
99 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
100 afs_stat_v(vnode, n_inval);
101 } else {
102 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
103 }
David Howells63a46812018-04-06 14:17:25 +0100104 } else if (vnode->status.type == AFS_FTYPE_DIR) {
105 /* Expected directory change is handled elsewhere so
106 * that we can locally edit the directory and save on a
107 * download.
108 */
109 if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
110 flags &= ~AFS_VNODE_DATA_CHANGED;
David Howells260a9802007-04-26 15:59:35 -0700111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 }
David Howellsc435ee32017-11-02 15:27:49 +0000113
David Howellsdd9fbcb2018-04-06 14:17:24 +0100114 if (flags & (AFS_VNODE_DATA_CHANGED | AFS_VNODE_NOT_YET_SET)) {
115 inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
116 i_size_write(&vnode->vfs_inode, status->size);
117 }
118}
119
120/*
121 * decode an AFSFetchStatus block
122 */
David Howells5f702c82018-04-06 14:17:25 +0100123static int xdr_decode_AFSFetchStatus(struct afs_call *call,
124 const __be32 **_bp,
David Howellsdd9fbcb2018-04-06 14:17:24 +0100125 struct afs_file_status *status,
126 struct afs_vnode *vnode,
127 const afs_dataversion_t *expected_version,
David Howellsf3ddee82018-04-06 14:17:25 +0100128 struct afs_read *read_req)
David Howellsdd9fbcb2018-04-06 14:17:24 +0100129{
130 const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
David Howells684b0f62018-05-10 21:51:47 +0100131 bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
David Howellsdd9fbcb2018-04-06 14:17:24 +0100132 u64 data_version, size;
133 u32 type, abort_code;
134 u8 flags = 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100135
David Howells684b0f62018-05-10 21:51:47 +0100136 abort_code = ntohl(xdr->abort_code);
137
David Howellsdd9fbcb2018-04-06 14:17:24 +0100138 if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
David Howells684b0f62018-05-10 21:51:47 +0100139 if (xdr->if_version == htonl(0) &&
140 abort_code != 0 &&
141 inline_error) {
142 /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
143 * whereby it doesn't set the interface version in the error
144 * case.
145 */
146 status->abort_code = abort_code;
Al Virode52cf92018-06-02 18:08:11 -0400147 return 0;
David Howells684b0f62018-05-10 21:51:47 +0100148 }
149
David Howellsdd9fbcb2018-04-06 14:17:24 +0100150 pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
151 goto bad;
152 }
153
David Howells684b0f62018-05-10 21:51:47 +0100154 if (abort_code != 0 && inline_error) {
155 status->abort_code = abort_code;
Al Virode52cf92018-06-02 18:08:11 -0400156 return 0;
David Howells684b0f62018-05-10 21:51:47 +0100157 }
158
David Howellsdd9fbcb2018-04-06 14:17:24 +0100159 type = ntohl(xdr->type);
David Howellsdd9fbcb2018-04-06 14:17:24 +0100160 switch (type) {
161 case AFS_FTYPE_FILE:
162 case AFS_FTYPE_DIR:
163 case AFS_FTYPE_SYMLINK:
164 if (type != status->type &&
165 vnode &&
166 !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
David Howells3b6492d2018-10-20 00:57:57 +0100167 pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n",
David Howellsdd9fbcb2018-04-06 14:17:24 +0100168 vnode->fid.vid,
169 vnode->fid.vnode,
170 vnode->fid.unique,
171 status->type, type);
172 goto bad;
173 }
174 status->type = type;
175 break;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100176 default:
177 goto bad;
178 }
179
180#define EXTRACT_M(FIELD) \
181 do { \
182 u32 x = ntohl(xdr->FIELD); \
183 if (status->FIELD != x) { \
184 flags |= AFS_VNODE_META_CHANGED; \
185 status->FIELD = x; \
186 } \
187 } while (0)
188
189 EXTRACT_M(nlink);
190 EXTRACT_M(author);
191 EXTRACT_M(owner);
192 EXTRACT_M(caller_access); /* call ticket dependent */
193 EXTRACT_M(anon_access);
194 EXTRACT_M(mode);
195 EXTRACT_M(group);
196
197 status->mtime_client = ntohl(xdr->mtime_client);
198 status->mtime_server = ntohl(xdr->mtime_server);
199 status->lock_count = ntohl(xdr->lock_count);
200
201 size = (u64)ntohl(xdr->size_lo);
202 size |= (u64)ntohl(xdr->size_hi) << 32;
David Howells63a46812018-04-06 14:17:25 +0100203 status->size = size;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100204
205 data_version = (u64)ntohl(xdr->data_version_lo);
206 data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
207 if (data_version != status->data_version) {
208 status->data_version = data_version;
209 flags |= AFS_VNODE_DATA_CHANGED;
210 }
David Howellsf3ddee82018-04-06 14:17:25 +0100211
212 if (read_req) {
213 read_req->data_version = data_version;
214 read_req->file_size = size;
215 }
David Howellsdd9fbcb2018-04-06 14:17:24 +0100216
217 *_bp = (const void *)*_bp + sizeof(*xdr);
218
219 if (vnode) {
220 if (test_bit(AFS_VNODE_UNSET, &vnode->flags))
221 flags |= AFS_VNODE_NOT_YET_SET;
222 afs_update_inode_from_status(vnode, status, expected_version,
223 flags);
224 }
225
David Howellsc875c762018-05-23 11:32:06 +0100226 return 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100227
228bad:
229 xdr_dump_bad(*_bp);
David Howells160cb952018-10-20 00:57:56 +0100230 return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
David Howellsc875c762018-05-23 11:32:06 +0100231}
232
233/*
234 * Decode the file status. We need to lock the target vnode if we're going to
235 * update its status so that stat() sees the attributes update atomically.
236 */
237static int afs_decode_status(struct afs_call *call,
238 const __be32 **_bp,
239 struct afs_file_status *status,
240 struct afs_vnode *vnode,
241 const afs_dataversion_t *expected_version,
242 struct afs_read *read_req)
243{
244 int ret;
245
246 if (!vnode)
247 return xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
248 expected_version, read_req);
249
250 write_seqlock(&vnode->cb_lock);
251 ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
252 expected_version, read_req);
253 write_sequnlock(&vnode->cb_lock);
254 return ret;
David Howellsec268152007-04-26 15:49:28 -0700255}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257/*
David Howells08e0e7c2007-04-26 15:55:03 -0700258 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 */
David Howellsc435ee32017-11-02 15:27:49 +0000260static void xdr_decode_AFSCallBack(struct afs_call *call,
261 struct afs_vnode *vnode,
262 const __be32 **_bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263{
David Howellsd2ddc772017-11-02 15:27:50 +0000264 struct afs_cb_interest *old, *cbi = call->cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700265 const __be32 *bp = *_bp;
David Howellsc435ee32017-11-02 15:27:49 +0000266 u32 cb_expiry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
David Howellsc435ee32017-11-02 15:27:49 +0000268 write_seqlock(&vnode->cb_lock);
269
David Howells68251f02018-05-12 22:31:33 +0100270 if (call->cb_break == afs_cb_break_sum(vnode, cbi)) {
David Howellsc435ee32017-11-02 15:27:49 +0000271 vnode->cb_version = ntohl(*bp++);
272 cb_expiry = ntohl(*bp++);
273 vnode->cb_type = ntohl(*bp++);
274 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
David Howellsd2ddc772017-11-02 15:27:50 +0000275 old = vnode->cb_interest;
276 if (old != call->cbi) {
277 vnode->cb_interest = cbi;
278 cbi = old;
279 }
David Howellsc435ee32017-11-02 15:27:49 +0000280 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
281 } else {
282 bp += 3;
283 }
284
285 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +0000286 call->cbi = cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700287 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700288}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
David Howells260a9802007-04-26 15:59:35 -0700290static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
291 struct afs_callback *cb)
292{
293 const __be32 *bp = *_bp;
294
295 cb->version = ntohl(*bp++);
296 cb->expiry = ntohl(*bp++);
297 cb->type = ntohl(*bp++);
298 *_bp = bp;
299}
300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301/*
David Howells08e0e7c2007-04-26 15:55:03 -0700302 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 */
David Howells08e0e7c2007-04-26 15:55:03 -0700304static void xdr_decode_AFSVolSync(const __be32 **_bp,
305 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306{
David Howells08e0e7c2007-04-26 15:55:03 -0700307 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
David Howells08e0e7c2007-04-26 15:55:03 -0700309 volsync->creation = ntohl(*bp++);
310 bp++; /* spare2 */
311 bp++; /* spare3 */
312 bp++; /* spare4 */
313 bp++; /* spare5 */
314 bp++; /* spare6 */
315 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700316}
David Howells08e0e7c2007-04-26 15:55:03 -0700317
318/*
David Howells31143d52007-05-09 02:33:46 -0700319 * encode the requested attributes into an AFSStoreStatus block
320 */
321static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
322{
323 __be32 *bp = *_bp;
324 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
325
326 mask = 0;
327 if (attr->ia_valid & ATTR_MTIME) {
328 mask |= AFS_SET_MTIME;
329 mtime = attr->ia_mtime.tv_sec;
330 }
331
332 if (attr->ia_valid & ATTR_UID) {
333 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800334 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700335 }
336
337 if (attr->ia_valid & ATTR_GID) {
338 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800339 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700340 }
341
342 if (attr->ia_valid & ATTR_MODE) {
343 mask |= AFS_SET_MODE;
344 mode = attr->ia_mode & S_IALLUGO;
345 }
346
347 *bp++ = htonl(mask);
348 *bp++ = htonl(mtime);
349 *bp++ = htonl(owner);
350 *bp++ = htonl(group);
351 *bp++ = htonl(mode);
352 *bp++ = 0; /* segment size */
353 *_bp = bp;
354}
355
356/*
David Howells45222b92007-05-10 22:22:20 -0700357 * decode an AFSFetchVolumeStatus block
358 */
359static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
360 struct afs_volume_status *vs)
361{
362 const __be32 *bp = *_bp;
363
364 vs->vid = ntohl(*bp++);
365 vs->parent_id = ntohl(*bp++);
366 vs->online = ntohl(*bp++);
367 vs->in_service = ntohl(*bp++);
368 vs->blessed = ntohl(*bp++);
369 vs->needs_salvage = ntohl(*bp++);
370 vs->type = ntohl(*bp++);
371 vs->min_quota = ntohl(*bp++);
372 vs->max_quota = ntohl(*bp++);
373 vs->blocks_in_use = ntohl(*bp++);
374 vs->part_blocks_avail = ntohl(*bp++);
375 vs->part_max_blocks = ntohl(*bp++);
376 *_bp = bp;
377}
378
379/*
David Howells08e0e7c2007-04-26 15:55:03 -0700380 * deliver reply data to an FS.FetchStatus
381 */
David Howells5cf9dd52018-04-09 21:12:31 +0100382static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700383{
David Howells97e30432017-11-02 15:27:48 +0000384 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700385 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100386 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700387
David Howellsd0016482016-08-30 20:42:14 +0100388 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100389 if (ret < 0)
390 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700391
David Howells3b6492d2018-10-20 00:57:57 +0100392 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
David Howellsc435ee32017-11-02 15:27:49 +0000393
David Howells08e0e7c2007-04-26 15:55:03 -0700394 /* unmarshall the reply once we've received all of it */
395 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100396 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
397 &call->expected_version, NULL);
398 if (ret < 0)
399 return ret;
David Howellsc435ee32017-11-02 15:27:49 +0000400 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000401 if (call->reply[1])
402 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700403
404 _leave(" = 0 [done]");
405 return 0;
406}
407
408/*
409 * FS.FetchStatus operation type
410 */
David Howells5cf9dd52018-04-09 21:12:31 +0100411static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
412 .name = "FS.FetchStatus(vnode)",
David Howells025db802017-11-02 15:27:51 +0000413 .op = afs_FS_FetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100414 .deliver = afs_deliver_fs_fetch_status_vnode,
David Howells08e0e7c2007-04-26 15:55:03 -0700415 .destructor = afs_flat_call_destructor,
416};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418/*
419 * fetch the status information for a file
420 */
David Howells0c3a5ac2018-04-06 14:17:24 +0100421int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync,
422 bool new_inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
David Howellsd2ddc772017-11-02 15:27:50 +0000424 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700425 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000426 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 __be32 *bp;
428
David Howells3b6492d2018-10-20 00:57:57 +0100429 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000430 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
David Howells5cf9dd52018-04-09 21:12:31 +0100432 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
433 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000434 if (!call) {
435 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700436 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
David Howellsd2ddc772017-11-02 15:27:50 +0000439 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000440 call->reply[0] = vnode;
441 call->reply[1] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +0100442 call->expected_version = new_inode ? 1 : vnode->status.data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
444 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700445 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 bp[0] = htonl(FSFETCHSTATUS);
447 bp[1] = htonl(vnode->fid.vid);
448 bp[2] = htonl(vnode->fid.vnode);
449 bp[3] = htonl(vnode->fid.unique);
450
David Howellsd2ddc772017-11-02 15:27:50 +0000451 call->cb_break = fc->cb_break;
452 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000453 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000454 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700455}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457/*
David Howells08e0e7c2007-04-26 15:55:03 -0700458 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 */
David Howellsd0016482016-08-30 20:42:14 +0100460static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
David Howells97e30432017-11-02 15:27:48 +0000462 struct afs_vnode *vnode = call->reply[0];
463 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700464 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000465 unsigned int size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700467
David Howells12bdcf32018-10-20 00:57:56 +0100468 _enter("{%u,%zu/%llu}",
469 call->unmarshall, iov_iter_count(&call->iter), req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700470
471 switch (call->unmarshall) {
472 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000473 req->actual_len = 0;
David Howells12bdcf32018-10-20 00:57:56 +0100474 req->index = 0;
475 req->offset = req->pos & (PAGE_SIZE - 1);
David Howells08e0e7c2007-04-26 15:55:03 -0700476 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +0100477 if (call->operation_ID == FSFETCHDATA64) {
478 afs_extract_to_tmp64(call);
479 } else {
480 call->tmp_u = htonl(0);
481 afs_extract_to_tmp(call);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700482 }
David Howells08e0e7c2007-04-26 15:55:03 -0700483
David Howellsb9b1f8d2007-05-10 03:15:21 -0700484 /* extract the returned data length */
David Howells12bdcf32018-10-20 00:57:56 +0100485 case 1:
David Howells08e0e7c2007-04-26 15:55:03 -0700486 _debug("extract data length");
David Howells12bdcf32018-10-20 00:57:56 +0100487 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +0100488 if (ret < 0)
489 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700490
David Howells12bdcf32018-10-20 00:57:56 +0100491 req->actual_len = be64_to_cpu(call->tmp64);
David Howells196ee9c2017-01-05 10:38:34 +0000492 _debug("DATA length: %llu", req->actual_len);
David Howells12bdcf32018-10-20 00:57:56 +0100493 req->remain = min(req->len, req->actual_len);
494 if (req->remain == 0)
David Howells196ee9c2017-01-05 10:38:34 +0000495 goto no_more_data;
David Howells12bdcf32018-10-20 00:57:56 +0100496
David Howells08e0e7c2007-04-26 15:55:03 -0700497 call->unmarshall++;
498
David Howells196ee9c2017-01-05 10:38:34 +0000499 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000500 ASSERTCMP(req->index, <, req->nr_pages);
David Howells12bdcf32018-10-20 00:57:56 +0100501 if (req->remain > PAGE_SIZE - req->offset)
502 size = PAGE_SIZE - req->offset;
David Howells196ee9c2017-01-05 10:38:34 +0000503 else
504 size = req->remain;
David Howells12bdcf32018-10-20 00:57:56 +0100505 call->bvec[0].bv_len = size;
506 call->bvec[0].bv_offset = req->offset;
507 call->bvec[0].bv_page = req->pages[req->index];
508 iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
509 ASSERTCMP(size, <=, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000510
David Howells08e0e7c2007-04-26 15:55:03 -0700511 /* extract the returned data */
David Howells12bdcf32018-10-20 00:57:56 +0100512 case 2:
513 _debug("extract data %zu/%llu",
514 iov_iter_count(&call->iter), req->remain);
David Howells196ee9c2017-01-05 10:38:34 +0000515
David Howells12bdcf32018-10-20 00:57:56 +0100516 ret = afs_extract_data(call, true);
David Howells196ee9c2017-01-05 10:38:34 +0000517 if (ret < 0)
518 return ret;
David Howells12bdcf32018-10-20 00:57:56 +0100519 req->remain -= call->bvec[0].bv_len;
520 req->offset += call->bvec[0].bv_len;
521 ASSERTCMP(req->offset, <=, PAGE_SIZE);
522 if (req->offset == PAGE_SIZE) {
523 req->offset = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000524 if (req->page_done)
525 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000526 req->index++;
David Howells12bdcf32018-10-20 00:57:56 +0100527 if (req->remain > 0)
David Howells196ee9c2017-01-05 10:38:34 +0000528 goto begin_page;
David Howells08e0e7c2007-04-26 15:55:03 -0700529 }
David Howells12bdcf32018-10-20 00:57:56 +0100530
531 ASSERTCMP(req->remain, ==, 0);
532 if (req->actual_len <= req->len)
533 goto no_more_data;
David Howells6db3ac32017-03-16 16:27:44 +0000534
535 /* Discard any excess data the server gave us */
David Howells12bdcf32018-10-20 00:57:56 +0100536 iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
537 call->unmarshall = 3;
538 case 3:
539 _debug("extract discard %zu/%llu",
540 iov_iter_count(&call->iter), req->actual_len - req->len);
David Howells6db3ac32017-03-16 16:27:44 +0000541
David Howells12bdcf32018-10-20 00:57:56 +0100542 ret = afs_extract_data(call, true);
David Howells6db3ac32017-03-16 16:27:44 +0000543 if (ret < 0)
544 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700545
David Howells196ee9c2017-01-05 10:38:34 +0000546 no_more_data:
David Howells12bdcf32018-10-20 00:57:56 +0100547 call->unmarshall = 4;
548 afs_extract_to_buf(call, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700549
550 /* extract the metadata */
David Howells12bdcf32018-10-20 00:57:56 +0100551 case 4:
552 ret = afs_extract_data(call, false);
David Howells372ee162016-08-03 14:11:40 +0100553 if (ret < 0)
554 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700555
556 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100557 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
558 &vnode->status.data_version, req);
559 if (ret < 0)
560 return ret;
David Howellsc435ee32017-11-02 15:27:49 +0000561 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000562 if (call->reply[1])
563 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700564
David Howells08e0e7c2007-04-26 15:55:03 -0700565 call->unmarshall++;
566
David Howells12bdcf32018-10-20 00:57:56 +0100567 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700568 break;
569 }
570
David Howells6db3ac32017-03-16 16:27:44 +0000571 for (; req->index < req->nr_pages; req->index++) {
David Howells12bdcf32018-10-20 00:57:56 +0100572 if (req->offset < PAGE_SIZE)
David Howells6db3ac32017-03-16 16:27:44 +0000573 zero_user_segment(req->pages[req->index],
David Howells12bdcf32018-10-20 00:57:56 +0100574 req->offset, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000575 if (req->page_done)
576 req->page_done(call, req);
David Howells12bdcf32018-10-20 00:57:56 +0100577 req->offset = 0;
David Howells416351f2007-05-09 02:33:45 -0700578 }
579
David Howells08e0e7c2007-04-26 15:55:03 -0700580 _leave(" = 0 [done]");
581 return 0;
582}
583
David Howells196ee9c2017-01-05 10:38:34 +0000584static void afs_fetch_data_destructor(struct afs_call *call)
585{
David Howells97e30432017-11-02 15:27:48 +0000586 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000587
588 afs_put_read(req);
589 afs_flat_call_destructor(call);
590}
591
David Howells08e0e7c2007-04-26 15:55:03 -0700592/*
593 * FS.FetchData operation type
594 */
595static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700596 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000597 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700598 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000599 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700600};
601
David Howellsb9b1f8d2007-05-10 03:15:21 -0700602static const struct afs_call_type afs_RXFSFetchData64 = {
603 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000604 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700605 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000606 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700607};
608
609/*
610 * fetch data from a very large file
611 */
David Howellsd2ddc772017-11-02 15:27:50 +0000612static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700613{
David Howellsd2ddc772017-11-02 15:27:50 +0000614 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700615 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000616 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700617 __be32 *bp;
618
619 _enter("");
620
David Howellsf044c882017-11-02 15:27:45 +0000621 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700622 if (!call)
623 return -ENOMEM;
624
David Howellsd2ddc772017-11-02 15:27:50 +0000625 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000626 call->reply[0] = vnode;
627 call->reply[1] = NULL; /* volsync */
628 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100629 call->expected_version = vnode->status.data_version;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700630
631 /* marshall the parameters */
632 bp = call->request;
633 bp[0] = htonl(FSFETCHDATA64);
634 bp[1] = htonl(vnode->fid.vid);
635 bp[2] = htonl(vnode->fid.vnode);
636 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000637 bp[4] = htonl(upper_32_bits(req->pos));
638 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700639 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000640 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700641
David Howellsf3ddee82018-04-06 14:17:25 +0100642 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000643 call->cb_break = fc->cb_break;
644 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000645 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000646 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700647}
648
David Howells08e0e7c2007-04-26 15:55:03 -0700649/*
650 * fetch data from a file
651 */
David Howellsd2ddc772017-11-02 15:27:50 +0000652int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700653{
David Howellsd2ddc772017-11-02 15:27:50 +0000654 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700655 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000656 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 __be32 *bp;
658
David Howells196ee9c2017-01-05 10:38:34 +0000659 if (upper_32_bits(req->pos) ||
660 upper_32_bits(req->len) ||
661 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000662 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700663
David Howells08e0e7c2007-04-26 15:55:03 -0700664 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
David Howellsf044c882017-11-02 15:27:45 +0000666 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700667 if (!call)
668 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
David Howellsd2ddc772017-11-02 15:27:50 +0000670 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000671 call->reply[0] = vnode;
672 call->reply[1] = NULL; /* volsync */
673 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100674 call->expected_version = vnode->status.data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
676 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700677 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700679 bp[1] = htonl(vnode->fid.vid);
680 bp[2] = htonl(vnode->fid.vnode);
681 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000682 bp[4] = htonl(lower_32_bits(req->pos));
683 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
David Howellsf3ddee82018-04-06 14:17:25 +0100685 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000686 call->cb_break = fc->cb_break;
687 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000688 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000689 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700690}
David Howells260a9802007-04-26 15:59:35 -0700691
692/*
693 * deliver reply data to an FS.CreateFile or an FS.MakeDir
694 */
David Howellsd0016482016-08-30 20:42:14 +0100695static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700696{
David Howells97e30432017-11-02 15:27:48 +0000697 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700698 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100699 int ret;
David Howells260a9802007-04-26 15:59:35 -0700700
David Howellsd0016482016-08-30 20:42:14 +0100701 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700702
David Howellsd0016482016-08-30 20:42:14 +0100703 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100704 if (ret < 0)
705 return ret;
David Howells260a9802007-04-26 15:59:35 -0700706
707 /* unmarshall the reply once we've received all of it */
708 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000709 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +0100710 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
711 if (ret < 0)
712 return ret;
713 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
714 &call->expected_version, NULL);
715 if (ret < 0)
716 return ret;
David Howells97e30432017-11-02 15:27:48 +0000717 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
718 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700719
720 _leave(" = 0 [done]");
721 return 0;
722}
723
724/*
725 * FS.CreateFile and FS.MakeDir operation type
726 */
David Howells025db802017-11-02 15:27:51 +0000727static const struct afs_call_type afs_RXFSCreateFile = {
728 .name = "FS.CreateFile",
729 .op = afs_FS_CreateFile,
730 .deliver = afs_deliver_fs_create_vnode,
731 .destructor = afs_flat_call_destructor,
732};
733
734static const struct afs_call_type afs_RXFSMakeDir = {
735 .name = "FS.MakeDir",
736 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700737 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700738 .destructor = afs_flat_call_destructor,
739};
740
741/*
742 * create a file or make a directory
743 */
David Howells8b2a4642017-11-02 15:27:50 +0000744int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700745 const char *name,
746 umode_t mode,
David Howells63a46812018-04-06 14:17:25 +0100747 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -0700748 struct afs_fid *newfid,
749 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000750 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700751{
David Howellsd2ddc772017-11-02 15:27:50 +0000752 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700753 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000754 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700755 size_t namesz, reqsz, padsz;
756 __be32 *bp;
757
758 _enter("");
759
760 namesz = strlen(name);
761 padsz = (4 - (namesz & 3)) & 3;
762 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
763
David Howells025db802017-11-02 15:27:51 +0000764 call = afs_alloc_flat_call(
765 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
766 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700767 if (!call)
768 return -ENOMEM;
769
David Howellsd2ddc772017-11-02 15:27:50 +0000770 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000771 call->reply[0] = vnode;
772 call->reply[1] = newfid;
773 call->reply[2] = newstatus;
774 call->reply[3] = newcb;
David Howells63a46812018-04-06 14:17:25 +0100775 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700776
777 /* marshall the parameters */
778 bp = call->request;
779 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
780 *bp++ = htonl(vnode->fid.vid);
781 *bp++ = htonl(vnode->fid.vnode);
782 *bp++ = htonl(vnode->fid.unique);
783 *bp++ = htonl(namesz);
784 memcpy(bp, name, namesz);
785 bp = (void *) bp + namesz;
786 if (padsz > 0) {
787 memset(bp, 0, padsz);
788 bp = (void *) bp + padsz;
789 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000790 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
791 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700792 *bp++ = 0; /* owner */
793 *bp++ = 0; /* group */
794 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
795 *bp++ = 0; /* segment size */
796
David Howellsd2ddc772017-11-02 15:27:50 +0000797 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000798 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000799 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700800}
801
802/*
803 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
804 */
David Howellsd0016482016-08-30 20:42:14 +0100805static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700806{
David Howells97e30432017-11-02 15:27:48 +0000807 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700808 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100809 int ret;
David Howells260a9802007-04-26 15:59:35 -0700810
David Howellsd0016482016-08-30 20:42:14 +0100811 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700812
David Howellsd0016482016-08-30 20:42:14 +0100813 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100814 if (ret < 0)
815 return ret;
David Howells260a9802007-04-26 15:59:35 -0700816
817 /* unmarshall the reply once we've received all of it */
818 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100819 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
820 &call->expected_version, NULL);
821 if (ret < 0)
822 return ret;
David Howells97e30432017-11-02 15:27:48 +0000823 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700824
825 _leave(" = 0 [done]");
826 return 0;
827}
828
829/*
830 * FS.RemoveDir/FS.RemoveFile operation type
831 */
David Howells025db802017-11-02 15:27:51 +0000832static const struct afs_call_type afs_RXFSRemoveFile = {
833 .name = "FS.RemoveFile",
834 .op = afs_FS_RemoveFile,
835 .deliver = afs_deliver_fs_remove,
836 .destructor = afs_flat_call_destructor,
837};
838
839static const struct afs_call_type afs_RXFSRemoveDir = {
840 .name = "FS.RemoveDir",
841 .op = afs_FS_RemoveDir,
David Howells260a9802007-04-26 15:59:35 -0700842 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700843 .destructor = afs_flat_call_destructor,
844};
845
846/*
847 * remove a file or directory
848 */
David Howells63a46812018-04-06 14:17:25 +0100849int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir,
850 u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700851{
David Howellsd2ddc772017-11-02 15:27:50 +0000852 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700853 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000854 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700855 size_t namesz, reqsz, padsz;
856 __be32 *bp;
857
858 _enter("");
859
860 namesz = strlen(name);
861 padsz = (4 - (namesz & 3)) & 3;
862 reqsz = (5 * 4) + namesz + padsz;
863
David Howells025db802017-11-02 15:27:51 +0000864 call = afs_alloc_flat_call(
865 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
866 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700867 if (!call)
868 return -ENOMEM;
869
David Howellsd2ddc772017-11-02 15:27:50 +0000870 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000871 call->reply[0] = vnode;
David Howells63a46812018-04-06 14:17:25 +0100872 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700873
874 /* marshall the parameters */
875 bp = call->request;
876 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
877 *bp++ = htonl(vnode->fid.vid);
878 *bp++ = htonl(vnode->fid.vnode);
879 *bp++ = htonl(vnode->fid.unique);
880 *bp++ = htonl(namesz);
881 memcpy(bp, name, namesz);
882 bp = (void *) bp + namesz;
883 if (padsz > 0) {
884 memset(bp, 0, padsz);
885 bp = (void *) bp + padsz;
886 }
887
David Howellsd2ddc772017-11-02 15:27:50 +0000888 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000889 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000890 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700891}
892
893/*
894 * deliver reply data to an FS.Link
895 */
David Howellsd0016482016-08-30 20:42:14 +0100896static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700897{
David Howells97e30432017-11-02 15:27:48 +0000898 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700899 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100900 int ret;
David Howells260a9802007-04-26 15:59:35 -0700901
David Howellsd0016482016-08-30 20:42:14 +0100902 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700903
David Howellsd0016482016-08-30 20:42:14 +0100904 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100905 if (ret < 0)
906 return ret;
David Howells260a9802007-04-26 15:59:35 -0700907
908 /* unmarshall the reply once we've received all of it */
909 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100910 ret = afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
911 if (ret < 0)
912 return ret;
913 ret = afs_decode_status(call, &bp, &dvnode->status, dvnode,
914 &call->expected_version, NULL);
915 if (ret < 0)
916 return ret;
David Howells97e30432017-11-02 15:27:48 +0000917 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700918
919 _leave(" = 0 [done]");
920 return 0;
921}
922
923/*
924 * FS.Link operation type
925 */
926static const struct afs_call_type afs_RXFSLink = {
927 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000928 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700929 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700930 .destructor = afs_flat_call_destructor,
931};
932
933/*
934 * make a hard link
935 */
David Howellsd2ddc772017-11-02 15:27:50 +0000936int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
David Howells63a46812018-04-06 14:17:25 +0100937 const char *name, u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700938{
David Howellsd2ddc772017-11-02 15:27:50 +0000939 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700940 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000941 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700942 size_t namesz, reqsz, padsz;
943 __be32 *bp;
944
945 _enter("");
946
947 namesz = strlen(name);
948 padsz = (4 - (namesz & 3)) & 3;
949 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
950
David Howellsf044c882017-11-02 15:27:45 +0000951 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700952 if (!call)
953 return -ENOMEM;
954
David Howellsd2ddc772017-11-02 15:27:50 +0000955 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000956 call->reply[0] = dvnode;
957 call->reply[1] = vnode;
David Howells63a46812018-04-06 14:17:25 +0100958 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700959
960 /* marshall the parameters */
961 bp = call->request;
962 *bp++ = htonl(FSLINK);
963 *bp++ = htonl(dvnode->fid.vid);
964 *bp++ = htonl(dvnode->fid.vnode);
965 *bp++ = htonl(dvnode->fid.unique);
966 *bp++ = htonl(namesz);
967 memcpy(bp, name, namesz);
968 bp = (void *) bp + namesz;
969 if (padsz > 0) {
970 memset(bp, 0, padsz);
971 bp = (void *) bp + padsz;
972 }
973 *bp++ = htonl(vnode->fid.vid);
974 *bp++ = htonl(vnode->fid.vnode);
975 *bp++ = htonl(vnode->fid.unique);
976
David Howellsd2ddc772017-11-02 15:27:50 +0000977 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000978 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000979 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700980}
981
982/*
983 * deliver reply data to an FS.Symlink
984 */
David Howellsd0016482016-08-30 20:42:14 +0100985static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700986{
David Howells97e30432017-11-02 15:27:48 +0000987 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700988 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100989 int ret;
David Howells260a9802007-04-26 15:59:35 -0700990
David Howellsd0016482016-08-30 20:42:14 +0100991 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700992
David Howellsd0016482016-08-30 20:42:14 +0100993 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100994 if (ret < 0)
995 return ret;
David Howells260a9802007-04-26 15:59:35 -0700996
997 /* unmarshall the reply once we've received all of it */
998 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000999 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +01001000 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
1001 if (ret < 0)
1002 return ret;
1003 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1004 &call->expected_version, NULL);
1005 if (ret < 0)
1006 return ret;
David Howells97e30432017-11-02 15:27:48 +00001007 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001008
1009 _leave(" = 0 [done]");
1010 return 0;
1011}
1012
1013/*
1014 * FS.Symlink operation type
1015 */
1016static const struct afs_call_type afs_RXFSSymlink = {
1017 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +00001018 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -07001019 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -07001020 .destructor = afs_flat_call_destructor,
1021};
1022
1023/*
1024 * create a symbolic link
1025 */
David Howells8b2a4642017-11-02 15:27:50 +00001026int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001027 const char *name,
1028 const char *contents,
David Howells63a46812018-04-06 14:17:25 +01001029 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -07001030 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +00001031 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -07001032{
David Howellsd2ddc772017-11-02 15:27:50 +00001033 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001034 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001035 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -07001036 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
1037 __be32 *bp;
1038
1039 _enter("");
1040
1041 namesz = strlen(name);
1042 padsz = (4 - (namesz & 3)) & 3;
1043
1044 c_namesz = strlen(contents);
1045 c_padsz = (4 - (c_namesz & 3)) & 3;
1046
1047 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
1048
David Howellsf044c882017-11-02 15:27:45 +00001049 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -07001050 (3 + 21 + 21 + 6) * 4);
1051 if (!call)
1052 return -ENOMEM;
1053
David Howellsd2ddc772017-11-02 15:27:50 +00001054 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001055 call->reply[0] = vnode;
1056 call->reply[1] = newfid;
1057 call->reply[2] = newstatus;
David Howells63a46812018-04-06 14:17:25 +01001058 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001059
1060 /* marshall the parameters */
1061 bp = call->request;
1062 *bp++ = htonl(FSSYMLINK);
1063 *bp++ = htonl(vnode->fid.vid);
1064 *bp++ = htonl(vnode->fid.vnode);
1065 *bp++ = htonl(vnode->fid.unique);
1066 *bp++ = htonl(namesz);
1067 memcpy(bp, name, namesz);
1068 bp = (void *) bp + namesz;
1069 if (padsz > 0) {
1070 memset(bp, 0, padsz);
1071 bp = (void *) bp + padsz;
1072 }
1073 *bp++ = htonl(c_namesz);
1074 memcpy(bp, contents, c_namesz);
1075 bp = (void *) bp + c_namesz;
1076 if (c_padsz > 0) {
1077 memset(bp, 0, c_padsz);
1078 bp = (void *) bp + c_padsz;
1079 }
Marc Dionneab94f5d2017-03-16 16:27:47 +00001080 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
1081 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -07001082 *bp++ = 0; /* owner */
1083 *bp++ = 0; /* group */
1084 *bp++ = htonl(S_IRWXUGO); /* unix mode */
1085 *bp++ = 0; /* segment size */
1086
David Howellsd2ddc772017-11-02 15:27:50 +00001087 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001088 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001089 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001090}
1091
1092/*
1093 * deliver reply data to an FS.Rename
1094 */
David Howellsd0016482016-08-30 20:42:14 +01001095static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001096{
David Howells97e30432017-11-02 15:27:48 +00001097 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -07001098 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001099 int ret;
David Howells260a9802007-04-26 15:59:35 -07001100
David Howellsd0016482016-08-30 20:42:14 +01001101 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001102
David Howellsd0016482016-08-30 20:42:14 +01001103 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001104 if (ret < 0)
1105 return ret;
David Howells260a9802007-04-26 15:59:35 -07001106
1107 /* unmarshall the reply once we've received all of it */
1108 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001109 ret = afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
1110 &call->expected_version, NULL);
1111 if (ret < 0)
1112 return ret;
1113 if (new_dvnode != orig_dvnode) {
1114 ret = afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
1115 &call->expected_version_2, NULL);
1116 if (ret < 0)
1117 return ret;
1118 }
David Howells97e30432017-11-02 15:27:48 +00001119 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001120
1121 _leave(" = 0 [done]");
1122 return 0;
1123}
1124
1125/*
1126 * FS.Rename operation type
1127 */
1128static const struct afs_call_type afs_RXFSRename = {
1129 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001130 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001131 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001132 .destructor = afs_flat_call_destructor,
1133};
1134
1135/*
1136 * create a symbolic link
1137 */
David Howells8b2a4642017-11-02 15:27:50 +00001138int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001139 const char *orig_name,
1140 struct afs_vnode *new_dvnode,
David Howells63a46812018-04-06 14:17:25 +01001141 const char *new_name,
1142 u64 current_orig_data_version,
1143 u64 current_new_data_version)
David Howells260a9802007-04-26 15:59:35 -07001144{
David Howellsd2ddc772017-11-02 15:27:50 +00001145 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001146 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001147 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001148 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1149 __be32 *bp;
1150
1151 _enter("");
1152
1153 o_namesz = strlen(orig_name);
1154 o_padsz = (4 - (o_namesz & 3)) & 3;
1155
1156 n_namesz = strlen(new_name);
1157 n_padsz = (4 - (n_namesz & 3)) & 3;
1158
1159 reqsz = (4 * 4) +
1160 4 + o_namesz + o_padsz +
1161 (3 * 4) +
1162 4 + n_namesz + n_padsz;
1163
David Howellsf044c882017-11-02 15:27:45 +00001164 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001165 if (!call)
1166 return -ENOMEM;
1167
David Howellsd2ddc772017-11-02 15:27:50 +00001168 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001169 call->reply[0] = orig_dvnode;
1170 call->reply[1] = new_dvnode;
David Howells63a46812018-04-06 14:17:25 +01001171 call->expected_version = current_orig_data_version + 1;
1172 call->expected_version_2 = current_new_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001173
1174 /* marshall the parameters */
1175 bp = call->request;
1176 *bp++ = htonl(FSRENAME);
1177 *bp++ = htonl(orig_dvnode->fid.vid);
1178 *bp++ = htonl(orig_dvnode->fid.vnode);
1179 *bp++ = htonl(orig_dvnode->fid.unique);
1180 *bp++ = htonl(o_namesz);
1181 memcpy(bp, orig_name, o_namesz);
1182 bp = (void *) bp + o_namesz;
1183 if (o_padsz > 0) {
1184 memset(bp, 0, o_padsz);
1185 bp = (void *) bp + o_padsz;
1186 }
1187
1188 *bp++ = htonl(new_dvnode->fid.vid);
1189 *bp++ = htonl(new_dvnode->fid.vnode);
1190 *bp++ = htonl(new_dvnode->fid.unique);
1191 *bp++ = htonl(n_namesz);
1192 memcpy(bp, new_name, n_namesz);
1193 bp = (void *) bp + n_namesz;
1194 if (n_padsz > 0) {
1195 memset(bp, 0, n_padsz);
1196 bp = (void *) bp + n_padsz;
1197 }
1198
David Howellsd2ddc772017-11-02 15:27:50 +00001199 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001200 trace_afs_make_fs_call(call, &orig_dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001201 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001202}
David Howells31143d52007-05-09 02:33:46 -07001203
1204/*
1205 * deliver reply data to an FS.StoreData
1206 */
David Howellsd0016482016-08-30 20:42:14 +01001207static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001208{
David Howells97e30432017-11-02 15:27:48 +00001209 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001210 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001211 int ret;
David Howells31143d52007-05-09 02:33:46 -07001212
David Howellsd0016482016-08-30 20:42:14 +01001213 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001214
David Howellsd0016482016-08-30 20:42:14 +01001215 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001216 if (ret < 0)
1217 return ret;
David Howells31143d52007-05-09 02:33:46 -07001218
1219 /* unmarshall the reply once we've received all of it */
1220 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001221 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1222 &call->expected_version, NULL);
1223 if (ret < 0)
1224 return ret;
David Howells97e30432017-11-02 15:27:48 +00001225 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001226
1227 afs_pages_written_back(vnode, call);
1228
1229 _leave(" = 0 [done]");
1230 return 0;
1231}
1232
1233/*
1234 * FS.StoreData operation type
1235 */
1236static const struct afs_call_type afs_RXFSStoreData = {
1237 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001238 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001239 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001240 .destructor = afs_flat_call_destructor,
1241};
1242
David Howellsb9b1f8d2007-05-10 03:15:21 -07001243static const struct afs_call_type afs_RXFSStoreData64 = {
1244 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001245 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001246 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001247 .destructor = afs_flat_call_destructor,
1248};
1249
1250/*
1251 * store a set of pages to a very large file
1252 */
David Howells8b2a4642017-11-02 15:27:50 +00001253static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001254 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001255 pgoff_t first, pgoff_t last,
1256 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001257 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001258{
David Howells4343d002017-11-02 15:27:52 +00001259 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001260 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001261 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001262 __be32 *bp;
1263
David Howells3b6492d2018-10-20 00:57:57 +01001264 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001265 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001266
David Howellsf044c882017-11-02 15:27:45 +00001267 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001268 (4 + 6 + 3 * 2) * 4,
1269 (21 + 6) * 4);
1270 if (!call)
1271 return -ENOMEM;
1272
David Howells4343d002017-11-02 15:27:52 +00001273 call->key = fc->key;
1274 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001275 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001276 call->first = first;
1277 call->last = last;
1278 call->first_offset = offset;
1279 call->last_to = to;
1280 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001281 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001282
1283 /* marshall the parameters */
1284 bp = call->request;
1285 *bp++ = htonl(FSSTOREDATA64);
1286 *bp++ = htonl(vnode->fid.vid);
1287 *bp++ = htonl(vnode->fid.vnode);
1288 *bp++ = htonl(vnode->fid.unique);
1289
Marc Dionneab94f5d2017-03-16 16:27:47 +00001290 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1291 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001292 *bp++ = 0; /* owner */
1293 *bp++ = 0; /* group */
1294 *bp++ = 0; /* unix mode */
1295 *bp++ = 0; /* segment size */
1296
1297 *bp++ = htonl(pos >> 32);
1298 *bp++ = htonl((u32) pos);
1299 *bp++ = htonl(size >> 32);
1300 *bp++ = htonl((u32) size);
1301 *bp++ = htonl(i_size >> 32);
1302 *bp++ = htonl((u32) i_size);
1303
David Howells025db802017-11-02 15:27:51 +00001304 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001305 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001306}
1307
David Howells31143d52007-05-09 02:33:46 -07001308/*
1309 * store a set of pages
1310 */
David Howells4343d002017-11-02 15:27:52 +00001311int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001312 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001313 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001314{
David Howells4343d002017-11-02 15:27:52 +00001315 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001316 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001317 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001318 loff_t size, pos, i_size;
1319 __be32 *bp;
1320
David Howells3b6492d2018-10-20 00:57:57 +01001321 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001322 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001323
David Howells146a1192017-03-16 16:27:47 +00001324 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001325 if (first != last)
1326 size += (loff_t)(last - first) << PAGE_SHIFT;
1327 pos = (loff_t)first << PAGE_SHIFT;
1328 pos += offset;
1329
1330 i_size = i_size_read(&vnode->vfs_inode);
1331 if (pos + size > i_size)
1332 i_size = size + pos;
1333
1334 _debug("size %llx, at %llx, i_size %llx",
1335 (unsigned long long) size, (unsigned long long) pos,
1336 (unsigned long long) i_size);
1337
David Howellsb9b1f8d2007-05-10 03:15:21 -07001338 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001339 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001340 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001341
David Howellsf044c882017-11-02 15:27:45 +00001342 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001343 (4 + 6 + 3) * 4,
1344 (21 + 6) * 4);
1345 if (!call)
1346 return -ENOMEM;
1347
David Howells4343d002017-11-02 15:27:52 +00001348 call->key = fc->key;
1349 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001350 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001351 call->first = first;
1352 call->last = last;
1353 call->first_offset = offset;
1354 call->last_to = to;
1355 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001356 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001357
1358 /* marshall the parameters */
1359 bp = call->request;
1360 *bp++ = htonl(FSSTOREDATA);
1361 *bp++ = htonl(vnode->fid.vid);
1362 *bp++ = htonl(vnode->fid.vnode);
1363 *bp++ = htonl(vnode->fid.unique);
1364
Marc Dionneab94f5d2017-03-16 16:27:47 +00001365 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1366 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001367 *bp++ = 0; /* owner */
1368 *bp++ = 0; /* group */
1369 *bp++ = 0; /* unix mode */
1370 *bp++ = 0; /* segment size */
1371
1372 *bp++ = htonl(pos);
1373 *bp++ = htonl(size);
1374 *bp++ = htonl(i_size);
1375
David Howellsd2ddc772017-11-02 15:27:50 +00001376 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001377 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001378 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001379}
1380
1381/*
1382 * deliver reply data to an FS.StoreStatus
1383 */
David Howellsd0016482016-08-30 20:42:14 +01001384static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001385{
David Howells97e30432017-11-02 15:27:48 +00001386 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001387 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001388 int ret;
David Howells31143d52007-05-09 02:33:46 -07001389
David Howellsd0016482016-08-30 20:42:14 +01001390 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001391
David Howellsd0016482016-08-30 20:42:14 +01001392 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001393 if (ret < 0)
1394 return ret;
David Howells31143d52007-05-09 02:33:46 -07001395
1396 /* unmarshall the reply once we've received all of it */
David Howells31143d52007-05-09 02:33:46 -07001397 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001398 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1399 &call->expected_version, NULL);
1400 if (ret < 0)
1401 return ret;
David Howells97e30432017-11-02 15:27:48 +00001402 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001403
1404 _leave(" = 0 [done]");
1405 return 0;
1406}
1407
1408/*
1409 * FS.StoreStatus operation type
1410 */
1411static const struct afs_call_type afs_RXFSStoreStatus = {
1412 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001413 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001414 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001415 .destructor = afs_flat_call_destructor,
1416};
1417
1418static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1419 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001420 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001421 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001422 .destructor = afs_flat_call_destructor,
1423};
1424
David Howellsb9b1f8d2007-05-10 03:15:21 -07001425static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1426 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001427 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001428 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001429 .destructor = afs_flat_call_destructor,
1430};
1431
1432/*
1433 * set the attributes on a very large file, using FS.StoreData rather than
1434 * FS.StoreStatus so as to alter the file size also
1435 */
David Howellsd2ddc772017-11-02 15:27:50 +00001436static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001437{
David Howellsd2ddc772017-11-02 15:27:50 +00001438 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001439 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001440 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001441 __be32 *bp;
1442
David Howells3b6492d2018-10-20 00:57:57 +01001443 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001444 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001445
1446 ASSERT(attr->ia_valid & ATTR_SIZE);
1447
David Howellsf044c882017-11-02 15:27:45 +00001448 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001449 (4 + 6 + 3 * 2) * 4,
1450 (21 + 6) * 4);
1451 if (!call)
1452 return -ENOMEM;
1453
David Howellsd2ddc772017-11-02 15:27:50 +00001454 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001455 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001456 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001457
1458 /* marshall the parameters */
1459 bp = call->request;
1460 *bp++ = htonl(FSSTOREDATA64);
1461 *bp++ = htonl(vnode->fid.vid);
1462 *bp++ = htonl(vnode->fid.vnode);
1463 *bp++ = htonl(vnode->fid.unique);
1464
1465 xdr_encode_AFS_StoreStatus(&bp, attr);
1466
1467 *bp++ = 0; /* position of start of write */
1468 *bp++ = 0;
1469 *bp++ = 0; /* size of write */
1470 *bp++ = 0;
1471 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1472 *bp++ = htonl((u32) attr->ia_size);
1473
David Howellsd2ddc772017-11-02 15:27:50 +00001474 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001475 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001476 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001477}
1478
David Howells31143d52007-05-09 02:33:46 -07001479/*
1480 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1481 * so as to alter the file size also
1482 */
David Howellsd2ddc772017-11-02 15:27:50 +00001483static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001484{
David Howellsd2ddc772017-11-02 15:27:50 +00001485 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001486 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001487 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001488 __be32 *bp;
1489
David Howells3b6492d2018-10-20 00:57:57 +01001490 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001491 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001492
1493 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001494 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001495 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001496
David Howellsf044c882017-11-02 15:27:45 +00001497 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001498 (4 + 6 + 3) * 4,
1499 (21 + 6) * 4);
1500 if (!call)
1501 return -ENOMEM;
1502
David Howellsd2ddc772017-11-02 15:27:50 +00001503 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001504 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001505 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001506
1507 /* marshall the parameters */
1508 bp = call->request;
1509 *bp++ = htonl(FSSTOREDATA);
1510 *bp++ = htonl(vnode->fid.vid);
1511 *bp++ = htonl(vnode->fid.vnode);
1512 *bp++ = htonl(vnode->fid.unique);
1513
1514 xdr_encode_AFS_StoreStatus(&bp, attr);
1515
1516 *bp++ = 0; /* position of start of write */
1517 *bp++ = 0; /* size of write */
1518 *bp++ = htonl(attr->ia_size); /* new file length */
1519
David Howellsd2ddc772017-11-02 15:27:50 +00001520 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001521 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001522 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001523}
1524
1525/*
1526 * set the attributes on a file, using FS.StoreData if there's a change in file
1527 * size, and FS.StoreStatus otherwise
1528 */
David Howellsd2ddc772017-11-02 15:27:50 +00001529int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001530{
David Howellsd2ddc772017-11-02 15:27:50 +00001531 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001532 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001533 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001534 __be32 *bp;
1535
1536 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001537 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001538
David Howells3b6492d2018-10-20 00:57:57 +01001539 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001540 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001541
David Howellsf044c882017-11-02 15:27:45 +00001542 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001543 (4 + 6) * 4,
1544 (21 + 6) * 4);
1545 if (!call)
1546 return -ENOMEM;
1547
David Howellsd2ddc772017-11-02 15:27:50 +00001548 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001549 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001550 call->expected_version = vnode->status.data_version;
David Howells31143d52007-05-09 02:33:46 -07001551
1552 /* marshall the parameters */
1553 bp = call->request;
1554 *bp++ = htonl(FSSTORESTATUS);
1555 *bp++ = htonl(vnode->fid.vid);
1556 *bp++ = htonl(vnode->fid.vnode);
1557 *bp++ = htonl(vnode->fid.unique);
1558
1559 xdr_encode_AFS_StoreStatus(&bp, attr);
1560
David Howellsd2ddc772017-11-02 15:27:50 +00001561 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001562 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001563 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001564}
David Howells45222b92007-05-10 22:22:20 -07001565
1566/*
1567 * deliver reply data to an FS.GetVolumeStatus
1568 */
David Howellsd0016482016-08-30 20:42:14 +01001569static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001570{
1571 const __be32 *bp;
1572 char *p;
David Howells12bdcf32018-10-20 00:57:56 +01001573 u32 size;
David Howells45222b92007-05-10 22:22:20 -07001574 int ret;
1575
David Howellsd0016482016-08-30 20:42:14 +01001576 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001577
1578 switch (call->unmarshall) {
1579 case 0:
David Howells45222b92007-05-10 22:22:20 -07001580 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001581 afs_extract_to_buf(call, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001582
1583 /* extract the returned status record */
1584 case 1:
1585 _debug("extract status");
David Howells12bdcf32018-10-20 00:57:56 +01001586 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001587 if (ret < 0)
1588 return ret;
David Howells45222b92007-05-10 22:22:20 -07001589
1590 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001591 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001592 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001593 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001594
1595 /* extract the volume name length */
1596 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001597 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001598 if (ret < 0)
1599 return ret;
David Howells45222b92007-05-10 22:22:20 -07001600
1601 call->count = ntohl(call->tmp);
1602 _debug("volname length: %u", call->count);
1603 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001604 return afs_protocol_error(call, -EBADMSG,
1605 afs_eproto_volname_len);
David Howells12bdcf32018-10-20 00:57:56 +01001606 size = (call->count + 3) & ~3; /* It's padded */
1607 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001608 call->unmarshall++;
1609
1610 /* extract the volume name */
1611 case 3:
1612 _debug("extract volname");
David Howells12bdcf32018-10-20 00:57:56 +01001613 ret = afs_extract_data(call, true);
1614 if (ret < 0)
1615 return ret;
David Howells45222b92007-05-10 22:22:20 -07001616
David Howells97e30432017-11-02 15:27:48 +00001617 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001618 p[call->count] = 0;
1619 _debug("volname '%s'", p);
David Howells12bdcf32018-10-20 00:57:56 +01001620 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001621 call->unmarshall++;
1622
David Howells45222b92007-05-10 22:22:20 -07001623 /* extract the offline message length */
David Howells12bdcf32018-10-20 00:57:56 +01001624 case 4:
1625 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001626 if (ret < 0)
1627 return ret;
David Howells45222b92007-05-10 22:22:20 -07001628
1629 call->count = ntohl(call->tmp);
1630 _debug("offline msg length: %u", call->count);
1631 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001632 return afs_protocol_error(call, -EBADMSG,
1633 afs_eproto_offline_msg_len);
David Howells12bdcf32018-10-20 00:57:56 +01001634 size = (call->count + 3) & ~3; /* It's padded */
1635 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001636 call->unmarshall++;
1637
1638 /* extract the offline message */
David Howells12bdcf32018-10-20 00:57:56 +01001639 case 5:
David Howells45222b92007-05-10 22:22:20 -07001640 _debug("extract offline");
David Howells12bdcf32018-10-20 00:57:56 +01001641 ret = afs_extract_data(call, true);
1642 if (ret < 0)
1643 return ret;
David Howells45222b92007-05-10 22:22:20 -07001644
David Howells97e30432017-11-02 15:27:48 +00001645 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001646 p[call->count] = 0;
1647 _debug("offline '%s'", p);
1648
David Howells12bdcf32018-10-20 00:57:56 +01001649 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001650 call->unmarshall++;
1651
David Howells45222b92007-05-10 22:22:20 -07001652 /* extract the message of the day length */
David Howells12bdcf32018-10-20 00:57:56 +01001653 case 6:
1654 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001655 if (ret < 0)
1656 return ret;
David Howells45222b92007-05-10 22:22:20 -07001657
1658 call->count = ntohl(call->tmp);
1659 _debug("motd length: %u", call->count);
1660 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001661 return afs_protocol_error(call, -EBADMSG,
1662 afs_eproto_motd_len);
David Howells12bdcf32018-10-20 00:57:56 +01001663 size = (call->count + 3) & ~3; /* It's padded */
1664 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001665 call->unmarshall++;
1666
1667 /* extract the message of the day */
David Howells12bdcf32018-10-20 00:57:56 +01001668 case 7:
David Howells45222b92007-05-10 22:22:20 -07001669 _debug("extract motd");
David Howells12bdcf32018-10-20 00:57:56 +01001670 ret = afs_extract_data(call, false);
1671 if (ret < 0)
1672 return ret;
David Howells45222b92007-05-10 22:22:20 -07001673
David Howells97e30432017-11-02 15:27:48 +00001674 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001675 p[call->count] = 0;
1676 _debug("motd '%s'", p);
1677
David Howells45222b92007-05-10 22:22:20 -07001678 call->unmarshall++;
1679
David Howells12bdcf32018-10-20 00:57:56 +01001680 case 8:
David Howells45222b92007-05-10 22:22:20 -07001681 break;
1682 }
1683
David Howells45222b92007-05-10 22:22:20 -07001684 _leave(" = 0 [done]");
1685 return 0;
1686}
1687
1688/*
1689 * destroy an FS.GetVolumeStatus call
1690 */
1691static void afs_get_volume_status_call_destructor(struct afs_call *call)
1692{
David Howells97e30432017-11-02 15:27:48 +00001693 kfree(call->reply[2]);
1694 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001695 afs_flat_call_destructor(call);
1696}
1697
1698/*
1699 * FS.GetVolumeStatus operation type
1700 */
1701static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1702 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001703 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001704 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001705 .destructor = afs_get_volume_status_call_destructor,
1706};
1707
1708/*
1709 * fetch the status of a volume
1710 */
David Howells8b2a4642017-11-02 15:27:50 +00001711int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001712 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001713{
David Howellsd2ddc772017-11-02 15:27:50 +00001714 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001715 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001716 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001717 __be32 *bp;
1718 void *tmpbuf;
1719
1720 _enter("");
1721
1722 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1723 if (!tmpbuf)
1724 return -ENOMEM;
1725
David Howellsf044c882017-11-02 15:27:45 +00001726 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001727 if (!call) {
1728 kfree(tmpbuf);
1729 return -ENOMEM;
1730 }
1731
David Howellsd2ddc772017-11-02 15:27:50 +00001732 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001733 call->reply[0] = vnode;
1734 call->reply[1] = vs;
1735 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001736
1737 /* marshall the parameters */
1738 bp = call->request;
1739 bp[0] = htonl(FSGETVOLUMESTATUS);
1740 bp[1] = htonl(vnode->fid.vid);
1741
David Howellsd2ddc772017-11-02 15:27:50 +00001742 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001743 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001744 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells45222b92007-05-10 22:22:20 -07001745}
David Howellse8d6c552007-07-15 23:40:12 -07001746
1747/*
1748 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1749 */
David Howellsd0016482016-08-30 20:42:14 +01001750static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001751{
1752 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001753 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001754
David Howellsd0016482016-08-30 20:42:14 +01001755 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001756
David Howellsd0016482016-08-30 20:42:14 +01001757 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001758 if (ret < 0)
1759 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001760
1761 /* unmarshall the reply once we've received all of it */
1762 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001763 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001764
1765 _leave(" = 0 [done]");
1766 return 0;
1767}
1768
1769/*
1770 * FS.SetLock operation type
1771 */
1772static const struct afs_call_type afs_RXFSSetLock = {
1773 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001774 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001775 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001776 .destructor = afs_flat_call_destructor,
1777};
1778
1779/*
1780 * FS.ExtendLock operation type
1781 */
1782static const struct afs_call_type afs_RXFSExtendLock = {
1783 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001784 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001785 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001786 .destructor = afs_flat_call_destructor,
1787};
1788
1789/*
1790 * FS.ReleaseLock operation type
1791 */
1792static const struct afs_call_type afs_RXFSReleaseLock = {
1793 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001794 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001795 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001796 .destructor = afs_flat_call_destructor,
1797};
1798
1799/*
David Howellsd2ddc772017-11-02 15:27:50 +00001800 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001801 */
David Howellsd2ddc772017-11-02 15:27:50 +00001802int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001803{
David Howellsd2ddc772017-11-02 15:27:50 +00001804 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001805 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001806 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001807 __be32 *bp;
1808
1809 _enter("");
1810
David Howellsf044c882017-11-02 15:27:45 +00001811 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001812 if (!call)
1813 return -ENOMEM;
1814
David Howellsd2ddc772017-11-02 15:27:50 +00001815 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001816 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001817
1818 /* marshall the parameters */
1819 bp = call->request;
1820 *bp++ = htonl(FSSETLOCK);
1821 *bp++ = htonl(vnode->fid.vid);
1822 *bp++ = htonl(vnode->fid.vnode);
1823 *bp++ = htonl(vnode->fid.unique);
1824 *bp++ = htonl(type);
1825
David Howellsd2ddc772017-11-02 15:27:50 +00001826 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001827 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001828 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001829}
1830
1831/*
1832 * extend a lock on a file
1833 */
David Howellsd2ddc772017-11-02 15:27:50 +00001834int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001835{
David Howellsd2ddc772017-11-02 15:27:50 +00001836 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001837 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001838 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001839 __be32 *bp;
1840
1841 _enter("");
1842
David Howellsf044c882017-11-02 15:27:45 +00001843 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001844 if (!call)
1845 return -ENOMEM;
1846
David Howellsd2ddc772017-11-02 15:27:50 +00001847 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001848 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001849
1850 /* marshall the parameters */
1851 bp = call->request;
1852 *bp++ = htonl(FSEXTENDLOCK);
1853 *bp++ = htonl(vnode->fid.vid);
1854 *bp++ = htonl(vnode->fid.vnode);
1855 *bp++ = htonl(vnode->fid.unique);
1856
David Howellsd2ddc772017-11-02 15:27:50 +00001857 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001858 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001859 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001860}
1861
1862/*
1863 * release a lock on a file
1864 */
David Howellsd2ddc772017-11-02 15:27:50 +00001865int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001866{
David Howellsd2ddc772017-11-02 15:27:50 +00001867 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001868 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001869 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001870 __be32 *bp;
1871
1872 _enter("");
1873
David Howellsf044c882017-11-02 15:27:45 +00001874 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001875 if (!call)
1876 return -ENOMEM;
1877
David Howellsd2ddc772017-11-02 15:27:50 +00001878 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001879 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001880
1881 /* marshall the parameters */
1882 bp = call->request;
1883 *bp++ = htonl(FSRELEASELOCK);
1884 *bp++ = htonl(vnode->fid.vid);
1885 *bp++ = htonl(vnode->fid.vnode);
1886 *bp++ = htonl(vnode->fid.unique);
1887
David Howellsd2ddc772017-11-02 15:27:50 +00001888 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001889 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001890 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsc435ee32017-11-02 15:27:49 +00001891}
1892
1893/*
1894 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1895 */
1896static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1897{
1898 return afs_transfer_reply(call);
1899}
1900
1901/*
1902 * FS.GiveUpAllCallBacks operation type
1903 */
1904static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1905 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001906 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001907 .deliver = afs_deliver_fs_give_up_all_callbacks,
1908 .destructor = afs_flat_call_destructor,
1909};
1910
1911/*
1912 * Flush all the callbacks we have on a server.
1913 */
David Howellsd2ddc772017-11-02 15:27:50 +00001914int afs_fs_give_up_all_callbacks(struct afs_net *net,
1915 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001916 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001917 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001918{
1919 struct afs_call *call;
1920 __be32 *bp;
1921
1922 _enter("");
1923
David Howellsd2ddc772017-11-02 15:27:50 +00001924 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001925 if (!call)
1926 return -ENOMEM;
1927
1928 call->key = key;
1929
1930 /* marshall the parameters */
1931 bp = call->request;
1932 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1933
1934 /* Can't take a ref on server */
David Howellsd2ddc772017-11-02 15:27:50 +00001935 return afs_make_call(ac, call, GFP_NOFS, false);
1936}
1937
1938/*
1939 * Deliver reply data to an FS.GetCapabilities operation.
1940 */
1941static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1942{
1943 u32 count;
1944 int ret;
1945
David Howells12bdcf32018-10-20 00:57:56 +01001946 _enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter));
David Howellsd2ddc772017-11-02 15:27:50 +00001947
David Howellsd2ddc772017-11-02 15:27:50 +00001948 switch (call->unmarshall) {
1949 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01001950 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00001951 call->unmarshall++;
1952
1953 /* Extract the capabilities word count */
1954 case 1:
David Howells12bdcf32018-10-20 00:57:56 +01001955 ret = afs_extract_data(call, true);
David Howellsd2ddc772017-11-02 15:27:50 +00001956 if (ret < 0)
1957 return ret;
1958
1959 count = ntohl(call->tmp);
1960
1961 call->count = count;
1962 call->count2 = count;
David Howells12bdcf32018-10-20 00:57:56 +01001963 iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
David Howellsd2ddc772017-11-02 15:27:50 +00001964 call->unmarshall++;
1965
1966 /* Extract capabilities words */
1967 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001968 ret = afs_extract_data(call, false);
David Howellsd2ddc772017-11-02 15:27:50 +00001969 if (ret < 0)
1970 return ret;
1971
1972 /* TODO: Examine capabilities */
1973
David Howellsd2ddc772017-11-02 15:27:50 +00001974 call->unmarshall++;
1975 break;
1976 }
1977
1978 _leave(" = 0 [done]");
1979 return 0;
1980}
1981
1982/*
1983 * FS.GetCapabilities operation type
1984 */
1985static const struct afs_call_type afs_RXFSGetCapabilities = {
1986 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001987 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001988 .deliver = afs_deliver_fs_get_capabilities,
1989 .destructor = afs_flat_call_destructor,
1990};
1991
1992/*
1993 * Probe a fileserver for the capabilities that it supports. This can
1994 * return up to 196 words.
1995 */
1996int afs_fs_get_capabilities(struct afs_net *net,
1997 struct afs_server *server,
1998 struct afs_addr_cursor *ac,
1999 struct key *key)
2000{
2001 struct afs_call *call;
2002 __be32 *bp;
2003
2004 _enter("");
2005
2006 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
2007 if (!call)
2008 return -ENOMEM;
2009
2010 call->key = key;
2011
2012 /* marshall the parameters */
2013 bp = call->request;
2014 *bp++ = htonl(FSGETCAPABILITIES);
2015
2016 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00002017 trace_afs_make_fs_call(call, NULL);
David Howellsd2ddc772017-11-02 15:27:50 +00002018 return afs_make_call(ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07002019}
David Howells5cf9dd52018-04-09 21:12:31 +01002020
2021/*
2022 * Deliver reply data to an FS.FetchStatus with no vnode.
2023 */
2024static int afs_deliver_fs_fetch_status(struct afs_call *call)
2025{
2026 struct afs_file_status *status = call->reply[1];
2027 struct afs_callback *callback = call->reply[2];
2028 struct afs_volsync *volsync = call->reply[3];
2029 struct afs_vnode *vnode = call->reply[0];
2030 const __be32 *bp;
2031 int ret;
2032
2033 ret = afs_transfer_reply(call);
2034 if (ret < 0)
2035 return ret;
2036
David Howells3b6492d2018-10-20 00:57:57 +01002037 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
David Howells5cf9dd52018-04-09 21:12:31 +01002038
2039 /* unmarshall the reply once we've received all of it */
2040 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01002041 ret = afs_decode_status(call, &bp, status, vnode,
2042 &call->expected_version, NULL);
2043 if (ret < 0)
2044 return ret;
David Howells5cf9dd52018-04-09 21:12:31 +01002045 callback[call->count].version = ntohl(bp[0]);
2046 callback[call->count].expiry = ntohl(bp[1]);
2047 callback[call->count].type = ntohl(bp[2]);
2048 if (vnode)
2049 xdr_decode_AFSCallBack(call, vnode, &bp);
2050 else
2051 bp += 3;
2052 if (volsync)
2053 xdr_decode_AFSVolSync(&bp, volsync);
2054
2055 _leave(" = 0 [done]");
2056 return 0;
2057}
2058
2059/*
2060 * FS.FetchStatus operation type
2061 */
2062static const struct afs_call_type afs_RXFSFetchStatus = {
2063 .name = "FS.FetchStatus",
2064 .op = afs_FS_FetchStatus,
2065 .deliver = afs_deliver_fs_fetch_status,
2066 .destructor = afs_flat_call_destructor,
2067};
2068
2069/*
2070 * Fetch the status information for a fid without needing a vnode handle.
2071 */
2072int afs_fs_fetch_status(struct afs_fs_cursor *fc,
2073 struct afs_net *net,
2074 struct afs_fid *fid,
2075 struct afs_file_status *status,
2076 struct afs_callback *callback,
2077 struct afs_volsync *volsync)
2078{
2079 struct afs_call *call;
2080 __be32 *bp;
2081
David Howells3b6492d2018-10-20 00:57:57 +01002082 _enter(",%x,{%llx:%llu},,",
David Howells5cf9dd52018-04-09 21:12:31 +01002083 key_serial(fc->key), fid->vid, fid->vnode);
2084
2085 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
2086 if (!call) {
2087 fc->ac.error = -ENOMEM;
2088 return -ENOMEM;
2089 }
2090
2091 call->key = fc->key;
2092 call->reply[0] = NULL; /* vnode for fid[0] */
2093 call->reply[1] = status;
2094 call->reply[2] = callback;
2095 call->reply[3] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +01002096 call->expected_version = 1; /* vnode->status.data_version */
David Howells5cf9dd52018-04-09 21:12:31 +01002097
2098 /* marshall the parameters */
2099 bp = call->request;
2100 bp[0] = htonl(FSFETCHSTATUS);
2101 bp[1] = htonl(fid->vid);
2102 bp[2] = htonl(fid->vnode);
2103 bp[3] = htonl(fid->unique);
2104
2105 call->cb_break = fc->cb_break;
2106 afs_use_fs_server(call, fc->cbi);
2107 trace_afs_make_fs_call(call, fid);
2108 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2109}
2110
2111/*
2112 * Deliver reply data to an FS.InlineBulkStatus call
2113 */
2114static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2115{
2116 struct afs_file_status *statuses;
2117 struct afs_callback *callbacks;
2118 struct afs_vnode *vnode = call->reply[0];
2119 const __be32 *bp;
2120 u32 tmp;
2121 int ret;
2122
2123 _enter("{%u}", call->unmarshall);
2124
2125 switch (call->unmarshall) {
2126 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01002127 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002128 call->unmarshall++;
2129
2130 /* Extract the file status count and array in two steps */
2131 case 1:
2132 _debug("extract status count");
David Howells12bdcf32018-10-20 00:57:56 +01002133 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002134 if (ret < 0)
2135 return ret;
2136
2137 tmp = ntohl(call->tmp);
2138 _debug("status count: %u/%u", tmp, call->count2);
2139 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002140 return afs_protocol_error(call, -EBADMSG,
2141 afs_eproto_ibulkst_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002142
2143 call->count = 0;
2144 call->unmarshall++;
2145 more_counts:
David Howells12bdcf32018-10-20 00:57:56 +01002146 afs_extract_to_buf(call, 21 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002147
2148 case 2:
2149 _debug("extract status array %u", call->count);
David Howells12bdcf32018-10-20 00:57:56 +01002150 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002151 if (ret < 0)
2152 return ret;
2153
2154 bp = call->buffer;
2155 statuses = call->reply[1];
David Howells160cb952018-10-20 00:57:56 +01002156 ret = afs_decode_status(call, &bp, &statuses[call->count],
2157 call->count == 0 ? vnode : NULL,
2158 NULL, NULL);
2159 if (ret < 0)
2160 return ret;
David Howells5cf9dd52018-04-09 21:12:31 +01002161
2162 call->count++;
2163 if (call->count < call->count2)
2164 goto more_counts;
2165
2166 call->count = 0;
2167 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01002168 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002169
2170 /* Extract the callback count and array in two steps */
2171 case 3:
2172 _debug("extract CB count");
David Howells12bdcf32018-10-20 00:57:56 +01002173 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002174 if (ret < 0)
2175 return ret;
2176
2177 tmp = ntohl(call->tmp);
2178 _debug("CB count: %u", tmp);
2179 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002180 return afs_protocol_error(call, -EBADMSG,
2181 afs_eproto_ibulkst_cb_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002182 call->count = 0;
2183 call->unmarshall++;
2184 more_cbs:
David Howells12bdcf32018-10-20 00:57:56 +01002185 afs_extract_to_buf(call, 3 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002186
2187 case 4:
2188 _debug("extract CB array");
David Howells12bdcf32018-10-20 00:57:56 +01002189 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002190 if (ret < 0)
2191 return ret;
2192
2193 _debug("unmarshall CB array");
2194 bp = call->buffer;
2195 callbacks = call->reply[2];
2196 callbacks[call->count].version = ntohl(bp[0]);
2197 callbacks[call->count].expiry = ntohl(bp[1]);
2198 callbacks[call->count].type = ntohl(bp[2]);
2199 statuses = call->reply[1];
2200 if (call->count == 0 && vnode && statuses[0].abort_code == 0)
2201 xdr_decode_AFSCallBack(call, vnode, &bp);
2202 call->count++;
2203 if (call->count < call->count2)
2204 goto more_cbs;
2205
David Howells12bdcf32018-10-20 00:57:56 +01002206 afs_extract_to_buf(call, 6 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002207 call->unmarshall++;
2208
2209 case 5:
David Howells12bdcf32018-10-20 00:57:56 +01002210 ret = afs_extract_data(call, false);
David Howells5cf9dd52018-04-09 21:12:31 +01002211 if (ret < 0)
2212 return ret;
2213
2214 bp = call->buffer;
2215 if (call->reply[3])
2216 xdr_decode_AFSVolSync(&bp, call->reply[3]);
2217
David Howells5cf9dd52018-04-09 21:12:31 +01002218 call->unmarshall++;
2219
2220 case 6:
2221 break;
2222 }
2223
2224 _leave(" = 0 [done]");
2225 return 0;
2226}
2227
2228/*
2229 * FS.InlineBulkStatus operation type
2230 */
2231static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2232 .name = "FS.InlineBulkStatus",
2233 .op = afs_FS_InlineBulkStatus,
2234 .deliver = afs_deliver_fs_inline_bulk_status,
2235 .destructor = afs_flat_call_destructor,
2236};
2237
2238/*
2239 * Fetch the status information for up to 50 files
2240 */
2241int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2242 struct afs_net *net,
2243 struct afs_fid *fids,
2244 struct afs_file_status *statuses,
2245 struct afs_callback *callbacks,
2246 unsigned int nr_fids,
2247 struct afs_volsync *volsync)
2248{
2249 struct afs_call *call;
2250 __be32 *bp;
2251 int i;
2252
David Howells3b6492d2018-10-20 00:57:57 +01002253 _enter(",%x,{%llx:%llu},%u",
David Howells5cf9dd52018-04-09 21:12:31 +01002254 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2255
2256 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2257 (2 + nr_fids * 3) * 4,
2258 21 * 4);
2259 if (!call) {
2260 fc->ac.error = -ENOMEM;
2261 return -ENOMEM;
2262 }
2263
2264 call->key = fc->key;
2265 call->reply[0] = NULL; /* vnode for fid[0] */
2266 call->reply[1] = statuses;
2267 call->reply[2] = callbacks;
2268 call->reply[3] = volsync;
2269 call->count2 = nr_fids;
2270
2271 /* marshall the parameters */
2272 bp = call->request;
2273 *bp++ = htonl(FSINLINEBULKSTATUS);
2274 *bp++ = htonl(nr_fids);
2275 for (i = 0; i < nr_fids; i++) {
2276 *bp++ = htonl(fids[i].vid);
2277 *bp++ = htonl(fids[i].vnode);
2278 *bp++ = htonl(fids[i].unique);
2279 }
2280
2281 call->cb_break = fc->cb_break;
2282 afs_use_fs_server(call, fc->cbi);
2283 trace_afs_make_fs_call(call, &fids[0]);
2284 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2285}