blob: 015bbbba08588e82313e22f06d2204344dce2d13 [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"
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
David Howells025db802017-11-02 15:27:51 +000020static const struct afs_fid afs_zero_fid;
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022/*
David Howells6db3ac32017-03-16 16:27:44 +000023 * We need somewhere to discard into in case the server helpfully returns more
24 * than we asked for in FS.FetchData{,64}.
25 */
26static u8 afs_discard_buffer[64];
27
David Howellsd2ddc772017-11-02 15:27:50 +000028static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
David Howellsc435ee32017-11-02 15:27:49 +000029{
David Howellsd2ddc772017-11-02 15:27:50 +000030 call->cbi = afs_get_cb_interest(cbi);
David Howellsc435ee32017-11-02 15:27:49 +000031}
32
David Howells6db3ac32017-03-16 16:27:44 +000033/*
David Howells260a9802007-04-26 15:59:35 -070034 * decode an AFSFid block
35 */
36static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
37{
38 const __be32 *bp = *_bp;
39
40 fid->vid = ntohl(*bp++);
41 fid->vnode = ntohl(*bp++);
42 fid->unique = ntohl(*bp++);
43 *_bp = bp;
44}
45
46/*
David Howells888b3382018-04-06 14:17:24 +010047 * Dump a bad file status record.
48 */
49static void xdr_dump_bad(const __be32 *bp)
50{
51 __be32 x[4];
52 int i;
53
54 pr_notice("AFS XDR: Bad status record\n");
55 for (i = 0; i < 5 * 4 * 4; i += 16) {
56 memcpy(x, bp, 16);
57 bp += 4;
58 pr_notice("%03x: %08x %08x %08x %08x\n",
59 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
60 }
61
62 memcpy(x, bp, 4);
63 pr_notice("0x50: %08x\n", ntohl(x[0]));
64}
65
66/*
David Howells08e0e7c2007-04-26 15:55:03 -070067 * decode an AFSFetchStatus block
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 */
David Howells08e0e7c2007-04-26 15:55:03 -070069static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
David Howells260a9802007-04-26 15:59:35 -070070 struct afs_file_status *status,
David Howells31143d52007-05-09 02:33:46 -070071 struct afs_vnode *vnode,
David Howells0c3a5ac2018-04-06 14:17:24 +010072 const afs_dataversion_t *expected_version,
73 afs_dataversion_t *_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
David Howells08e0e7c2007-04-26 15:55:03 -070075 const __be32 *bp = *_bp;
76 umode_t mode;
David Howells260a9802007-04-26 15:59:35 -070077 u64 data_version, size;
David Howellsc435ee32017-11-02 15:27:49 +000078 bool changed = false;
Eric W. Biedermana0a53862012-02-07 16:20:48 -080079 kuid_t owner;
80 kgid_t group;
David Howells08e0e7c2007-04-26 15:55:03 -070081
David Howellsd2ddc772017-11-02 15:27:50 +000082 if (vnode)
83 write_seqlock(&vnode->cb_lock);
David Howellsc435ee32017-11-02 15:27:49 +000084
David Howells08e0e7c2007-04-26 15:55:03 -070085#define EXTRACT(DST) \
86 do { \
87 u32 x = ntohl(*bp++); \
David Howellsc435ee32017-11-02 15:27:49 +000088 if (DST != x) \
89 changed |= true; \
David Howells08e0e7c2007-04-26 15:55:03 -070090 DST = x; \
91 } while (0)
92
David Howells260a9802007-04-26 15:59:35 -070093 status->if_version = ntohl(*bp++);
94 EXTRACT(status->type);
95 EXTRACT(status->nlink);
96 size = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -070097 data_version = ntohl(*bp++);
David Howells260a9802007-04-26 15:59:35 -070098 EXTRACT(status->author);
Eric W. Biedermana0a53862012-02-07 16:20:48 -080099 owner = make_kuid(&init_user_ns, ntohl(*bp++));
100 changed |= !uid_eq(owner, status->owner);
101 status->owner = owner;
David Howells260a9802007-04-26 15:59:35 -0700102 EXTRACT(status->caller_access); /* call ticket dependent */
103 EXTRACT(status->anon_access);
104 EXTRACT(status->mode);
David Howellsbe080a62017-11-02 15:27:49 +0000105 bp++; /* parent.vnode */
106 bp++; /* parent.unique */
David Howells08e0e7c2007-04-26 15:55:03 -0700107 bp++; /* seg size */
David Howells260a9802007-04-26 15:59:35 -0700108 status->mtime_client = ntohl(*bp++);
109 status->mtime_server = ntohl(*bp++);
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800110 group = make_kgid(&init_user_ns, ntohl(*bp++));
111 changed |= !gid_eq(group, status->group);
112 status->group = group;
David Howells08e0e7c2007-04-26 15:55:03 -0700113 bp++; /* sync counter */
114 data_version |= (u64) ntohl(*bp++) << 32;
David Howellse8d6c552007-07-15 23:40:12 -0700115 EXTRACT(status->lock_count);
David Howells260a9802007-04-26 15:59:35 -0700116 size |= (u64) ntohl(*bp++) << 32;
David Howells5cf9dd52018-04-09 21:12:31 +0100117 EXTRACT(status->abort_code); /* spare 4 */
David Howells08e0e7c2007-04-26 15:55:03 -0700118 *_bp = bp;
119
David Howells888b3382018-04-06 14:17:24 +0100120 switch (status->type) {
121 case AFS_FTYPE_FILE:
122 case AFS_FTYPE_DIR:
123 case AFS_FTYPE_SYMLINK:
124 break;
125 case AFS_FTYPE_INVALID:
126 if (status->abort_code != 0)
127 goto out;
128 /* Fall through */
129 default:
130 xdr_dump_bad(bp - 2);
131 goto out;
132 }
133
David Howells260a9802007-04-26 15:59:35 -0700134 if (size != status->size) {
135 status->size = size;
136 changed |= true;
David Howells08e0e7c2007-04-26 15:55:03 -0700137 }
David Howells260a9802007-04-26 15:59:35 -0700138 status->mode &= S_IALLUGO;
David Howells0c3a5ac2018-04-06 14:17:24 +0100139 if (_version)
140 *_version = data_version;
David Howells08e0e7c2007-04-26 15:55:03 -0700141
142 _debug("vnode time %lx, %lx",
David Howells260a9802007-04-26 15:59:35 -0700143 status->mtime_client, status->mtime_server);
David Howells08e0e7c2007-04-26 15:55:03 -0700144
David Howells260a9802007-04-26 15:59:35 -0700145 if (vnode) {
David Howells260a9802007-04-26 15:59:35 -0700146 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
147 _debug("vnode changed");
148 i_size_write(&vnode->vfs_inode, size);
149 vnode->vfs_inode.i_uid = status->owner;
150 vnode->vfs_inode.i_gid = status->group;
David Howellsd6e43f72011-06-14 00:45:44 +0100151 vnode->vfs_inode.i_generation = vnode->fid.unique;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200152 set_nlink(&vnode->vfs_inode, status->nlink);
David Howells260a9802007-04-26 15:59:35 -0700153
154 mode = vnode->vfs_inode.i_mode;
155 mode &= ~S_IALLUGO;
156 mode |= status->mode;
157 barrier();
158 vnode->vfs_inode.i_mode = mode;
159 }
160
Marc Dionneab94f5d2017-03-16 16:27:47 +0000161 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
David Howells260a9802007-04-26 15:59:35 -0700162 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
163 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
Jeff Laytona01179e2017-12-11 06:35:11 -0500164 inode_set_iversion_raw(&vnode->vfs_inode, data_version);
David Howells260a9802007-04-26 15:59:35 -0700165 }
166
David Howells0c3a5ac2018-04-06 14:17:24 +0100167 status->data_version = data_version;
168 if (expected_version && *expected_version != data_version) {
David Howells260a9802007-04-26 15:59:35 -0700169 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
170 _debug("vnode modified %llx on {%x:%u}",
David S. Millerba3e0e12007-04-26 16:06:22 -0700171 (unsigned long long) data_version,
172 vnode->fid.vid, vnode->fid.vnode);
David Howellsc435ee32017-11-02 15:27:49 +0000173 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
David Howells260a9802007-04-26 15:59:35 -0700174 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 }
David Howellsc435ee32017-11-02 15:27:49 +0000177
David Howells888b3382018-04-06 14:17:24 +0100178out:
David Howellsd2ddc772017-11-02 15:27:50 +0000179 if (vnode)
180 write_sequnlock(&vnode->cb_lock);
David Howellsec268152007-04-26 15:49:28 -0700181}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183/*
David Howells08e0e7c2007-04-26 15:55:03 -0700184 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 */
David Howellsc435ee32017-11-02 15:27:49 +0000186static void xdr_decode_AFSCallBack(struct afs_call *call,
187 struct afs_vnode *vnode,
188 const __be32 **_bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189{
David Howellsd2ddc772017-11-02 15:27:50 +0000190 struct afs_cb_interest *old, *cbi = call->cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700191 const __be32 *bp = *_bp;
David Howellsc435ee32017-11-02 15:27:49 +0000192 u32 cb_expiry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
David Howellsc435ee32017-11-02 15:27:49 +0000194 write_seqlock(&vnode->cb_lock);
195
David Howellsd2ddc772017-11-02 15:27:50 +0000196 if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) {
David Howellsc435ee32017-11-02 15:27:49 +0000197 vnode->cb_version = ntohl(*bp++);
198 cb_expiry = ntohl(*bp++);
199 vnode->cb_type = ntohl(*bp++);
200 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
David Howellsd2ddc772017-11-02 15:27:50 +0000201 old = vnode->cb_interest;
202 if (old != call->cbi) {
203 vnode->cb_interest = cbi;
204 cbi = old;
205 }
David Howellsc435ee32017-11-02 15:27:49 +0000206 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
207 } else {
208 bp += 3;
209 }
210
211 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +0000212 call->cbi = cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700213 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700214}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
David Howells260a9802007-04-26 15:59:35 -0700216static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
217 struct afs_callback *cb)
218{
219 const __be32 *bp = *_bp;
220
221 cb->version = ntohl(*bp++);
222 cb->expiry = ntohl(*bp++);
223 cb->type = ntohl(*bp++);
224 *_bp = bp;
225}
226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227/*
David Howells08e0e7c2007-04-26 15:55:03 -0700228 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 */
David Howells08e0e7c2007-04-26 15:55:03 -0700230static void xdr_decode_AFSVolSync(const __be32 **_bp,
231 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232{
David Howells08e0e7c2007-04-26 15:55:03 -0700233 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
David Howells08e0e7c2007-04-26 15:55:03 -0700235 volsync->creation = ntohl(*bp++);
236 bp++; /* spare2 */
237 bp++; /* spare3 */
238 bp++; /* spare4 */
239 bp++; /* spare5 */
240 bp++; /* spare6 */
241 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700242}
David Howells08e0e7c2007-04-26 15:55:03 -0700243
244/*
David Howells31143d52007-05-09 02:33:46 -0700245 * encode the requested attributes into an AFSStoreStatus block
246 */
247static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
248{
249 __be32 *bp = *_bp;
250 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
251
252 mask = 0;
253 if (attr->ia_valid & ATTR_MTIME) {
254 mask |= AFS_SET_MTIME;
255 mtime = attr->ia_mtime.tv_sec;
256 }
257
258 if (attr->ia_valid & ATTR_UID) {
259 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800260 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700261 }
262
263 if (attr->ia_valid & ATTR_GID) {
264 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800265 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700266 }
267
268 if (attr->ia_valid & ATTR_MODE) {
269 mask |= AFS_SET_MODE;
270 mode = attr->ia_mode & S_IALLUGO;
271 }
272
273 *bp++ = htonl(mask);
274 *bp++ = htonl(mtime);
275 *bp++ = htonl(owner);
276 *bp++ = htonl(group);
277 *bp++ = htonl(mode);
278 *bp++ = 0; /* segment size */
279 *_bp = bp;
280}
281
282/*
David Howells45222b92007-05-10 22:22:20 -0700283 * decode an AFSFetchVolumeStatus block
284 */
285static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
286 struct afs_volume_status *vs)
287{
288 const __be32 *bp = *_bp;
289
290 vs->vid = ntohl(*bp++);
291 vs->parent_id = ntohl(*bp++);
292 vs->online = ntohl(*bp++);
293 vs->in_service = ntohl(*bp++);
294 vs->blessed = ntohl(*bp++);
295 vs->needs_salvage = ntohl(*bp++);
296 vs->type = ntohl(*bp++);
297 vs->min_quota = ntohl(*bp++);
298 vs->max_quota = ntohl(*bp++);
299 vs->blocks_in_use = ntohl(*bp++);
300 vs->part_blocks_avail = ntohl(*bp++);
301 vs->part_max_blocks = ntohl(*bp++);
302 *_bp = bp;
303}
304
305/*
David Howells08e0e7c2007-04-26 15:55:03 -0700306 * deliver reply data to an FS.FetchStatus
307 */
David Howells5cf9dd52018-04-09 21:12:31 +0100308static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700309{
David Howells97e30432017-11-02 15:27:48 +0000310 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700311 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100312 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700313
David Howellsd0016482016-08-30 20:42:14 +0100314 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100315 if (ret < 0)
316 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700317
David Howellsc435ee32017-11-02 15:27:49 +0000318 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
319
David Howells08e0e7c2007-04-26 15:55:03 -0700320 /* unmarshall the reply once we've received all of it */
321 bp = call->buffer;
David Howells0c3a5ac2018-04-06 14:17:24 +0100322 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
323 &call->expected_version, NULL);
David Howellsc435ee32017-11-02 15:27:49 +0000324 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000325 if (call->reply[1])
326 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700327
328 _leave(" = 0 [done]");
329 return 0;
330}
331
332/*
333 * FS.FetchStatus operation type
334 */
David Howells5cf9dd52018-04-09 21:12:31 +0100335static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
336 .name = "FS.FetchStatus(vnode)",
David Howells025db802017-11-02 15:27:51 +0000337 .op = afs_FS_FetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100338 .deliver = afs_deliver_fs_fetch_status_vnode,
David Howells08e0e7c2007-04-26 15:55:03 -0700339 .destructor = afs_flat_call_destructor,
340};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342/*
343 * fetch the status information for a file
344 */
David Howells0c3a5ac2018-04-06 14:17:24 +0100345int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync,
346 bool new_inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
David Howellsd2ddc772017-11-02 15:27:50 +0000348 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700349 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000350 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 __be32 *bp;
352
David Howells416351f2007-05-09 02:33:45 -0700353 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000354 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
David Howells5cf9dd52018-04-09 21:12:31 +0100356 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
357 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000358 if (!call) {
359 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700360 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
David Howellsd2ddc772017-11-02 15:27:50 +0000363 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000364 call->reply[0] = vnode;
365 call->reply[1] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +0100366 call->expected_version = new_inode ? 1 : vnode->status.data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
368 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700369 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 bp[0] = htonl(FSFETCHSTATUS);
371 bp[1] = htonl(vnode->fid.vid);
372 bp[2] = htonl(vnode->fid.vnode);
373 bp[3] = htonl(vnode->fid.unique);
374
David Howellsd2ddc772017-11-02 15:27:50 +0000375 call->cb_break = fc->cb_break;
376 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000377 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000378 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700379}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381/*
David Howells08e0e7c2007-04-26 15:55:03 -0700382 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 */
David Howellsd0016482016-08-30 20:42:14 +0100384static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{
David Howells97e30432017-11-02 15:27:48 +0000386 struct afs_vnode *vnode = call->reply[0];
387 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700388 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000389 unsigned int size;
David Howells08e0e7c2007-04-26 15:55:03 -0700390 void *buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700392
David Howells6a0e3992017-03-16 16:27:46 +0000393 _enter("{%u,%zu/%u;%llu/%llu}",
David Howells196ee9c2017-01-05 10:38:34 +0000394 call->unmarshall, call->offset, call->count,
395 req->remain, req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700396
397 switch (call->unmarshall) {
398 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000399 req->actual_len = 0;
David Howells08e0e7c2007-04-26 15:55:03 -0700400 call->offset = 0;
401 call->unmarshall++;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700402 if (call->operation_ID != FSFETCHDATA64) {
403 call->unmarshall++;
404 goto no_msw;
405 }
David Howells08e0e7c2007-04-26 15:55:03 -0700406
David Howellsb9b1f8d2007-05-10 03:15:21 -0700407 /* extract the upper part of the returned data length of an
408 * FSFETCHDATA64 op (which should always be 0 using this
409 * client) */
David Howells08e0e7c2007-04-26 15:55:03 -0700410 case 1:
David Howellsb9b1f8d2007-05-10 03:15:21 -0700411 _debug("extract data length (MSW)");
David Howellsd0016482016-08-30 20:42:14 +0100412 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100413 if (ret < 0)
414 return ret;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700415
David Howells196ee9c2017-01-05 10:38:34 +0000416 req->actual_len = ntohl(call->tmp);
417 req->actual_len <<= 32;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700418 call->offset = 0;
419 call->unmarshall++;
420
421 no_msw:
422 /* extract the returned data length */
423 case 2:
David Howells08e0e7c2007-04-26 15:55:03 -0700424 _debug("extract data length");
David Howellsd0016482016-08-30 20:42:14 +0100425 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100426 if (ret < 0)
427 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700428
David Howells196ee9c2017-01-05 10:38:34 +0000429 req->actual_len |= ntohl(call->tmp);
430 _debug("DATA length: %llu", req->actual_len);
David Howells196ee9c2017-01-05 10:38:34 +0000431
432 req->remain = req->actual_len;
433 call->offset = req->pos & (PAGE_SIZE - 1);
434 req->index = 0;
435 if (req->actual_len == 0)
436 goto no_more_data;
David Howells08e0e7c2007-04-26 15:55:03 -0700437 call->unmarshall++;
438
David Howells196ee9c2017-01-05 10:38:34 +0000439 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000440 ASSERTCMP(req->index, <, req->nr_pages);
David Howells196ee9c2017-01-05 10:38:34 +0000441 if (req->remain > PAGE_SIZE - call->offset)
442 size = PAGE_SIZE - call->offset;
443 else
444 size = req->remain;
445 call->count = call->offset + size;
446 ASSERTCMP(call->count, <=, PAGE_SIZE);
447 req->remain -= size;
448
David Howells08e0e7c2007-04-26 15:55:03 -0700449 /* extract the returned data */
David Howellsb9b1f8d2007-05-10 03:15:21 -0700450 case 3:
David Howells6a0e3992017-03-16 16:27:46 +0000451 _debug("extract data %llu/%llu %zu/%u",
David Howells196ee9c2017-01-05 10:38:34 +0000452 req->remain, req->actual_len, call->offset, call->count);
453
454 buffer = kmap(req->pages[req->index]);
455 ret = afs_extract_data(call, buffer, call->count, true);
456 kunmap(req->pages[req->index]);
457 if (ret < 0)
458 return ret;
459 if (call->offset == PAGE_SIZE) {
460 if (req->page_done)
461 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000462 req->index++;
David Howells196ee9c2017-01-05 10:38:34 +0000463 if (req->remain > 0) {
David Howells196ee9c2017-01-05 10:38:34 +0000464 call->offset = 0;
David Howellse8e581a2017-03-16 16:27:44 +0000465 if (req->index >= req->nr_pages) {
466 call->unmarshall = 4;
David Howells6db3ac32017-03-16 16:27:44 +0000467 goto begin_discard;
David Howellse8e581a2017-03-16 16:27:44 +0000468 }
David Howells196ee9c2017-01-05 10:38:34 +0000469 goto begin_page;
470 }
David Howells08e0e7c2007-04-26 15:55:03 -0700471 }
David Howells6db3ac32017-03-16 16:27:44 +0000472 goto no_more_data;
473
474 /* Discard any excess data the server gave us */
475 begin_discard:
476 case 4:
David Howells6a0e3992017-03-16 16:27:46 +0000477 size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
David Howells6db3ac32017-03-16 16:27:44 +0000478 call->count = size;
David Howells6a0e3992017-03-16 16:27:46 +0000479 _debug("extract discard %llu/%llu %zu/%u",
David Howells6db3ac32017-03-16 16:27:44 +0000480 req->remain, req->actual_len, call->offset, call->count);
481
482 call->offset = 0;
483 ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
484 req->remain -= call->offset;
485 if (ret < 0)
486 return ret;
487 if (req->remain > 0)
488 goto begin_discard;
David Howells08e0e7c2007-04-26 15:55:03 -0700489
David Howells196ee9c2017-01-05 10:38:34 +0000490 no_more_data:
David Howells08e0e7c2007-04-26 15:55:03 -0700491 call->offset = 0;
David Howells6db3ac32017-03-16 16:27:44 +0000492 call->unmarshall = 5;
David Howells08e0e7c2007-04-26 15:55:03 -0700493
494 /* extract the metadata */
David Howells6db3ac32017-03-16 16:27:44 +0000495 case 5:
David Howellsd0016482016-08-30 20:42:14 +0100496 ret = afs_extract_data(call, call->buffer,
497 (21 + 3 + 6) * 4, false);
David Howells372ee162016-08-03 14:11:40 +0100498 if (ret < 0)
499 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700500
501 bp = call->buffer;
David Howells0c3a5ac2018-04-06 14:17:24 +0100502 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
503 &vnode->status.data_version,
504 &req->new_version);
David Howellsc435ee32017-11-02 15:27:49 +0000505 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000506 if (call->reply[1])
507 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700508
509 call->offset = 0;
510 call->unmarshall++;
511
David Howells6db3ac32017-03-16 16:27:44 +0000512 case 6:
David Howells08e0e7c2007-04-26 15:55:03 -0700513 break;
514 }
515
David Howells6db3ac32017-03-16 16:27:44 +0000516 for (; req->index < req->nr_pages; req->index++) {
517 if (call->count < PAGE_SIZE)
518 zero_user_segment(req->pages[req->index],
519 call->count, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000520 if (req->page_done)
521 req->page_done(call, req);
David Howells6db3ac32017-03-16 16:27:44 +0000522 call->count = 0;
David Howells416351f2007-05-09 02:33:45 -0700523 }
524
David Howells08e0e7c2007-04-26 15:55:03 -0700525 _leave(" = 0 [done]");
526 return 0;
527}
528
David Howells196ee9c2017-01-05 10:38:34 +0000529static void afs_fetch_data_destructor(struct afs_call *call)
530{
David Howells97e30432017-11-02 15:27:48 +0000531 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000532
533 afs_put_read(req);
534 afs_flat_call_destructor(call);
535}
536
David Howells08e0e7c2007-04-26 15:55:03 -0700537/*
538 * FS.FetchData operation type
539 */
540static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700541 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000542 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700543 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000544 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700545};
546
David Howellsb9b1f8d2007-05-10 03:15:21 -0700547static const struct afs_call_type afs_RXFSFetchData64 = {
548 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000549 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700550 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000551 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700552};
553
554/*
555 * fetch data from a very large file
556 */
David Howellsd2ddc772017-11-02 15:27:50 +0000557static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700558{
David Howellsd2ddc772017-11-02 15:27:50 +0000559 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700560 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000561 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700562 __be32 *bp;
563
564 _enter("");
565
David Howellsf044c882017-11-02 15:27:45 +0000566 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700567 if (!call)
568 return -ENOMEM;
569
David Howellsd2ddc772017-11-02 15:27:50 +0000570 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000571 call->reply[0] = vnode;
572 call->reply[1] = NULL; /* volsync */
573 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100574 call->expected_version = vnode->status.data_version;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700575
576 /* marshall the parameters */
577 bp = call->request;
578 bp[0] = htonl(FSFETCHDATA64);
579 bp[1] = htonl(vnode->fid.vid);
580 bp[2] = htonl(vnode->fid.vnode);
581 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000582 bp[4] = htonl(upper_32_bits(req->pos));
583 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700584 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000585 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700586
David Howells196ee9c2017-01-05 10:38:34 +0000587 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000588 call->cb_break = fc->cb_break;
589 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000590 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000591 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700592}
593
David Howells08e0e7c2007-04-26 15:55:03 -0700594/*
595 * fetch data from a file
596 */
David Howellsd2ddc772017-11-02 15:27:50 +0000597int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700598{
David Howellsd2ddc772017-11-02 15:27:50 +0000599 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700600 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000601 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 __be32 *bp;
603
David Howells196ee9c2017-01-05 10:38:34 +0000604 if (upper_32_bits(req->pos) ||
605 upper_32_bits(req->len) ||
606 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000607 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700608
David Howells08e0e7c2007-04-26 15:55:03 -0700609 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
David Howellsf044c882017-11-02 15:27:45 +0000611 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700612 if (!call)
613 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
David Howellsd2ddc772017-11-02 15:27:50 +0000615 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000616 call->reply[0] = vnode;
617 call->reply[1] = NULL; /* volsync */
618 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100619 call->expected_version = vnode->status.data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700622 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700624 bp[1] = htonl(vnode->fid.vid);
625 bp[2] = htonl(vnode->fid.vnode);
626 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000627 bp[4] = htonl(lower_32_bits(req->pos));
628 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
David Howells196ee9c2017-01-05 10:38:34 +0000630 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000631 call->cb_break = fc->cb_break;
632 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000633 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000634 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700635}
David Howells260a9802007-04-26 15:59:35 -0700636
637/*
638 * deliver reply data to an FS.CreateFile or an FS.MakeDir
639 */
David Howellsd0016482016-08-30 20:42:14 +0100640static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700641{
David Howells97e30432017-11-02 15:27:48 +0000642 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700643 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100644 int ret;
David Howells260a9802007-04-26 15:59:35 -0700645
David Howellsd0016482016-08-30 20:42:14 +0100646 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700647
David Howellsd0016482016-08-30 20:42:14 +0100648 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100649 if (ret < 0)
650 return ret;
David Howells260a9802007-04-26 15:59:35 -0700651
652 /* unmarshall the reply once we've received all of it */
653 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000654 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells0c3a5ac2018-04-06 14:17:24 +0100655 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL, NULL);
656 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
657 &call->expected_version, NULL);
David Howells97e30432017-11-02 15:27:48 +0000658 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
659 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700660
661 _leave(" = 0 [done]");
662 return 0;
663}
664
665/*
666 * FS.CreateFile and FS.MakeDir operation type
667 */
David Howells025db802017-11-02 15:27:51 +0000668static const struct afs_call_type afs_RXFSCreateFile = {
669 .name = "FS.CreateFile",
670 .op = afs_FS_CreateFile,
671 .deliver = afs_deliver_fs_create_vnode,
672 .destructor = afs_flat_call_destructor,
673};
674
675static const struct afs_call_type afs_RXFSMakeDir = {
676 .name = "FS.MakeDir",
677 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700678 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700679 .destructor = afs_flat_call_destructor,
680};
681
682/*
683 * create a file or make a directory
684 */
David Howells8b2a4642017-11-02 15:27:50 +0000685int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700686 const char *name,
687 umode_t mode,
688 struct afs_fid *newfid,
689 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000690 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700691{
David Howellsd2ddc772017-11-02 15:27:50 +0000692 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700693 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000694 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700695 size_t namesz, reqsz, padsz;
696 __be32 *bp;
697
698 _enter("");
699
700 namesz = strlen(name);
701 padsz = (4 - (namesz & 3)) & 3;
702 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
703
David Howells025db802017-11-02 15:27:51 +0000704 call = afs_alloc_flat_call(
705 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
706 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700707 if (!call)
708 return -ENOMEM;
709
David Howellsd2ddc772017-11-02 15:27:50 +0000710 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000711 call->reply[0] = vnode;
712 call->reply[1] = newfid;
713 call->reply[2] = newstatus;
714 call->reply[3] = newcb;
David Howells0c3a5ac2018-04-06 14:17:24 +0100715 call->expected_version = vnode->status.data_version;
David Howells260a9802007-04-26 15:59:35 -0700716
717 /* marshall the parameters */
718 bp = call->request;
719 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
720 *bp++ = htonl(vnode->fid.vid);
721 *bp++ = htonl(vnode->fid.vnode);
722 *bp++ = htonl(vnode->fid.unique);
723 *bp++ = htonl(namesz);
724 memcpy(bp, name, namesz);
725 bp = (void *) bp + namesz;
726 if (padsz > 0) {
727 memset(bp, 0, padsz);
728 bp = (void *) bp + padsz;
729 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000730 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
731 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700732 *bp++ = 0; /* owner */
733 *bp++ = 0; /* group */
734 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
735 *bp++ = 0; /* segment size */
736
David Howellsd2ddc772017-11-02 15:27:50 +0000737 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000738 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000739 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700740}
741
742/*
743 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
744 */
David Howellsd0016482016-08-30 20:42:14 +0100745static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700746{
David Howells97e30432017-11-02 15:27:48 +0000747 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700748 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100749 int ret;
David Howells260a9802007-04-26 15:59:35 -0700750
David Howellsd0016482016-08-30 20:42:14 +0100751 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700752
David Howellsd0016482016-08-30 20:42:14 +0100753 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100754 if (ret < 0)
755 return ret;
David Howells260a9802007-04-26 15:59:35 -0700756
757 /* unmarshall the reply once we've received all of it */
758 bp = call->buffer;
David Howells0c3a5ac2018-04-06 14:17:24 +0100759 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
760 &call->expected_version, NULL);
David Howells97e30432017-11-02 15:27:48 +0000761 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700762
763 _leave(" = 0 [done]");
764 return 0;
765}
766
767/*
768 * FS.RemoveDir/FS.RemoveFile operation type
769 */
David Howells025db802017-11-02 15:27:51 +0000770static const struct afs_call_type afs_RXFSRemoveFile = {
771 .name = "FS.RemoveFile",
772 .op = afs_FS_RemoveFile,
773 .deliver = afs_deliver_fs_remove,
774 .destructor = afs_flat_call_destructor,
775};
776
777static const struct afs_call_type afs_RXFSRemoveDir = {
778 .name = "FS.RemoveDir",
779 .op = afs_FS_RemoveDir,
David Howells260a9802007-04-26 15:59:35 -0700780 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700781 .destructor = afs_flat_call_destructor,
782};
783
784/*
785 * remove a file or directory
786 */
David Howellsd2ddc772017-11-02 15:27:50 +0000787int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir)
David Howells260a9802007-04-26 15:59:35 -0700788{
David Howellsd2ddc772017-11-02 15:27:50 +0000789 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700790 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000791 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700792 size_t namesz, reqsz, padsz;
793 __be32 *bp;
794
795 _enter("");
796
797 namesz = strlen(name);
798 padsz = (4 - (namesz & 3)) & 3;
799 reqsz = (5 * 4) + namesz + padsz;
800
David Howells025db802017-11-02 15:27:51 +0000801 call = afs_alloc_flat_call(
802 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
803 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700804 if (!call)
805 return -ENOMEM;
806
David Howellsd2ddc772017-11-02 15:27:50 +0000807 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000808 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +0100809 call->expected_version = vnode->status.data_version;
David Howells260a9802007-04-26 15:59:35 -0700810
811 /* marshall the parameters */
812 bp = call->request;
813 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
814 *bp++ = htonl(vnode->fid.vid);
815 *bp++ = htonl(vnode->fid.vnode);
816 *bp++ = htonl(vnode->fid.unique);
817 *bp++ = htonl(namesz);
818 memcpy(bp, name, namesz);
819 bp = (void *) bp + namesz;
820 if (padsz > 0) {
821 memset(bp, 0, padsz);
822 bp = (void *) bp + padsz;
823 }
824
David Howellsd2ddc772017-11-02 15:27:50 +0000825 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000826 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000827 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700828}
829
830/*
831 * deliver reply data to an FS.Link
832 */
David Howellsd0016482016-08-30 20:42:14 +0100833static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700834{
David Howells97e30432017-11-02 15:27:48 +0000835 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700836 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100837 int ret;
David Howells260a9802007-04-26 15:59:35 -0700838
David Howellsd0016482016-08-30 20:42:14 +0100839 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700840
David Howellsd0016482016-08-30 20:42:14 +0100841 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100842 if (ret < 0)
843 return ret;
David Howells260a9802007-04-26 15:59:35 -0700844
845 /* unmarshall the reply once we've received all of it */
846 bp = call->buffer;
David Howells0c3a5ac2018-04-06 14:17:24 +0100847 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL, NULL);
848 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode,
849 &call->expected_version, NULL);
David Howells97e30432017-11-02 15:27:48 +0000850 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700851
852 _leave(" = 0 [done]");
853 return 0;
854}
855
856/*
857 * FS.Link operation type
858 */
859static const struct afs_call_type afs_RXFSLink = {
860 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000861 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700862 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700863 .destructor = afs_flat_call_destructor,
864};
865
866/*
867 * make a hard link
868 */
David Howellsd2ddc772017-11-02 15:27:50 +0000869int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
870 const char *name)
David Howells260a9802007-04-26 15:59:35 -0700871{
David Howellsd2ddc772017-11-02 15:27:50 +0000872 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700873 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000874 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700875 size_t namesz, reqsz, padsz;
876 __be32 *bp;
877
878 _enter("");
879
880 namesz = strlen(name);
881 padsz = (4 - (namesz & 3)) & 3;
882 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
883
David Howellsf044c882017-11-02 15:27:45 +0000884 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700885 if (!call)
886 return -ENOMEM;
887
David Howellsd2ddc772017-11-02 15:27:50 +0000888 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000889 call->reply[0] = dvnode;
890 call->reply[1] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +0100891 call->expected_version = vnode->status.data_version;
David Howells260a9802007-04-26 15:59:35 -0700892
893 /* marshall the parameters */
894 bp = call->request;
895 *bp++ = htonl(FSLINK);
896 *bp++ = htonl(dvnode->fid.vid);
897 *bp++ = htonl(dvnode->fid.vnode);
898 *bp++ = htonl(dvnode->fid.unique);
899 *bp++ = htonl(namesz);
900 memcpy(bp, name, namesz);
901 bp = (void *) bp + namesz;
902 if (padsz > 0) {
903 memset(bp, 0, padsz);
904 bp = (void *) bp + padsz;
905 }
906 *bp++ = htonl(vnode->fid.vid);
907 *bp++ = htonl(vnode->fid.vnode);
908 *bp++ = htonl(vnode->fid.unique);
909
David Howellsd2ddc772017-11-02 15:27:50 +0000910 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000911 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000912 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700913}
914
915/*
916 * deliver reply data to an FS.Symlink
917 */
David Howellsd0016482016-08-30 20:42:14 +0100918static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700919{
David Howells97e30432017-11-02 15:27:48 +0000920 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700921 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100922 int ret;
David Howells260a9802007-04-26 15:59:35 -0700923
David Howellsd0016482016-08-30 20:42:14 +0100924 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700925
David Howellsd0016482016-08-30 20:42:14 +0100926 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100927 if (ret < 0)
928 return ret;
David Howells260a9802007-04-26 15:59:35 -0700929
930 /* unmarshall the reply once we've received all of it */
931 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000932 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells0c3a5ac2018-04-06 14:17:24 +0100933 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL, NULL);
934 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
935 &call->expected_version, NULL);
David Howells97e30432017-11-02 15:27:48 +0000936 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700937
938 _leave(" = 0 [done]");
939 return 0;
940}
941
942/*
943 * FS.Symlink operation type
944 */
945static const struct afs_call_type afs_RXFSSymlink = {
946 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +0000947 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -0700948 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700949 .destructor = afs_flat_call_destructor,
950};
951
952/*
953 * create a symbolic link
954 */
David Howells8b2a4642017-11-02 15:27:50 +0000955int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700956 const char *name,
957 const char *contents,
958 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +0000959 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -0700960{
David Howellsd2ddc772017-11-02 15:27:50 +0000961 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700962 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000963 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700964 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
965 __be32 *bp;
966
967 _enter("");
968
969 namesz = strlen(name);
970 padsz = (4 - (namesz & 3)) & 3;
971
972 c_namesz = strlen(contents);
973 c_padsz = (4 - (c_namesz & 3)) & 3;
974
975 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
976
David Howellsf044c882017-11-02 15:27:45 +0000977 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700978 (3 + 21 + 21 + 6) * 4);
979 if (!call)
980 return -ENOMEM;
981
David Howellsd2ddc772017-11-02 15:27:50 +0000982 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000983 call->reply[0] = vnode;
984 call->reply[1] = newfid;
985 call->reply[2] = newstatus;
David Howells0c3a5ac2018-04-06 14:17:24 +0100986 call->expected_version = vnode->status.data_version;
David Howells260a9802007-04-26 15:59:35 -0700987
988 /* marshall the parameters */
989 bp = call->request;
990 *bp++ = htonl(FSSYMLINK);
991 *bp++ = htonl(vnode->fid.vid);
992 *bp++ = htonl(vnode->fid.vnode);
993 *bp++ = htonl(vnode->fid.unique);
994 *bp++ = htonl(namesz);
995 memcpy(bp, name, namesz);
996 bp = (void *) bp + namesz;
997 if (padsz > 0) {
998 memset(bp, 0, padsz);
999 bp = (void *) bp + padsz;
1000 }
1001 *bp++ = htonl(c_namesz);
1002 memcpy(bp, contents, c_namesz);
1003 bp = (void *) bp + c_namesz;
1004 if (c_padsz > 0) {
1005 memset(bp, 0, c_padsz);
1006 bp = (void *) bp + c_padsz;
1007 }
Marc Dionneab94f5d2017-03-16 16:27:47 +00001008 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
1009 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -07001010 *bp++ = 0; /* owner */
1011 *bp++ = 0; /* group */
1012 *bp++ = htonl(S_IRWXUGO); /* unix mode */
1013 *bp++ = 0; /* segment size */
1014
David Howellsd2ddc772017-11-02 15:27:50 +00001015 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001016 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001017 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001018}
1019
1020/*
1021 * deliver reply data to an FS.Rename
1022 */
David Howellsd0016482016-08-30 20:42:14 +01001023static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001024{
David Howells97e30432017-11-02 15:27:48 +00001025 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -07001026 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001027 int ret;
David Howells260a9802007-04-26 15:59:35 -07001028
David Howellsd0016482016-08-30 20:42:14 +01001029 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001030
David Howellsd0016482016-08-30 20:42:14 +01001031 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001032 if (ret < 0)
1033 return ret;
David Howells260a9802007-04-26 15:59:35 -07001034
1035 /* unmarshall the reply once we've received all of it */
1036 bp = call->buffer;
David Howells0c3a5ac2018-04-06 14:17:24 +01001037 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode,
1038 &call->expected_version, NULL);
David Howells260a9802007-04-26 15:59:35 -07001039 if (new_dvnode != orig_dvnode)
David Howells31143d52007-05-09 02:33:46 -07001040 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
David Howells0c3a5ac2018-04-06 14:17:24 +01001041 &call->expected_version_2, NULL);
David Howells97e30432017-11-02 15:27:48 +00001042 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001043
1044 _leave(" = 0 [done]");
1045 return 0;
1046}
1047
1048/*
1049 * FS.Rename operation type
1050 */
1051static const struct afs_call_type afs_RXFSRename = {
1052 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001053 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001054 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001055 .destructor = afs_flat_call_destructor,
1056};
1057
1058/*
1059 * create a symbolic link
1060 */
David Howells8b2a4642017-11-02 15:27:50 +00001061int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001062 const char *orig_name,
1063 struct afs_vnode *new_dvnode,
David Howellsd2ddc772017-11-02 15:27:50 +00001064 const char *new_name)
David Howells260a9802007-04-26 15:59:35 -07001065{
David Howellsd2ddc772017-11-02 15:27:50 +00001066 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001067 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001068 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001069 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1070 __be32 *bp;
1071
1072 _enter("");
1073
1074 o_namesz = strlen(orig_name);
1075 o_padsz = (4 - (o_namesz & 3)) & 3;
1076
1077 n_namesz = strlen(new_name);
1078 n_padsz = (4 - (n_namesz & 3)) & 3;
1079
1080 reqsz = (4 * 4) +
1081 4 + o_namesz + o_padsz +
1082 (3 * 4) +
1083 4 + n_namesz + n_padsz;
1084
David Howellsf044c882017-11-02 15:27:45 +00001085 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001086 if (!call)
1087 return -ENOMEM;
1088
David Howellsd2ddc772017-11-02 15:27:50 +00001089 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001090 call->reply[0] = orig_dvnode;
1091 call->reply[1] = new_dvnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001092 call->expected_version = orig_dvnode->status.data_version;
1093 call->expected_version_2 = new_dvnode->status.data_version;
David Howells260a9802007-04-26 15:59:35 -07001094
1095 /* marshall the parameters */
1096 bp = call->request;
1097 *bp++ = htonl(FSRENAME);
1098 *bp++ = htonl(orig_dvnode->fid.vid);
1099 *bp++ = htonl(orig_dvnode->fid.vnode);
1100 *bp++ = htonl(orig_dvnode->fid.unique);
1101 *bp++ = htonl(o_namesz);
1102 memcpy(bp, orig_name, o_namesz);
1103 bp = (void *) bp + o_namesz;
1104 if (o_padsz > 0) {
1105 memset(bp, 0, o_padsz);
1106 bp = (void *) bp + o_padsz;
1107 }
1108
1109 *bp++ = htonl(new_dvnode->fid.vid);
1110 *bp++ = htonl(new_dvnode->fid.vnode);
1111 *bp++ = htonl(new_dvnode->fid.unique);
1112 *bp++ = htonl(n_namesz);
1113 memcpy(bp, new_name, n_namesz);
1114 bp = (void *) bp + n_namesz;
1115 if (n_padsz > 0) {
1116 memset(bp, 0, n_padsz);
1117 bp = (void *) bp + n_padsz;
1118 }
1119
David Howellsd2ddc772017-11-02 15:27:50 +00001120 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001121 trace_afs_make_fs_call(call, &orig_dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001122 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001123}
David Howells31143d52007-05-09 02:33:46 -07001124
1125/*
1126 * deliver reply data to an FS.StoreData
1127 */
David Howellsd0016482016-08-30 20:42:14 +01001128static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001129{
David Howells97e30432017-11-02 15:27:48 +00001130 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001131 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001132 int ret;
David Howells31143d52007-05-09 02:33:46 -07001133
David Howellsd0016482016-08-30 20:42:14 +01001134 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001135
David Howellsd0016482016-08-30 20:42:14 +01001136 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001137 if (ret < 0)
1138 return ret;
David Howells31143d52007-05-09 02:33:46 -07001139
1140 /* unmarshall the reply once we've received all of it */
1141 bp = call->buffer;
1142 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
David Howells0c3a5ac2018-04-06 14:17:24 +01001143 &call->expected_version, NULL);
David Howells97e30432017-11-02 15:27:48 +00001144 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001145
1146 afs_pages_written_back(vnode, call);
1147
1148 _leave(" = 0 [done]");
1149 return 0;
1150}
1151
1152/*
1153 * FS.StoreData operation type
1154 */
1155static const struct afs_call_type afs_RXFSStoreData = {
1156 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001157 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001158 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001159 .destructor = afs_flat_call_destructor,
1160};
1161
David Howellsb9b1f8d2007-05-10 03:15:21 -07001162static const struct afs_call_type afs_RXFSStoreData64 = {
1163 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001164 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001165 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001166 .destructor = afs_flat_call_destructor,
1167};
1168
1169/*
1170 * store a set of pages to a very large file
1171 */
David Howells8b2a4642017-11-02 15:27:50 +00001172static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001173 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001174 pgoff_t first, pgoff_t last,
1175 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001176 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001177{
David Howells4343d002017-11-02 15:27:52 +00001178 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001179 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001180 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001181 __be32 *bp;
1182
1183 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001184 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001185
David Howellsf044c882017-11-02 15:27:45 +00001186 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001187 (4 + 6 + 3 * 2) * 4,
1188 (21 + 6) * 4);
1189 if (!call)
1190 return -ENOMEM;
1191
David Howells4343d002017-11-02 15:27:52 +00001192 call->key = fc->key;
1193 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001194 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001195 call->first = first;
1196 call->last = last;
1197 call->first_offset = offset;
1198 call->last_to = to;
1199 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001200 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001201
1202 /* marshall the parameters */
1203 bp = call->request;
1204 *bp++ = htonl(FSSTOREDATA64);
1205 *bp++ = htonl(vnode->fid.vid);
1206 *bp++ = htonl(vnode->fid.vnode);
1207 *bp++ = htonl(vnode->fid.unique);
1208
Marc Dionneab94f5d2017-03-16 16:27:47 +00001209 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1210 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001211 *bp++ = 0; /* owner */
1212 *bp++ = 0; /* group */
1213 *bp++ = 0; /* unix mode */
1214 *bp++ = 0; /* segment size */
1215
1216 *bp++ = htonl(pos >> 32);
1217 *bp++ = htonl((u32) pos);
1218 *bp++ = htonl(size >> 32);
1219 *bp++ = htonl((u32) size);
1220 *bp++ = htonl(i_size >> 32);
1221 *bp++ = htonl((u32) i_size);
1222
David Howells025db802017-11-02 15:27:51 +00001223 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001224 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001225}
1226
David Howells31143d52007-05-09 02:33:46 -07001227/*
1228 * store a set of pages
1229 */
David Howells4343d002017-11-02 15:27:52 +00001230int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001231 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001232 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001233{
David Howells4343d002017-11-02 15:27:52 +00001234 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001235 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001236 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001237 loff_t size, pos, i_size;
1238 __be32 *bp;
1239
1240 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001241 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001242
David Howells146a1192017-03-16 16:27:47 +00001243 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001244 if (first != last)
1245 size += (loff_t)(last - first) << PAGE_SHIFT;
1246 pos = (loff_t)first << PAGE_SHIFT;
1247 pos += offset;
1248
1249 i_size = i_size_read(&vnode->vfs_inode);
1250 if (pos + size > i_size)
1251 i_size = size + pos;
1252
1253 _debug("size %llx, at %llx, i_size %llx",
1254 (unsigned long long) size, (unsigned long long) pos,
1255 (unsigned long long) i_size);
1256
David Howellsb9b1f8d2007-05-10 03:15:21 -07001257 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001258 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001259 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001260
David Howellsf044c882017-11-02 15:27:45 +00001261 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001262 (4 + 6 + 3) * 4,
1263 (21 + 6) * 4);
1264 if (!call)
1265 return -ENOMEM;
1266
David Howells4343d002017-11-02 15:27:52 +00001267 call->key = fc->key;
1268 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001269 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001270 call->first = first;
1271 call->last = last;
1272 call->first_offset = offset;
1273 call->last_to = to;
1274 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001275 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001276
1277 /* marshall the parameters */
1278 bp = call->request;
1279 *bp++ = htonl(FSSTOREDATA);
1280 *bp++ = htonl(vnode->fid.vid);
1281 *bp++ = htonl(vnode->fid.vnode);
1282 *bp++ = htonl(vnode->fid.unique);
1283
Marc Dionneab94f5d2017-03-16 16:27:47 +00001284 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1285 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001286 *bp++ = 0; /* owner */
1287 *bp++ = 0; /* group */
1288 *bp++ = 0; /* unix mode */
1289 *bp++ = 0; /* segment size */
1290
1291 *bp++ = htonl(pos);
1292 *bp++ = htonl(size);
1293 *bp++ = htonl(i_size);
1294
David Howellsd2ddc772017-11-02 15:27:50 +00001295 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001296 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001297 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001298}
1299
1300/*
1301 * deliver reply data to an FS.StoreStatus
1302 */
David Howellsd0016482016-08-30 20:42:14 +01001303static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001304{
David Howells97e30432017-11-02 15:27:48 +00001305 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001306 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001307 int ret;
David Howells31143d52007-05-09 02:33:46 -07001308
David Howellsd0016482016-08-30 20:42:14 +01001309 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001310
David Howellsd0016482016-08-30 20:42:14 +01001311 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001312 if (ret < 0)
1313 return ret;
David Howells31143d52007-05-09 02:33:46 -07001314
1315 /* unmarshall the reply once we've received all of it */
David Howells31143d52007-05-09 02:33:46 -07001316 bp = call->buffer;
David Howells0c3a5ac2018-04-06 14:17:24 +01001317 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1318 &call->expected_version, NULL);
David Howells97e30432017-11-02 15:27:48 +00001319 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001320
1321 _leave(" = 0 [done]");
1322 return 0;
1323}
1324
1325/*
1326 * FS.StoreStatus operation type
1327 */
1328static const struct afs_call_type afs_RXFSStoreStatus = {
1329 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001330 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001331 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001332 .destructor = afs_flat_call_destructor,
1333};
1334
1335static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1336 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001337 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001338 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001339 .destructor = afs_flat_call_destructor,
1340};
1341
David Howellsb9b1f8d2007-05-10 03:15:21 -07001342static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1343 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001344 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001345 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001346 .destructor = afs_flat_call_destructor,
1347};
1348
1349/*
1350 * set the attributes on a very large file, using FS.StoreData rather than
1351 * FS.StoreStatus so as to alter the file size also
1352 */
David Howellsd2ddc772017-11-02 15:27:50 +00001353static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001354{
David Howellsd2ddc772017-11-02 15:27:50 +00001355 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001356 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001357 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001358 __be32 *bp;
1359
1360 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001361 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001362
1363 ASSERT(attr->ia_valid & ATTR_SIZE);
1364
David Howellsf044c882017-11-02 15:27:45 +00001365 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001366 (4 + 6 + 3 * 2) * 4,
1367 (21 + 6) * 4);
1368 if (!call)
1369 return -ENOMEM;
1370
David Howellsd2ddc772017-11-02 15:27:50 +00001371 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001372 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001373 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001374
1375 /* marshall the parameters */
1376 bp = call->request;
1377 *bp++ = htonl(FSSTOREDATA64);
1378 *bp++ = htonl(vnode->fid.vid);
1379 *bp++ = htonl(vnode->fid.vnode);
1380 *bp++ = htonl(vnode->fid.unique);
1381
1382 xdr_encode_AFS_StoreStatus(&bp, attr);
1383
1384 *bp++ = 0; /* position of start of write */
1385 *bp++ = 0;
1386 *bp++ = 0; /* size of write */
1387 *bp++ = 0;
1388 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1389 *bp++ = htonl((u32) attr->ia_size);
1390
David Howellsd2ddc772017-11-02 15:27:50 +00001391 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001392 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001393 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001394}
1395
David Howells31143d52007-05-09 02:33:46 -07001396/*
1397 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1398 * so as to alter the file size also
1399 */
David Howellsd2ddc772017-11-02 15:27:50 +00001400static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001401{
David Howellsd2ddc772017-11-02 15:27:50 +00001402 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001403 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001404 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001405 __be32 *bp;
1406
1407 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001408 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001409
1410 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001411 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001412 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001413
David Howellsf044c882017-11-02 15:27:45 +00001414 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001415 (4 + 6 + 3) * 4,
1416 (21 + 6) * 4);
1417 if (!call)
1418 return -ENOMEM;
1419
David Howellsd2ddc772017-11-02 15:27:50 +00001420 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001421 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001422 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001423
1424 /* marshall the parameters */
1425 bp = call->request;
1426 *bp++ = htonl(FSSTOREDATA);
1427 *bp++ = htonl(vnode->fid.vid);
1428 *bp++ = htonl(vnode->fid.vnode);
1429 *bp++ = htonl(vnode->fid.unique);
1430
1431 xdr_encode_AFS_StoreStatus(&bp, attr);
1432
1433 *bp++ = 0; /* position of start of write */
1434 *bp++ = 0; /* size of write */
1435 *bp++ = htonl(attr->ia_size); /* new file length */
1436
David Howellsd2ddc772017-11-02 15:27:50 +00001437 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001438 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001439 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001440}
1441
1442/*
1443 * set the attributes on a file, using FS.StoreData if there's a change in file
1444 * size, and FS.StoreStatus otherwise
1445 */
David Howellsd2ddc772017-11-02 15:27:50 +00001446int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001447{
David Howellsd2ddc772017-11-02 15:27:50 +00001448 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001449 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001450 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001451 __be32 *bp;
1452
1453 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001454 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001455
1456 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001457 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001458
David Howellsf044c882017-11-02 15:27:45 +00001459 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001460 (4 + 6) * 4,
1461 (21 + 6) * 4);
1462 if (!call)
1463 return -ENOMEM;
1464
David Howellsd2ddc772017-11-02 15:27:50 +00001465 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001466 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001467 call->expected_version = vnode->status.data_version;
David Howells31143d52007-05-09 02:33:46 -07001468
1469 /* marshall the parameters */
1470 bp = call->request;
1471 *bp++ = htonl(FSSTORESTATUS);
1472 *bp++ = htonl(vnode->fid.vid);
1473 *bp++ = htonl(vnode->fid.vnode);
1474 *bp++ = htonl(vnode->fid.unique);
1475
1476 xdr_encode_AFS_StoreStatus(&bp, attr);
1477
David Howellsd2ddc772017-11-02 15:27:50 +00001478 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001479 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001480 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001481}
David Howells45222b92007-05-10 22:22:20 -07001482
1483/*
1484 * deliver reply data to an FS.GetVolumeStatus
1485 */
David Howellsd0016482016-08-30 20:42:14 +01001486static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001487{
1488 const __be32 *bp;
1489 char *p;
1490 int ret;
1491
David Howellsd0016482016-08-30 20:42:14 +01001492 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001493
1494 switch (call->unmarshall) {
1495 case 0:
1496 call->offset = 0;
1497 call->unmarshall++;
1498
1499 /* extract the returned status record */
1500 case 1:
1501 _debug("extract status");
David Howellsd0016482016-08-30 20:42:14 +01001502 ret = afs_extract_data(call, call->buffer,
1503 12 * 4, true);
David Howells372ee162016-08-03 14:11:40 +01001504 if (ret < 0)
1505 return ret;
David Howells45222b92007-05-10 22:22:20 -07001506
1507 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001508 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001509 call->offset = 0;
1510 call->unmarshall++;
1511
1512 /* extract the volume name length */
1513 case 2:
David Howellsd0016482016-08-30 20:42:14 +01001514 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001515 if (ret < 0)
1516 return ret;
David Howells45222b92007-05-10 22:22:20 -07001517
1518 call->count = ntohl(call->tmp);
1519 _debug("volname length: %u", call->count);
1520 if (call->count >= AFSNAMEMAX)
1521 return -EBADMSG;
1522 call->offset = 0;
1523 call->unmarshall++;
1524
1525 /* extract the volume name */
1526 case 3:
1527 _debug("extract volname");
1528 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001529 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001530 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001531 if (ret < 0)
1532 return ret;
David Howells45222b92007-05-10 22:22:20 -07001533 }
1534
David Howells97e30432017-11-02 15:27:48 +00001535 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001536 p[call->count] = 0;
1537 _debug("volname '%s'", p);
1538
1539 call->offset = 0;
1540 call->unmarshall++;
1541
1542 /* extract the volume name padding */
1543 if ((call->count & 3) == 0) {
1544 call->unmarshall++;
1545 goto no_volname_padding;
1546 }
1547 call->count = 4 - (call->count & 3);
1548
1549 case 4:
David Howellsd0016482016-08-30 20:42:14 +01001550 ret = afs_extract_data(call, call->buffer,
1551 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001552 if (ret < 0)
1553 return ret;
David Howells45222b92007-05-10 22:22:20 -07001554
1555 call->offset = 0;
1556 call->unmarshall++;
1557 no_volname_padding:
1558
1559 /* extract the offline message length */
1560 case 5:
David Howellsd0016482016-08-30 20:42:14 +01001561 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001562 if (ret < 0)
1563 return ret;
David Howells45222b92007-05-10 22:22:20 -07001564
1565 call->count = ntohl(call->tmp);
1566 _debug("offline msg length: %u", call->count);
1567 if (call->count >= AFSNAMEMAX)
1568 return -EBADMSG;
1569 call->offset = 0;
1570 call->unmarshall++;
1571
1572 /* extract the offline message */
1573 case 6:
1574 _debug("extract offline");
1575 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001576 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001577 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001578 if (ret < 0)
1579 return ret;
David Howells45222b92007-05-10 22:22:20 -07001580 }
1581
David Howells97e30432017-11-02 15:27:48 +00001582 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001583 p[call->count] = 0;
1584 _debug("offline '%s'", p);
1585
1586 call->offset = 0;
1587 call->unmarshall++;
1588
1589 /* extract the offline message padding */
1590 if ((call->count & 3) == 0) {
1591 call->unmarshall++;
1592 goto no_offline_padding;
1593 }
1594 call->count = 4 - (call->count & 3);
1595
1596 case 7:
David Howellsd0016482016-08-30 20:42:14 +01001597 ret = afs_extract_data(call, call->buffer,
1598 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001599 if (ret < 0)
1600 return ret;
David Howells45222b92007-05-10 22:22:20 -07001601
1602 call->offset = 0;
1603 call->unmarshall++;
1604 no_offline_padding:
1605
1606 /* extract the message of the day length */
1607 case 8:
David Howellsd0016482016-08-30 20:42:14 +01001608 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001609 if (ret < 0)
1610 return ret;
David Howells45222b92007-05-10 22:22:20 -07001611
1612 call->count = ntohl(call->tmp);
1613 _debug("motd length: %u", call->count);
1614 if (call->count >= AFSNAMEMAX)
1615 return -EBADMSG;
1616 call->offset = 0;
1617 call->unmarshall++;
1618
1619 /* extract the message of the day */
1620 case 9:
1621 _debug("extract motd");
1622 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001623 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001624 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001625 if (ret < 0)
1626 return ret;
David Howells45222b92007-05-10 22:22:20 -07001627 }
1628
David Howells97e30432017-11-02 15:27:48 +00001629 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001630 p[call->count] = 0;
1631 _debug("motd '%s'", p);
1632
1633 call->offset = 0;
1634 call->unmarshall++;
1635
1636 /* extract the message of the day padding */
David Howellsd0016482016-08-30 20:42:14 +01001637 call->count = (4 - (call->count & 3)) & 3;
David Howells45222b92007-05-10 22:22:20 -07001638
1639 case 10:
David Howellsd0016482016-08-30 20:42:14 +01001640 ret = afs_extract_data(call, call->buffer,
1641 call->count, false);
David Howells372ee162016-08-03 14:11:40 +01001642 if (ret < 0)
1643 return ret;
David Howells45222b92007-05-10 22:22:20 -07001644
1645 call->offset = 0;
1646 call->unmarshall++;
David Howells45222b92007-05-10 22:22:20 -07001647 case 11:
David Howells45222b92007-05-10 22:22:20 -07001648 break;
1649 }
1650
David Howells45222b92007-05-10 22:22:20 -07001651 _leave(" = 0 [done]");
1652 return 0;
1653}
1654
1655/*
1656 * destroy an FS.GetVolumeStatus call
1657 */
1658static void afs_get_volume_status_call_destructor(struct afs_call *call)
1659{
David Howells97e30432017-11-02 15:27:48 +00001660 kfree(call->reply[2]);
1661 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001662 afs_flat_call_destructor(call);
1663}
1664
1665/*
1666 * FS.GetVolumeStatus operation type
1667 */
1668static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1669 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001670 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001671 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001672 .destructor = afs_get_volume_status_call_destructor,
1673};
1674
1675/*
1676 * fetch the status of a volume
1677 */
David Howells8b2a4642017-11-02 15:27:50 +00001678int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001679 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001680{
David Howellsd2ddc772017-11-02 15:27:50 +00001681 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001682 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001683 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001684 __be32 *bp;
1685 void *tmpbuf;
1686
1687 _enter("");
1688
1689 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1690 if (!tmpbuf)
1691 return -ENOMEM;
1692
David Howellsf044c882017-11-02 15:27:45 +00001693 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001694 if (!call) {
1695 kfree(tmpbuf);
1696 return -ENOMEM;
1697 }
1698
David Howellsd2ddc772017-11-02 15:27:50 +00001699 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001700 call->reply[0] = vnode;
1701 call->reply[1] = vs;
1702 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001703
1704 /* marshall the parameters */
1705 bp = call->request;
1706 bp[0] = htonl(FSGETVOLUMESTATUS);
1707 bp[1] = htonl(vnode->fid.vid);
1708
David Howellsd2ddc772017-11-02 15:27:50 +00001709 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001710 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001711 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells45222b92007-05-10 22:22:20 -07001712}
David Howellse8d6c552007-07-15 23:40:12 -07001713
1714/*
1715 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1716 */
David Howellsd0016482016-08-30 20:42:14 +01001717static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001718{
1719 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001720 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001721
David Howellsd0016482016-08-30 20:42:14 +01001722 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001723
David Howellsd0016482016-08-30 20:42:14 +01001724 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001725 if (ret < 0)
1726 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001727
1728 /* unmarshall the reply once we've received all of it */
1729 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001730 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001731
1732 _leave(" = 0 [done]");
1733 return 0;
1734}
1735
1736/*
1737 * FS.SetLock operation type
1738 */
1739static const struct afs_call_type afs_RXFSSetLock = {
1740 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001741 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001742 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001743 .destructor = afs_flat_call_destructor,
1744};
1745
1746/*
1747 * FS.ExtendLock operation type
1748 */
1749static const struct afs_call_type afs_RXFSExtendLock = {
1750 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001751 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001752 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001753 .destructor = afs_flat_call_destructor,
1754};
1755
1756/*
1757 * FS.ReleaseLock operation type
1758 */
1759static const struct afs_call_type afs_RXFSReleaseLock = {
1760 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001761 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001762 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001763 .destructor = afs_flat_call_destructor,
1764};
1765
1766/*
David Howellsd2ddc772017-11-02 15:27:50 +00001767 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001768 */
David Howellsd2ddc772017-11-02 15:27:50 +00001769int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001770{
David Howellsd2ddc772017-11-02 15:27:50 +00001771 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001772 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001773 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001774 __be32 *bp;
1775
1776 _enter("");
1777
David Howellsf044c882017-11-02 15:27:45 +00001778 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001779 if (!call)
1780 return -ENOMEM;
1781
David Howellsd2ddc772017-11-02 15:27:50 +00001782 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001783 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001784
1785 /* marshall the parameters */
1786 bp = call->request;
1787 *bp++ = htonl(FSSETLOCK);
1788 *bp++ = htonl(vnode->fid.vid);
1789 *bp++ = htonl(vnode->fid.vnode);
1790 *bp++ = htonl(vnode->fid.unique);
1791 *bp++ = htonl(type);
1792
David Howellsd2ddc772017-11-02 15:27:50 +00001793 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001794 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001795 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001796}
1797
1798/*
1799 * extend a lock on a file
1800 */
David Howellsd2ddc772017-11-02 15:27:50 +00001801int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001802{
David Howellsd2ddc772017-11-02 15:27:50 +00001803 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001804 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001805 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001806 __be32 *bp;
1807
1808 _enter("");
1809
David Howellsf044c882017-11-02 15:27:45 +00001810 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001811 if (!call)
1812 return -ENOMEM;
1813
David Howellsd2ddc772017-11-02 15:27:50 +00001814 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001815 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001816
1817 /* marshall the parameters */
1818 bp = call->request;
1819 *bp++ = htonl(FSEXTENDLOCK);
1820 *bp++ = htonl(vnode->fid.vid);
1821 *bp++ = htonl(vnode->fid.vnode);
1822 *bp++ = htonl(vnode->fid.unique);
1823
David Howellsd2ddc772017-11-02 15:27:50 +00001824 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001825 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001826 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001827}
1828
1829/*
1830 * release a lock on a file
1831 */
David Howellsd2ddc772017-11-02 15:27:50 +00001832int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001833{
David Howellsd2ddc772017-11-02 15:27:50 +00001834 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001835 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001836 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001837 __be32 *bp;
1838
1839 _enter("");
1840
David Howellsf044c882017-11-02 15:27:45 +00001841 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001842 if (!call)
1843 return -ENOMEM;
1844
David Howellsd2ddc772017-11-02 15:27:50 +00001845 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001846 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001847
1848 /* marshall the parameters */
1849 bp = call->request;
1850 *bp++ = htonl(FSRELEASELOCK);
1851 *bp++ = htonl(vnode->fid.vid);
1852 *bp++ = htonl(vnode->fid.vnode);
1853 *bp++ = htonl(vnode->fid.unique);
1854
David Howellsd2ddc772017-11-02 15:27:50 +00001855 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001856 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001857 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsc435ee32017-11-02 15:27:49 +00001858}
1859
1860/*
1861 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1862 */
1863static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1864{
1865 return afs_transfer_reply(call);
1866}
1867
1868/*
1869 * FS.GiveUpAllCallBacks operation type
1870 */
1871static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1872 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001873 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001874 .deliver = afs_deliver_fs_give_up_all_callbacks,
1875 .destructor = afs_flat_call_destructor,
1876};
1877
1878/*
1879 * Flush all the callbacks we have on a server.
1880 */
David Howellsd2ddc772017-11-02 15:27:50 +00001881int afs_fs_give_up_all_callbacks(struct afs_net *net,
1882 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001883 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001884 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001885{
1886 struct afs_call *call;
1887 __be32 *bp;
1888
1889 _enter("");
1890
David Howellsd2ddc772017-11-02 15:27:50 +00001891 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001892 if (!call)
1893 return -ENOMEM;
1894
1895 call->key = key;
1896
1897 /* marshall the parameters */
1898 bp = call->request;
1899 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1900
1901 /* Can't take a ref on server */
David Howellsd2ddc772017-11-02 15:27:50 +00001902 return afs_make_call(ac, call, GFP_NOFS, false);
1903}
1904
1905/*
1906 * Deliver reply data to an FS.GetCapabilities operation.
1907 */
1908static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1909{
1910 u32 count;
1911 int ret;
1912
1913 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count);
1914
1915again:
1916 switch (call->unmarshall) {
1917 case 0:
1918 call->offset = 0;
1919 call->unmarshall++;
1920
1921 /* Extract the capabilities word count */
1922 case 1:
1923 ret = afs_extract_data(call, &call->tmp,
1924 1 * sizeof(__be32),
1925 true);
1926 if (ret < 0)
1927 return ret;
1928
1929 count = ntohl(call->tmp);
1930
1931 call->count = count;
1932 call->count2 = count;
1933 call->offset = 0;
1934 call->unmarshall++;
1935
1936 /* Extract capabilities words */
1937 case 2:
1938 count = min(call->count, 16U);
1939 ret = afs_extract_data(call, call->buffer,
1940 count * sizeof(__be32),
1941 call->count > 16);
1942 if (ret < 0)
1943 return ret;
1944
1945 /* TODO: Examine capabilities */
1946
1947 call->count -= count;
1948 if (call->count > 0)
1949 goto again;
1950 call->offset = 0;
1951 call->unmarshall++;
1952 break;
1953 }
1954
1955 _leave(" = 0 [done]");
1956 return 0;
1957}
1958
1959/*
1960 * FS.GetCapabilities operation type
1961 */
1962static const struct afs_call_type afs_RXFSGetCapabilities = {
1963 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001964 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001965 .deliver = afs_deliver_fs_get_capabilities,
1966 .destructor = afs_flat_call_destructor,
1967};
1968
1969/*
1970 * Probe a fileserver for the capabilities that it supports. This can
1971 * return up to 196 words.
1972 */
1973int afs_fs_get_capabilities(struct afs_net *net,
1974 struct afs_server *server,
1975 struct afs_addr_cursor *ac,
1976 struct key *key)
1977{
1978 struct afs_call *call;
1979 __be32 *bp;
1980
1981 _enter("");
1982
1983 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1984 if (!call)
1985 return -ENOMEM;
1986
1987 call->key = key;
1988
1989 /* marshall the parameters */
1990 bp = call->request;
1991 *bp++ = htonl(FSGETCAPABILITIES);
1992
1993 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00001994 trace_afs_make_fs_call(call, NULL);
David Howellsd2ddc772017-11-02 15:27:50 +00001995 return afs_make_call(ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001996}
David Howells5cf9dd52018-04-09 21:12:31 +01001997
1998/*
1999 * Deliver reply data to an FS.FetchStatus with no vnode.
2000 */
2001static int afs_deliver_fs_fetch_status(struct afs_call *call)
2002{
2003 struct afs_file_status *status = call->reply[1];
2004 struct afs_callback *callback = call->reply[2];
2005 struct afs_volsync *volsync = call->reply[3];
2006 struct afs_vnode *vnode = call->reply[0];
2007 const __be32 *bp;
2008 int ret;
2009
2010 ret = afs_transfer_reply(call);
2011 if (ret < 0)
2012 return ret;
2013
2014 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
2015
2016 /* unmarshall the reply once we've received all of it */
2017 bp = call->buffer;
David Howells0c3a5ac2018-04-06 14:17:24 +01002018 xdr_decode_AFSFetchStatus(&bp, status, vnode,
2019 &call->expected_version, NULL);
David Howells5cf9dd52018-04-09 21:12:31 +01002020 callback[call->count].version = ntohl(bp[0]);
2021 callback[call->count].expiry = ntohl(bp[1]);
2022 callback[call->count].type = ntohl(bp[2]);
2023 if (vnode)
2024 xdr_decode_AFSCallBack(call, vnode, &bp);
2025 else
2026 bp += 3;
2027 if (volsync)
2028 xdr_decode_AFSVolSync(&bp, volsync);
2029
2030 _leave(" = 0 [done]");
2031 return 0;
2032}
2033
2034/*
2035 * FS.FetchStatus operation type
2036 */
2037static const struct afs_call_type afs_RXFSFetchStatus = {
2038 .name = "FS.FetchStatus",
2039 .op = afs_FS_FetchStatus,
2040 .deliver = afs_deliver_fs_fetch_status,
2041 .destructor = afs_flat_call_destructor,
2042};
2043
2044/*
2045 * Fetch the status information for a fid without needing a vnode handle.
2046 */
2047int afs_fs_fetch_status(struct afs_fs_cursor *fc,
2048 struct afs_net *net,
2049 struct afs_fid *fid,
2050 struct afs_file_status *status,
2051 struct afs_callback *callback,
2052 struct afs_volsync *volsync)
2053{
2054 struct afs_call *call;
2055 __be32 *bp;
2056
2057 _enter(",%x,{%x:%u},,",
2058 key_serial(fc->key), fid->vid, fid->vnode);
2059
2060 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
2061 if (!call) {
2062 fc->ac.error = -ENOMEM;
2063 return -ENOMEM;
2064 }
2065
2066 call->key = fc->key;
2067 call->reply[0] = NULL; /* vnode for fid[0] */
2068 call->reply[1] = status;
2069 call->reply[2] = callback;
2070 call->reply[3] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +01002071 call->expected_version = 1; /* vnode->status.data_version */
David Howells5cf9dd52018-04-09 21:12:31 +01002072
2073 /* marshall the parameters */
2074 bp = call->request;
2075 bp[0] = htonl(FSFETCHSTATUS);
2076 bp[1] = htonl(fid->vid);
2077 bp[2] = htonl(fid->vnode);
2078 bp[3] = htonl(fid->unique);
2079
2080 call->cb_break = fc->cb_break;
2081 afs_use_fs_server(call, fc->cbi);
2082 trace_afs_make_fs_call(call, fid);
2083 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2084}
2085
2086/*
2087 * Deliver reply data to an FS.InlineBulkStatus call
2088 */
2089static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2090{
2091 struct afs_file_status *statuses;
2092 struct afs_callback *callbacks;
2093 struct afs_vnode *vnode = call->reply[0];
2094 const __be32 *bp;
2095 u32 tmp;
2096 int ret;
2097
2098 _enter("{%u}", call->unmarshall);
2099
2100 switch (call->unmarshall) {
2101 case 0:
2102 call->offset = 0;
2103 call->unmarshall++;
2104
2105 /* Extract the file status count and array in two steps */
2106 case 1:
2107 _debug("extract status count");
2108 ret = afs_extract_data(call, &call->tmp, 4, true);
2109 if (ret < 0)
2110 return ret;
2111
2112 tmp = ntohl(call->tmp);
2113 _debug("status count: %u/%u", tmp, call->count2);
2114 if (tmp != call->count2)
2115 return -EBADMSG;
2116
2117 call->count = 0;
2118 call->unmarshall++;
2119 more_counts:
2120 call->offset = 0;
2121
2122 case 2:
2123 _debug("extract status array %u", call->count);
2124 ret = afs_extract_data(call, call->buffer, 21 * 4, true);
2125 if (ret < 0)
2126 return ret;
2127
2128 bp = call->buffer;
2129 statuses = call->reply[1];
2130 xdr_decode_AFSFetchStatus(&bp, &statuses[call->count],
2131 call->count == 0 ? vnode : NULL,
David Howells0c3a5ac2018-04-06 14:17:24 +01002132 NULL, NULL);
David Howells5cf9dd52018-04-09 21:12:31 +01002133
2134 call->count++;
2135 if (call->count < call->count2)
2136 goto more_counts;
2137
2138 call->count = 0;
2139 call->unmarshall++;
2140 call->offset = 0;
2141
2142 /* Extract the callback count and array in two steps */
2143 case 3:
2144 _debug("extract CB count");
2145 ret = afs_extract_data(call, &call->tmp, 4, true);
2146 if (ret < 0)
2147 return ret;
2148
2149 tmp = ntohl(call->tmp);
2150 _debug("CB count: %u", tmp);
2151 if (tmp != call->count2)
2152 return -EBADMSG;
2153 call->count = 0;
2154 call->unmarshall++;
2155 more_cbs:
2156 call->offset = 0;
2157
2158 case 4:
2159 _debug("extract CB array");
2160 ret = afs_extract_data(call, call->buffer, 3 * 4, true);
2161 if (ret < 0)
2162 return ret;
2163
2164 _debug("unmarshall CB array");
2165 bp = call->buffer;
2166 callbacks = call->reply[2];
2167 callbacks[call->count].version = ntohl(bp[0]);
2168 callbacks[call->count].expiry = ntohl(bp[1]);
2169 callbacks[call->count].type = ntohl(bp[2]);
2170 statuses = call->reply[1];
2171 if (call->count == 0 && vnode && statuses[0].abort_code == 0)
2172 xdr_decode_AFSCallBack(call, vnode, &bp);
2173 call->count++;
2174 if (call->count < call->count2)
2175 goto more_cbs;
2176
2177 call->offset = 0;
2178 call->unmarshall++;
2179
2180 case 5:
2181 ret = afs_extract_data(call, call->buffer, 6 * 4, false);
2182 if (ret < 0)
2183 return ret;
2184
2185 bp = call->buffer;
2186 if (call->reply[3])
2187 xdr_decode_AFSVolSync(&bp, call->reply[3]);
2188
2189 call->offset = 0;
2190 call->unmarshall++;
2191
2192 case 6:
2193 break;
2194 }
2195
2196 _leave(" = 0 [done]");
2197 return 0;
2198}
2199
2200/*
2201 * FS.InlineBulkStatus operation type
2202 */
2203static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2204 .name = "FS.InlineBulkStatus",
2205 .op = afs_FS_InlineBulkStatus,
2206 .deliver = afs_deliver_fs_inline_bulk_status,
2207 .destructor = afs_flat_call_destructor,
2208};
2209
2210/*
2211 * Fetch the status information for up to 50 files
2212 */
2213int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2214 struct afs_net *net,
2215 struct afs_fid *fids,
2216 struct afs_file_status *statuses,
2217 struct afs_callback *callbacks,
2218 unsigned int nr_fids,
2219 struct afs_volsync *volsync)
2220{
2221 struct afs_call *call;
2222 __be32 *bp;
2223 int i;
2224
2225 _enter(",%x,{%x:%u},%u",
2226 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2227
2228 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2229 (2 + nr_fids * 3) * 4,
2230 21 * 4);
2231 if (!call) {
2232 fc->ac.error = -ENOMEM;
2233 return -ENOMEM;
2234 }
2235
2236 call->key = fc->key;
2237 call->reply[0] = NULL; /* vnode for fid[0] */
2238 call->reply[1] = statuses;
2239 call->reply[2] = callbacks;
2240 call->reply[3] = volsync;
2241 call->count2 = nr_fids;
2242
2243 /* marshall the parameters */
2244 bp = call->request;
2245 *bp++ = htonl(FSINLINEBULKSTATUS);
2246 *bp++ = htonl(nr_fids);
2247 for (i = 0; i < nr_fids; i++) {
2248 *bp++ = htonl(fids[i].vid);
2249 *bp++ = htonl(fids[i].vnode);
2250 *bp++ = htonl(fids[i].unique);
2251 }
2252
2253 call->cb_break = fc->cb_break;
2254 afs_use_fs_server(call, fc->cbi);
2255 trace_afs_make_fs_call(call, &fids[0]);
2256 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2257}