blob: 90aa3eb2c893675a0bde73dd644422f804f92bbb [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,
72 afs_dataversion_t *store_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073{
David Howells31143d52007-05-09 02:33:46 -070074 afs_dataversion_t expected_version;
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 Howells08e0e7c2007-04-26 15:55:03 -0700139
140 _debug("vnode time %lx, %lx",
David Howells260a9802007-04-26 15:59:35 -0700141 status->mtime_client, status->mtime_server);
David Howells08e0e7c2007-04-26 15:55:03 -0700142
David Howells260a9802007-04-26 15:59:35 -0700143 if (vnode) {
David Howells260a9802007-04-26 15:59:35 -0700144 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
145 _debug("vnode changed");
146 i_size_write(&vnode->vfs_inode, size);
147 vnode->vfs_inode.i_uid = status->owner;
148 vnode->vfs_inode.i_gid = status->group;
David Howellsd6e43f72011-06-14 00:45:44 +0100149 vnode->vfs_inode.i_generation = vnode->fid.unique;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200150 set_nlink(&vnode->vfs_inode, status->nlink);
David Howells260a9802007-04-26 15:59:35 -0700151
152 mode = vnode->vfs_inode.i_mode;
153 mode &= ~S_IALLUGO;
154 mode |= status->mode;
155 barrier();
156 vnode->vfs_inode.i_mode = mode;
157 }
158
Marc Dionneab94f5d2017-03-16 16:27:47 +0000159 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
David Howells260a9802007-04-26 15:59:35 -0700160 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
161 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
Jeff Laytona01179e2017-12-11 06:35:11 -0500162 inode_set_iversion_raw(&vnode->vfs_inode, data_version);
David Howells260a9802007-04-26 15:59:35 -0700163 }
164
David Howells31143d52007-05-09 02:33:46 -0700165 expected_version = status->data_version;
166 if (store_version)
167 expected_version = *store_version;
168
169 if (expected_version != data_version) {
David Howells260a9802007-04-26 15:59:35 -0700170 status->data_version = data_version;
171 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
172 _debug("vnode modified %llx on {%x:%u}",
David S. Millerba3e0e12007-04-26 16:06:22 -0700173 (unsigned long long) data_version,
174 vnode->fid.vid, vnode->fid.vnode);
David Howellsc435ee32017-11-02 15:27:49 +0000175 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
David Howells260a9802007-04-26 15:59:35 -0700176 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
177 }
David Howells31143d52007-05-09 02:33:46 -0700178 } else if (store_version) {
179 status->data_version = data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 }
David Howellsc435ee32017-11-02 15:27:49 +0000181
David Howells888b3382018-04-06 14:17:24 +0100182out:
David Howellsd2ddc772017-11-02 15:27:50 +0000183 if (vnode)
184 write_sequnlock(&vnode->cb_lock);
David Howellsec268152007-04-26 15:49:28 -0700185}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187/*
David Howells08e0e7c2007-04-26 15:55:03 -0700188 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 */
David Howellsc435ee32017-11-02 15:27:49 +0000190static void xdr_decode_AFSCallBack(struct afs_call *call,
191 struct afs_vnode *vnode,
192 const __be32 **_bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193{
David Howellsd2ddc772017-11-02 15:27:50 +0000194 struct afs_cb_interest *old, *cbi = call->cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700195 const __be32 *bp = *_bp;
David Howellsc435ee32017-11-02 15:27:49 +0000196 u32 cb_expiry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
David Howellsc435ee32017-11-02 15:27:49 +0000198 write_seqlock(&vnode->cb_lock);
199
David Howellsd2ddc772017-11-02 15:27:50 +0000200 if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) {
David Howellsc435ee32017-11-02 15:27:49 +0000201 vnode->cb_version = ntohl(*bp++);
202 cb_expiry = ntohl(*bp++);
203 vnode->cb_type = ntohl(*bp++);
204 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
David Howellsd2ddc772017-11-02 15:27:50 +0000205 old = vnode->cb_interest;
206 if (old != call->cbi) {
207 vnode->cb_interest = cbi;
208 cbi = old;
209 }
David Howellsc435ee32017-11-02 15:27:49 +0000210 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
211 } else {
212 bp += 3;
213 }
214
215 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +0000216 call->cbi = cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700217 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700218}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
David Howells260a9802007-04-26 15:59:35 -0700220static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
221 struct afs_callback *cb)
222{
223 const __be32 *bp = *_bp;
224
225 cb->version = ntohl(*bp++);
226 cb->expiry = ntohl(*bp++);
227 cb->type = ntohl(*bp++);
228 *_bp = bp;
229}
230
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231/*
David Howells08e0e7c2007-04-26 15:55:03 -0700232 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 */
David Howells08e0e7c2007-04-26 15:55:03 -0700234static void xdr_decode_AFSVolSync(const __be32 **_bp,
235 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236{
David Howells08e0e7c2007-04-26 15:55:03 -0700237 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
David Howells08e0e7c2007-04-26 15:55:03 -0700239 volsync->creation = ntohl(*bp++);
240 bp++; /* spare2 */
241 bp++; /* spare3 */
242 bp++; /* spare4 */
243 bp++; /* spare5 */
244 bp++; /* spare6 */
245 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700246}
David Howells08e0e7c2007-04-26 15:55:03 -0700247
248/*
David Howells31143d52007-05-09 02:33:46 -0700249 * encode the requested attributes into an AFSStoreStatus block
250 */
251static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
252{
253 __be32 *bp = *_bp;
254 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
255
256 mask = 0;
257 if (attr->ia_valid & ATTR_MTIME) {
258 mask |= AFS_SET_MTIME;
259 mtime = attr->ia_mtime.tv_sec;
260 }
261
262 if (attr->ia_valid & ATTR_UID) {
263 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800264 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700265 }
266
267 if (attr->ia_valid & ATTR_GID) {
268 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800269 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700270 }
271
272 if (attr->ia_valid & ATTR_MODE) {
273 mask |= AFS_SET_MODE;
274 mode = attr->ia_mode & S_IALLUGO;
275 }
276
277 *bp++ = htonl(mask);
278 *bp++ = htonl(mtime);
279 *bp++ = htonl(owner);
280 *bp++ = htonl(group);
281 *bp++ = htonl(mode);
282 *bp++ = 0; /* segment size */
283 *_bp = bp;
284}
285
286/*
David Howells45222b92007-05-10 22:22:20 -0700287 * decode an AFSFetchVolumeStatus block
288 */
289static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
290 struct afs_volume_status *vs)
291{
292 const __be32 *bp = *_bp;
293
294 vs->vid = ntohl(*bp++);
295 vs->parent_id = ntohl(*bp++);
296 vs->online = ntohl(*bp++);
297 vs->in_service = ntohl(*bp++);
298 vs->blessed = ntohl(*bp++);
299 vs->needs_salvage = ntohl(*bp++);
300 vs->type = ntohl(*bp++);
301 vs->min_quota = ntohl(*bp++);
302 vs->max_quota = ntohl(*bp++);
303 vs->blocks_in_use = ntohl(*bp++);
304 vs->part_blocks_avail = ntohl(*bp++);
305 vs->part_max_blocks = ntohl(*bp++);
306 *_bp = bp;
307}
308
309/*
David Howells08e0e7c2007-04-26 15:55:03 -0700310 * deliver reply data to an FS.FetchStatus
311 */
David Howells5cf9dd52018-04-09 21:12:31 +0100312static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700313{
David Howells97e30432017-11-02 15:27:48 +0000314 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700315 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100316 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700317
David Howellsd0016482016-08-30 20:42:14 +0100318 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100319 if (ret < 0)
320 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700321
David Howellsc435ee32017-11-02 15:27:49 +0000322 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
323
David Howells08e0e7c2007-04-26 15:55:03 -0700324 /* unmarshall the reply once we've received all of it */
325 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700326 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howellsc435ee32017-11-02 15:27:49 +0000327 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000328 if (call->reply[1])
329 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700330
331 _leave(" = 0 [done]");
332 return 0;
333}
334
335/*
336 * FS.FetchStatus operation type
337 */
David Howells5cf9dd52018-04-09 21:12:31 +0100338static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
339 .name = "FS.FetchStatus(vnode)",
David Howells025db802017-11-02 15:27:51 +0000340 .op = afs_FS_FetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100341 .deliver = afs_deliver_fs_fetch_status_vnode,
David Howells08e0e7c2007-04-26 15:55:03 -0700342 .destructor = afs_flat_call_destructor,
343};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345/*
346 * fetch the status information for a file
347 */
David Howellsd2ddc772017-11-02 15:27:50 +0000348int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349{
David Howellsd2ddc772017-11-02 15:27:50 +0000350 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700351 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000352 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 __be32 *bp;
354
David Howells416351f2007-05-09 02:33:45 -0700355 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000356 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
David Howells5cf9dd52018-04-09 21:12:31 +0100358 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
359 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000360 if (!call) {
361 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700362 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
David Howellsd2ddc772017-11-02 15:27:50 +0000365 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000366 call->reply[0] = vnode;
367 call->reply[1] = volsync;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
369 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700370 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 bp[0] = htonl(FSFETCHSTATUS);
372 bp[1] = htonl(vnode->fid.vid);
373 bp[2] = htonl(vnode->fid.vnode);
374 bp[3] = htonl(vnode->fid.unique);
375
David Howellsd2ddc772017-11-02 15:27:50 +0000376 call->cb_break = fc->cb_break;
377 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000378 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000379 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700380}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382/*
David Howells08e0e7c2007-04-26 15:55:03 -0700383 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 */
David Howellsd0016482016-08-30 20:42:14 +0100385static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
David Howells97e30432017-11-02 15:27:48 +0000387 struct afs_vnode *vnode = call->reply[0];
388 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700389 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000390 unsigned int size;
David Howells08e0e7c2007-04-26 15:55:03 -0700391 void *buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700393
David Howells6a0e3992017-03-16 16:27:46 +0000394 _enter("{%u,%zu/%u;%llu/%llu}",
David Howells196ee9c2017-01-05 10:38:34 +0000395 call->unmarshall, call->offset, call->count,
396 req->remain, req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700397
398 switch (call->unmarshall) {
399 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000400 req->actual_len = 0;
David Howells08e0e7c2007-04-26 15:55:03 -0700401 call->offset = 0;
402 call->unmarshall++;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700403 if (call->operation_ID != FSFETCHDATA64) {
404 call->unmarshall++;
405 goto no_msw;
406 }
David Howells08e0e7c2007-04-26 15:55:03 -0700407
David Howellsb9b1f8d2007-05-10 03:15:21 -0700408 /* extract the upper part of the returned data length of an
409 * FSFETCHDATA64 op (which should always be 0 using this
410 * client) */
David Howells08e0e7c2007-04-26 15:55:03 -0700411 case 1:
David Howellsb9b1f8d2007-05-10 03:15:21 -0700412 _debug("extract data length (MSW)");
David Howellsd0016482016-08-30 20:42:14 +0100413 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100414 if (ret < 0)
415 return ret;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700416
David Howells196ee9c2017-01-05 10:38:34 +0000417 req->actual_len = ntohl(call->tmp);
418 req->actual_len <<= 32;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700419 call->offset = 0;
420 call->unmarshall++;
421
422 no_msw:
423 /* extract the returned data length */
424 case 2:
David Howells08e0e7c2007-04-26 15:55:03 -0700425 _debug("extract data length");
David Howellsd0016482016-08-30 20:42:14 +0100426 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100427 if (ret < 0)
428 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700429
David Howells196ee9c2017-01-05 10:38:34 +0000430 req->actual_len |= ntohl(call->tmp);
431 _debug("DATA length: %llu", req->actual_len);
David Howells196ee9c2017-01-05 10:38:34 +0000432
433 req->remain = req->actual_len;
434 call->offset = req->pos & (PAGE_SIZE - 1);
435 req->index = 0;
436 if (req->actual_len == 0)
437 goto no_more_data;
David Howells08e0e7c2007-04-26 15:55:03 -0700438 call->unmarshall++;
439
David Howells196ee9c2017-01-05 10:38:34 +0000440 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000441 ASSERTCMP(req->index, <, req->nr_pages);
David Howells196ee9c2017-01-05 10:38:34 +0000442 if (req->remain > PAGE_SIZE - call->offset)
443 size = PAGE_SIZE - call->offset;
444 else
445 size = req->remain;
446 call->count = call->offset + size;
447 ASSERTCMP(call->count, <=, PAGE_SIZE);
448 req->remain -= size;
449
David Howells08e0e7c2007-04-26 15:55:03 -0700450 /* extract the returned data */
David Howellsb9b1f8d2007-05-10 03:15:21 -0700451 case 3:
David Howells6a0e3992017-03-16 16:27:46 +0000452 _debug("extract data %llu/%llu %zu/%u",
David Howells196ee9c2017-01-05 10:38:34 +0000453 req->remain, req->actual_len, call->offset, call->count);
454
455 buffer = kmap(req->pages[req->index]);
456 ret = afs_extract_data(call, buffer, call->count, true);
457 kunmap(req->pages[req->index]);
458 if (ret < 0)
459 return ret;
460 if (call->offset == PAGE_SIZE) {
461 if (req->page_done)
462 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000463 req->index++;
David Howells196ee9c2017-01-05 10:38:34 +0000464 if (req->remain > 0) {
David Howells196ee9c2017-01-05 10:38:34 +0000465 call->offset = 0;
David Howellse8e581a2017-03-16 16:27:44 +0000466 if (req->index >= req->nr_pages) {
467 call->unmarshall = 4;
David Howells6db3ac32017-03-16 16:27:44 +0000468 goto begin_discard;
David Howellse8e581a2017-03-16 16:27:44 +0000469 }
David Howells196ee9c2017-01-05 10:38:34 +0000470 goto begin_page;
471 }
David Howells08e0e7c2007-04-26 15:55:03 -0700472 }
David Howells6db3ac32017-03-16 16:27:44 +0000473 goto no_more_data;
474
475 /* Discard any excess data the server gave us */
476 begin_discard:
477 case 4:
David Howells6a0e3992017-03-16 16:27:46 +0000478 size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
David Howells6db3ac32017-03-16 16:27:44 +0000479 call->count = size;
David Howells6a0e3992017-03-16 16:27:46 +0000480 _debug("extract discard %llu/%llu %zu/%u",
David Howells6db3ac32017-03-16 16:27:44 +0000481 req->remain, req->actual_len, call->offset, call->count);
482
483 call->offset = 0;
484 ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
485 req->remain -= call->offset;
486 if (ret < 0)
487 return ret;
488 if (req->remain > 0)
489 goto begin_discard;
David Howells08e0e7c2007-04-26 15:55:03 -0700490
David Howells196ee9c2017-01-05 10:38:34 +0000491 no_more_data:
David Howells08e0e7c2007-04-26 15:55:03 -0700492 call->offset = 0;
David Howells6db3ac32017-03-16 16:27:44 +0000493 call->unmarshall = 5;
David Howells08e0e7c2007-04-26 15:55:03 -0700494
495 /* extract the metadata */
David Howells6db3ac32017-03-16 16:27:44 +0000496 case 5:
David Howellsd0016482016-08-30 20:42:14 +0100497 ret = afs_extract_data(call, call->buffer,
498 (21 + 3 + 6) * 4, false);
David Howells372ee162016-08-03 14:11:40 +0100499 if (ret < 0)
500 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700501
502 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700503 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howellsc435ee32017-11-02 15:27:49 +0000504 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000505 if (call->reply[1])
506 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700507
508 call->offset = 0;
509 call->unmarshall++;
510
David Howells6db3ac32017-03-16 16:27:44 +0000511 case 6:
David Howells08e0e7c2007-04-26 15:55:03 -0700512 break;
513 }
514
David Howells6db3ac32017-03-16 16:27:44 +0000515 for (; req->index < req->nr_pages; req->index++) {
516 if (call->count < PAGE_SIZE)
517 zero_user_segment(req->pages[req->index],
518 call->count, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000519 if (req->page_done)
520 req->page_done(call, req);
David Howells6db3ac32017-03-16 16:27:44 +0000521 call->count = 0;
David Howells416351f2007-05-09 02:33:45 -0700522 }
523
David Howells08e0e7c2007-04-26 15:55:03 -0700524 _leave(" = 0 [done]");
525 return 0;
526}
527
David Howells196ee9c2017-01-05 10:38:34 +0000528static void afs_fetch_data_destructor(struct afs_call *call)
529{
David Howells97e30432017-11-02 15:27:48 +0000530 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000531
532 afs_put_read(req);
533 afs_flat_call_destructor(call);
534}
535
David Howells08e0e7c2007-04-26 15:55:03 -0700536/*
537 * FS.FetchData operation type
538 */
539static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700540 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000541 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700542 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000543 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700544};
545
David Howellsb9b1f8d2007-05-10 03:15:21 -0700546static const struct afs_call_type afs_RXFSFetchData64 = {
547 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000548 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700549 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000550 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700551};
552
553/*
554 * fetch data from a very large file
555 */
David Howellsd2ddc772017-11-02 15:27:50 +0000556static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700557{
David Howellsd2ddc772017-11-02 15:27:50 +0000558 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700559 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000560 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700561 __be32 *bp;
562
563 _enter("");
564
David Howellsf044c882017-11-02 15:27:45 +0000565 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700566 if (!call)
567 return -ENOMEM;
568
David Howellsd2ddc772017-11-02 15:27:50 +0000569 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000570 call->reply[0] = vnode;
571 call->reply[1] = NULL; /* volsync */
572 call->reply[2] = req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700573
574 /* marshall the parameters */
575 bp = call->request;
576 bp[0] = htonl(FSFETCHDATA64);
577 bp[1] = htonl(vnode->fid.vid);
578 bp[2] = htonl(vnode->fid.vnode);
579 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000580 bp[4] = htonl(upper_32_bits(req->pos));
581 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700582 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000583 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700584
David Howells196ee9c2017-01-05 10:38:34 +0000585 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000586 call->cb_break = fc->cb_break;
587 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000588 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000589 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700590}
591
David Howells08e0e7c2007-04-26 15:55:03 -0700592/*
593 * fetch data from a file
594 */
David Howellsd2ddc772017-11-02 15:27:50 +0000595int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700596{
David Howellsd2ddc772017-11-02 15:27:50 +0000597 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700598 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000599 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 __be32 *bp;
601
David Howells196ee9c2017-01-05 10:38:34 +0000602 if (upper_32_bits(req->pos) ||
603 upper_32_bits(req->len) ||
604 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000605 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700606
David Howells08e0e7c2007-04-26 15:55:03 -0700607 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
David Howellsf044c882017-11-02 15:27:45 +0000609 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700610 if (!call)
611 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
David Howellsd2ddc772017-11-02 15:27:50 +0000613 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000614 call->reply[0] = vnode;
615 call->reply[1] = NULL; /* volsync */
616 call->reply[2] = req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
618 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700619 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700621 bp[1] = htonl(vnode->fid.vid);
622 bp[2] = htonl(vnode->fid.vnode);
623 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000624 bp[4] = htonl(lower_32_bits(req->pos));
625 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
David Howells196ee9c2017-01-05 10:38:34 +0000627 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000628 call->cb_break = fc->cb_break;
629 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000630 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000631 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700632}
David Howells260a9802007-04-26 15:59:35 -0700633
634/*
635 * deliver reply data to an FS.CreateFile or an FS.MakeDir
636 */
David Howellsd0016482016-08-30 20:42:14 +0100637static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700638{
David Howells97e30432017-11-02 15:27:48 +0000639 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700640 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100641 int ret;
David Howells260a9802007-04-26 15:59:35 -0700642
David Howellsd0016482016-08-30 20:42:14 +0100643 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700644
David Howellsd0016482016-08-30 20:42:14 +0100645 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100646 if (ret < 0)
647 return ret;
David Howells260a9802007-04-26 15:59:35 -0700648
649 /* unmarshall the reply once we've received all of it */
650 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000651 xdr_decode_AFSFid(&bp, call->reply[1]);
652 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700653 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000654 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
655 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700656
657 _leave(" = 0 [done]");
658 return 0;
659}
660
661/*
662 * FS.CreateFile and FS.MakeDir operation type
663 */
David Howells025db802017-11-02 15:27:51 +0000664static const struct afs_call_type afs_RXFSCreateFile = {
665 .name = "FS.CreateFile",
666 .op = afs_FS_CreateFile,
667 .deliver = afs_deliver_fs_create_vnode,
668 .destructor = afs_flat_call_destructor,
669};
670
671static const struct afs_call_type afs_RXFSMakeDir = {
672 .name = "FS.MakeDir",
673 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700674 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700675 .destructor = afs_flat_call_destructor,
676};
677
678/*
679 * create a file or make a directory
680 */
David Howells8b2a4642017-11-02 15:27:50 +0000681int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700682 const char *name,
683 umode_t mode,
684 struct afs_fid *newfid,
685 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000686 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700687{
David Howellsd2ddc772017-11-02 15:27:50 +0000688 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700689 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000690 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700691 size_t namesz, reqsz, padsz;
692 __be32 *bp;
693
694 _enter("");
695
696 namesz = strlen(name);
697 padsz = (4 - (namesz & 3)) & 3;
698 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
699
David Howells025db802017-11-02 15:27:51 +0000700 call = afs_alloc_flat_call(
701 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
702 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700703 if (!call)
704 return -ENOMEM;
705
David Howellsd2ddc772017-11-02 15:27:50 +0000706 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000707 call->reply[0] = vnode;
708 call->reply[1] = newfid;
709 call->reply[2] = newstatus;
710 call->reply[3] = newcb;
David Howells260a9802007-04-26 15:59:35 -0700711
712 /* marshall the parameters */
713 bp = call->request;
714 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
715 *bp++ = htonl(vnode->fid.vid);
716 *bp++ = htonl(vnode->fid.vnode);
717 *bp++ = htonl(vnode->fid.unique);
718 *bp++ = htonl(namesz);
719 memcpy(bp, name, namesz);
720 bp = (void *) bp + namesz;
721 if (padsz > 0) {
722 memset(bp, 0, padsz);
723 bp = (void *) bp + padsz;
724 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000725 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
726 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700727 *bp++ = 0; /* owner */
728 *bp++ = 0; /* group */
729 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
730 *bp++ = 0; /* segment size */
731
David Howellsd2ddc772017-11-02 15:27:50 +0000732 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000733 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000734 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700735}
736
737/*
738 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
739 */
David Howellsd0016482016-08-30 20:42:14 +0100740static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700741{
David Howells97e30432017-11-02 15:27:48 +0000742 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700743 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100744 int ret;
David Howells260a9802007-04-26 15:59:35 -0700745
David Howellsd0016482016-08-30 20:42:14 +0100746 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700747
David Howellsd0016482016-08-30 20:42:14 +0100748 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100749 if (ret < 0)
750 return ret;
David Howells260a9802007-04-26 15:59:35 -0700751
752 /* unmarshall the reply once we've received all of it */
753 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700754 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000755 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700756
757 _leave(" = 0 [done]");
758 return 0;
759}
760
761/*
762 * FS.RemoveDir/FS.RemoveFile operation type
763 */
David Howells025db802017-11-02 15:27:51 +0000764static const struct afs_call_type afs_RXFSRemoveFile = {
765 .name = "FS.RemoveFile",
766 .op = afs_FS_RemoveFile,
767 .deliver = afs_deliver_fs_remove,
768 .destructor = afs_flat_call_destructor,
769};
770
771static const struct afs_call_type afs_RXFSRemoveDir = {
772 .name = "FS.RemoveDir",
773 .op = afs_FS_RemoveDir,
David Howells260a9802007-04-26 15:59:35 -0700774 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700775 .destructor = afs_flat_call_destructor,
776};
777
778/*
779 * remove a file or directory
780 */
David Howellsd2ddc772017-11-02 15:27:50 +0000781int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir)
David Howells260a9802007-04-26 15:59:35 -0700782{
David Howellsd2ddc772017-11-02 15:27:50 +0000783 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700784 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000785 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700786 size_t namesz, reqsz, padsz;
787 __be32 *bp;
788
789 _enter("");
790
791 namesz = strlen(name);
792 padsz = (4 - (namesz & 3)) & 3;
793 reqsz = (5 * 4) + namesz + padsz;
794
David Howells025db802017-11-02 15:27:51 +0000795 call = afs_alloc_flat_call(
796 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
797 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700798 if (!call)
799 return -ENOMEM;
800
David Howellsd2ddc772017-11-02 15:27:50 +0000801 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000802 call->reply[0] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700803
804 /* marshall the parameters */
805 bp = call->request;
806 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
807 *bp++ = htonl(vnode->fid.vid);
808 *bp++ = htonl(vnode->fid.vnode);
809 *bp++ = htonl(vnode->fid.unique);
810 *bp++ = htonl(namesz);
811 memcpy(bp, name, namesz);
812 bp = (void *) bp + namesz;
813 if (padsz > 0) {
814 memset(bp, 0, padsz);
815 bp = (void *) bp + padsz;
816 }
817
David Howellsd2ddc772017-11-02 15:27:50 +0000818 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000819 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000820 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700821}
822
823/*
824 * deliver reply data to an FS.Link
825 */
David Howellsd0016482016-08-30 20:42:14 +0100826static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700827{
David Howells97e30432017-11-02 15:27:48 +0000828 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700829 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100830 int ret;
David Howells260a9802007-04-26 15:59:35 -0700831
David Howellsd0016482016-08-30 20:42:14 +0100832 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700833
David Howellsd0016482016-08-30 20:42:14 +0100834 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100835 if (ret < 0)
836 return ret;
David Howells260a9802007-04-26 15:59:35 -0700837
838 /* unmarshall the reply once we've received all of it */
839 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700840 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
841 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000842 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700843
844 _leave(" = 0 [done]");
845 return 0;
846}
847
848/*
849 * FS.Link operation type
850 */
851static const struct afs_call_type afs_RXFSLink = {
852 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000853 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700854 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700855 .destructor = afs_flat_call_destructor,
856};
857
858/*
859 * make a hard link
860 */
David Howellsd2ddc772017-11-02 15:27:50 +0000861int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
862 const char *name)
David Howells260a9802007-04-26 15:59:35 -0700863{
David Howellsd2ddc772017-11-02 15:27:50 +0000864 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700865 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000866 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700867 size_t namesz, reqsz, padsz;
868 __be32 *bp;
869
870 _enter("");
871
872 namesz = strlen(name);
873 padsz = (4 - (namesz & 3)) & 3;
874 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
875
David Howellsf044c882017-11-02 15:27:45 +0000876 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700877 if (!call)
878 return -ENOMEM;
879
David Howellsd2ddc772017-11-02 15:27:50 +0000880 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000881 call->reply[0] = dvnode;
882 call->reply[1] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700883
884 /* marshall the parameters */
885 bp = call->request;
886 *bp++ = htonl(FSLINK);
887 *bp++ = htonl(dvnode->fid.vid);
888 *bp++ = htonl(dvnode->fid.vnode);
889 *bp++ = htonl(dvnode->fid.unique);
890 *bp++ = htonl(namesz);
891 memcpy(bp, name, namesz);
892 bp = (void *) bp + namesz;
893 if (padsz > 0) {
894 memset(bp, 0, padsz);
895 bp = (void *) bp + padsz;
896 }
897 *bp++ = htonl(vnode->fid.vid);
898 *bp++ = htonl(vnode->fid.vnode);
899 *bp++ = htonl(vnode->fid.unique);
900
David Howellsd2ddc772017-11-02 15:27:50 +0000901 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000902 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000903 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700904}
905
906/*
907 * deliver reply data to an FS.Symlink
908 */
David Howellsd0016482016-08-30 20:42:14 +0100909static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700910{
David Howells97e30432017-11-02 15:27:48 +0000911 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700912 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100913 int ret;
David Howells260a9802007-04-26 15:59:35 -0700914
David Howellsd0016482016-08-30 20:42:14 +0100915 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700916
David Howellsd0016482016-08-30 20:42:14 +0100917 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100918 if (ret < 0)
919 return ret;
David Howells260a9802007-04-26 15:59:35 -0700920
921 /* unmarshall the reply once we've received all of it */
922 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000923 xdr_decode_AFSFid(&bp, call->reply[1]);
924 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700925 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000926 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700927
928 _leave(" = 0 [done]");
929 return 0;
930}
931
932/*
933 * FS.Symlink operation type
934 */
935static const struct afs_call_type afs_RXFSSymlink = {
936 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +0000937 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -0700938 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700939 .destructor = afs_flat_call_destructor,
940};
941
942/*
943 * create a symbolic link
944 */
David Howells8b2a4642017-11-02 15:27:50 +0000945int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700946 const char *name,
947 const char *contents,
948 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +0000949 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -0700950{
David Howellsd2ddc772017-11-02 15:27:50 +0000951 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700952 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000953 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700954 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
955 __be32 *bp;
956
957 _enter("");
958
959 namesz = strlen(name);
960 padsz = (4 - (namesz & 3)) & 3;
961
962 c_namesz = strlen(contents);
963 c_padsz = (4 - (c_namesz & 3)) & 3;
964
965 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
966
David Howellsf044c882017-11-02 15:27:45 +0000967 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700968 (3 + 21 + 21 + 6) * 4);
969 if (!call)
970 return -ENOMEM;
971
David Howellsd2ddc772017-11-02 15:27:50 +0000972 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000973 call->reply[0] = vnode;
974 call->reply[1] = newfid;
975 call->reply[2] = newstatus;
David Howells260a9802007-04-26 15:59:35 -0700976
977 /* marshall the parameters */
978 bp = call->request;
979 *bp++ = htonl(FSSYMLINK);
980 *bp++ = htonl(vnode->fid.vid);
981 *bp++ = htonl(vnode->fid.vnode);
982 *bp++ = htonl(vnode->fid.unique);
983 *bp++ = htonl(namesz);
984 memcpy(bp, name, namesz);
985 bp = (void *) bp + namesz;
986 if (padsz > 0) {
987 memset(bp, 0, padsz);
988 bp = (void *) bp + padsz;
989 }
990 *bp++ = htonl(c_namesz);
991 memcpy(bp, contents, c_namesz);
992 bp = (void *) bp + c_namesz;
993 if (c_padsz > 0) {
994 memset(bp, 0, c_padsz);
995 bp = (void *) bp + c_padsz;
996 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000997 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
998 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700999 *bp++ = 0; /* owner */
1000 *bp++ = 0; /* group */
1001 *bp++ = htonl(S_IRWXUGO); /* unix mode */
1002 *bp++ = 0; /* segment size */
1003
David Howellsd2ddc772017-11-02 15:27:50 +00001004 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001005 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001006 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001007}
1008
1009/*
1010 * deliver reply data to an FS.Rename
1011 */
David Howellsd0016482016-08-30 20:42:14 +01001012static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001013{
David Howells97e30432017-11-02 15:27:48 +00001014 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -07001015 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001016 int ret;
David Howells260a9802007-04-26 15:59:35 -07001017
David Howellsd0016482016-08-30 20:42:14 +01001018 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001019
David Howellsd0016482016-08-30 20:42:14 +01001020 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001021 if (ret < 0)
1022 return ret;
David Howells260a9802007-04-26 15:59:35 -07001023
1024 /* unmarshall the reply once we've received all of it */
1025 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -07001026 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
David Howells260a9802007-04-26 15:59:35 -07001027 if (new_dvnode != orig_dvnode)
David Howells31143d52007-05-09 02:33:46 -07001028 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
1029 NULL);
David Howells97e30432017-11-02 15:27:48 +00001030 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001031
1032 _leave(" = 0 [done]");
1033 return 0;
1034}
1035
1036/*
1037 * FS.Rename operation type
1038 */
1039static const struct afs_call_type afs_RXFSRename = {
1040 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001041 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001042 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001043 .destructor = afs_flat_call_destructor,
1044};
1045
1046/*
1047 * create a symbolic link
1048 */
David Howells8b2a4642017-11-02 15:27:50 +00001049int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001050 const char *orig_name,
1051 struct afs_vnode *new_dvnode,
David Howellsd2ddc772017-11-02 15:27:50 +00001052 const char *new_name)
David Howells260a9802007-04-26 15:59:35 -07001053{
David Howellsd2ddc772017-11-02 15:27:50 +00001054 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001055 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001056 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001057 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1058 __be32 *bp;
1059
1060 _enter("");
1061
1062 o_namesz = strlen(orig_name);
1063 o_padsz = (4 - (o_namesz & 3)) & 3;
1064
1065 n_namesz = strlen(new_name);
1066 n_padsz = (4 - (n_namesz & 3)) & 3;
1067
1068 reqsz = (4 * 4) +
1069 4 + o_namesz + o_padsz +
1070 (3 * 4) +
1071 4 + n_namesz + n_padsz;
1072
David Howellsf044c882017-11-02 15:27:45 +00001073 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001074 if (!call)
1075 return -ENOMEM;
1076
David Howellsd2ddc772017-11-02 15:27:50 +00001077 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001078 call->reply[0] = orig_dvnode;
1079 call->reply[1] = new_dvnode;
David Howells260a9802007-04-26 15:59:35 -07001080
1081 /* marshall the parameters */
1082 bp = call->request;
1083 *bp++ = htonl(FSRENAME);
1084 *bp++ = htonl(orig_dvnode->fid.vid);
1085 *bp++ = htonl(orig_dvnode->fid.vnode);
1086 *bp++ = htonl(orig_dvnode->fid.unique);
1087 *bp++ = htonl(o_namesz);
1088 memcpy(bp, orig_name, o_namesz);
1089 bp = (void *) bp + o_namesz;
1090 if (o_padsz > 0) {
1091 memset(bp, 0, o_padsz);
1092 bp = (void *) bp + o_padsz;
1093 }
1094
1095 *bp++ = htonl(new_dvnode->fid.vid);
1096 *bp++ = htonl(new_dvnode->fid.vnode);
1097 *bp++ = htonl(new_dvnode->fid.unique);
1098 *bp++ = htonl(n_namesz);
1099 memcpy(bp, new_name, n_namesz);
1100 bp = (void *) bp + n_namesz;
1101 if (n_padsz > 0) {
1102 memset(bp, 0, n_padsz);
1103 bp = (void *) bp + n_padsz;
1104 }
1105
David Howellsd2ddc772017-11-02 15:27:50 +00001106 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001107 trace_afs_make_fs_call(call, &orig_dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001108 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001109}
David Howells31143d52007-05-09 02:33:46 -07001110
1111/*
1112 * deliver reply data to an FS.StoreData
1113 */
David Howellsd0016482016-08-30 20:42:14 +01001114static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001115{
David Howells97e30432017-11-02 15:27:48 +00001116 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001117 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001118 int ret;
David Howells31143d52007-05-09 02:33:46 -07001119
David Howellsd0016482016-08-30 20:42:14 +01001120 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001121
David Howellsd0016482016-08-30 20:42:14 +01001122 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001123 if (ret < 0)
1124 return ret;
David Howells31143d52007-05-09 02:33:46 -07001125
1126 /* unmarshall the reply once we've received all of it */
1127 bp = call->buffer;
1128 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1129 &call->store_version);
David Howells97e30432017-11-02 15:27:48 +00001130 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001131
1132 afs_pages_written_back(vnode, call);
1133
1134 _leave(" = 0 [done]");
1135 return 0;
1136}
1137
1138/*
1139 * FS.StoreData operation type
1140 */
1141static const struct afs_call_type afs_RXFSStoreData = {
1142 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001143 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001144 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001145 .destructor = afs_flat_call_destructor,
1146};
1147
David Howellsb9b1f8d2007-05-10 03:15:21 -07001148static const struct afs_call_type afs_RXFSStoreData64 = {
1149 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001150 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001151 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001152 .destructor = afs_flat_call_destructor,
1153};
1154
1155/*
1156 * store a set of pages to a very large file
1157 */
David Howells8b2a4642017-11-02 15:27:50 +00001158static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001159 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001160 pgoff_t first, pgoff_t last,
1161 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001162 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001163{
David Howells4343d002017-11-02 15:27:52 +00001164 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001165 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001166 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001167 __be32 *bp;
1168
1169 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001170 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001171
David Howellsf044c882017-11-02 15:27:45 +00001172 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001173 (4 + 6 + 3 * 2) * 4,
1174 (21 + 6) * 4);
1175 if (!call)
1176 return -ENOMEM;
1177
David Howells4343d002017-11-02 15:27:52 +00001178 call->key = fc->key;
1179 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001180 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001181 call->first = first;
1182 call->last = last;
1183 call->first_offset = offset;
1184 call->last_to = to;
1185 call->send_pages = true;
1186 call->store_version = vnode->status.data_version + 1;
1187
1188 /* marshall the parameters */
1189 bp = call->request;
1190 *bp++ = htonl(FSSTOREDATA64);
1191 *bp++ = htonl(vnode->fid.vid);
1192 *bp++ = htonl(vnode->fid.vnode);
1193 *bp++ = htonl(vnode->fid.unique);
1194
Marc Dionneab94f5d2017-03-16 16:27:47 +00001195 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1196 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001197 *bp++ = 0; /* owner */
1198 *bp++ = 0; /* group */
1199 *bp++ = 0; /* unix mode */
1200 *bp++ = 0; /* segment size */
1201
1202 *bp++ = htonl(pos >> 32);
1203 *bp++ = htonl((u32) pos);
1204 *bp++ = htonl(size >> 32);
1205 *bp++ = htonl((u32) size);
1206 *bp++ = htonl(i_size >> 32);
1207 *bp++ = htonl((u32) i_size);
1208
David Howells025db802017-11-02 15:27:51 +00001209 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001210 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001211}
1212
David Howells31143d52007-05-09 02:33:46 -07001213/*
1214 * store a set of pages
1215 */
David Howells4343d002017-11-02 15:27:52 +00001216int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001217 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001218 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001219{
David Howells4343d002017-11-02 15:27:52 +00001220 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001221 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001222 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001223 loff_t size, pos, i_size;
1224 __be32 *bp;
1225
1226 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001227 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001228
David Howells146a1192017-03-16 16:27:47 +00001229 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001230 if (first != last)
1231 size += (loff_t)(last - first) << PAGE_SHIFT;
1232 pos = (loff_t)first << PAGE_SHIFT;
1233 pos += offset;
1234
1235 i_size = i_size_read(&vnode->vfs_inode);
1236 if (pos + size > i_size)
1237 i_size = size + pos;
1238
1239 _debug("size %llx, at %llx, i_size %llx",
1240 (unsigned long long) size, (unsigned long long) pos,
1241 (unsigned long long) i_size);
1242
David Howellsb9b1f8d2007-05-10 03:15:21 -07001243 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001244 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001245 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001246
David Howellsf044c882017-11-02 15:27:45 +00001247 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001248 (4 + 6 + 3) * 4,
1249 (21 + 6) * 4);
1250 if (!call)
1251 return -ENOMEM;
1252
David Howells4343d002017-11-02 15:27:52 +00001253 call->key = fc->key;
1254 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001255 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001256 call->first = first;
1257 call->last = last;
1258 call->first_offset = offset;
1259 call->last_to = to;
1260 call->send_pages = true;
1261 call->store_version = vnode->status.data_version + 1;
1262
1263 /* marshall the parameters */
1264 bp = call->request;
1265 *bp++ = htonl(FSSTOREDATA);
1266 *bp++ = htonl(vnode->fid.vid);
1267 *bp++ = htonl(vnode->fid.vnode);
1268 *bp++ = htonl(vnode->fid.unique);
1269
Marc Dionneab94f5d2017-03-16 16:27:47 +00001270 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1271 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001272 *bp++ = 0; /* owner */
1273 *bp++ = 0; /* group */
1274 *bp++ = 0; /* unix mode */
1275 *bp++ = 0; /* segment size */
1276
1277 *bp++ = htonl(pos);
1278 *bp++ = htonl(size);
1279 *bp++ = htonl(i_size);
1280
David Howellsd2ddc772017-11-02 15:27:50 +00001281 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001282 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001283 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001284}
1285
1286/*
1287 * deliver reply data to an FS.StoreStatus
1288 */
David Howellsd0016482016-08-30 20:42:14 +01001289static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001290{
1291 afs_dataversion_t *store_version;
David Howells97e30432017-11-02 15:27:48 +00001292 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001293 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001294 int ret;
David Howells31143d52007-05-09 02:33:46 -07001295
David Howellsd0016482016-08-30 20:42:14 +01001296 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001297
David Howellsd0016482016-08-30 20:42:14 +01001298 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001299 if (ret < 0)
1300 return ret;
David Howells31143d52007-05-09 02:33:46 -07001301
1302 /* unmarshall the reply once we've received all of it */
1303 store_version = NULL;
1304 if (call->operation_ID == FSSTOREDATA)
1305 store_version = &call->store_version;
1306
1307 bp = call->buffer;
1308 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
David Howells97e30432017-11-02 15:27:48 +00001309 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001310
1311 _leave(" = 0 [done]");
1312 return 0;
1313}
1314
1315/*
1316 * FS.StoreStatus operation type
1317 */
1318static const struct afs_call_type afs_RXFSStoreStatus = {
1319 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001320 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001321 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001322 .destructor = afs_flat_call_destructor,
1323};
1324
1325static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1326 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001327 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001328 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001329 .destructor = afs_flat_call_destructor,
1330};
1331
David Howellsb9b1f8d2007-05-10 03:15:21 -07001332static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1333 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001334 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001335 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001336 .destructor = afs_flat_call_destructor,
1337};
1338
1339/*
1340 * set the attributes on a very large file, using FS.StoreData rather than
1341 * FS.StoreStatus so as to alter the file size also
1342 */
David Howellsd2ddc772017-11-02 15:27:50 +00001343static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001344{
David Howellsd2ddc772017-11-02 15:27:50 +00001345 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001346 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001347 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001348 __be32 *bp;
1349
1350 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001351 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001352
1353 ASSERT(attr->ia_valid & ATTR_SIZE);
1354
David Howellsf044c882017-11-02 15:27:45 +00001355 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001356 (4 + 6 + 3 * 2) * 4,
1357 (21 + 6) * 4);
1358 if (!call)
1359 return -ENOMEM;
1360
David Howellsd2ddc772017-11-02 15:27:50 +00001361 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001362 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001363 call->store_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001364
1365 /* marshall the parameters */
1366 bp = call->request;
1367 *bp++ = htonl(FSSTOREDATA64);
1368 *bp++ = htonl(vnode->fid.vid);
1369 *bp++ = htonl(vnode->fid.vnode);
1370 *bp++ = htonl(vnode->fid.unique);
1371
1372 xdr_encode_AFS_StoreStatus(&bp, attr);
1373
1374 *bp++ = 0; /* position of start of write */
1375 *bp++ = 0;
1376 *bp++ = 0; /* size of write */
1377 *bp++ = 0;
1378 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1379 *bp++ = htonl((u32) attr->ia_size);
1380
David Howellsd2ddc772017-11-02 15:27:50 +00001381 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001382 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001383 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001384}
1385
David Howells31143d52007-05-09 02:33:46 -07001386/*
1387 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1388 * so as to alter the file size also
1389 */
David Howellsd2ddc772017-11-02 15:27:50 +00001390static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001391{
David Howellsd2ddc772017-11-02 15:27:50 +00001392 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001393 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001394 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001395 __be32 *bp;
1396
1397 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001398 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001399
1400 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001401 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001402 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001403
David Howellsf044c882017-11-02 15:27:45 +00001404 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001405 (4 + 6 + 3) * 4,
1406 (21 + 6) * 4);
1407 if (!call)
1408 return -ENOMEM;
1409
David Howellsd2ddc772017-11-02 15:27:50 +00001410 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001411 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001412 call->store_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001413
1414 /* marshall the parameters */
1415 bp = call->request;
1416 *bp++ = htonl(FSSTOREDATA);
1417 *bp++ = htonl(vnode->fid.vid);
1418 *bp++ = htonl(vnode->fid.vnode);
1419 *bp++ = htonl(vnode->fid.unique);
1420
1421 xdr_encode_AFS_StoreStatus(&bp, attr);
1422
1423 *bp++ = 0; /* position of start of write */
1424 *bp++ = 0; /* size of write */
1425 *bp++ = htonl(attr->ia_size); /* new file length */
1426
David Howellsd2ddc772017-11-02 15:27:50 +00001427 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001428 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001429 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001430}
1431
1432/*
1433 * set the attributes on a file, using FS.StoreData if there's a change in file
1434 * size, and FS.StoreStatus otherwise
1435 */
David Howellsd2ddc772017-11-02 15:27:50 +00001436int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001437{
David Howellsd2ddc772017-11-02 15:27:50 +00001438 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001439 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001440 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001441 __be32 *bp;
1442
1443 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001444 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001445
1446 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001447 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001448
David Howellsf044c882017-11-02 15:27:45 +00001449 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001450 (4 + 6) * 4,
1451 (21 + 6) * 4);
1452 if (!call)
1453 return -ENOMEM;
1454
David Howellsd2ddc772017-11-02 15:27:50 +00001455 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001456 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001457
1458 /* marshall the parameters */
1459 bp = call->request;
1460 *bp++ = htonl(FSSTORESTATUS);
1461 *bp++ = htonl(vnode->fid.vid);
1462 *bp++ = htonl(vnode->fid.vnode);
1463 *bp++ = htonl(vnode->fid.unique);
1464
1465 xdr_encode_AFS_StoreStatus(&bp, attr);
1466
David Howellsd2ddc772017-11-02 15:27:50 +00001467 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001468 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001469 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001470}
David Howells45222b92007-05-10 22:22:20 -07001471
1472/*
1473 * deliver reply data to an FS.GetVolumeStatus
1474 */
David Howellsd0016482016-08-30 20:42:14 +01001475static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001476{
1477 const __be32 *bp;
1478 char *p;
1479 int ret;
1480
David Howellsd0016482016-08-30 20:42:14 +01001481 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001482
1483 switch (call->unmarshall) {
1484 case 0:
1485 call->offset = 0;
1486 call->unmarshall++;
1487
1488 /* extract the returned status record */
1489 case 1:
1490 _debug("extract status");
David Howellsd0016482016-08-30 20:42:14 +01001491 ret = afs_extract_data(call, call->buffer,
1492 12 * 4, true);
David Howells372ee162016-08-03 14:11:40 +01001493 if (ret < 0)
1494 return ret;
David Howells45222b92007-05-10 22:22:20 -07001495
1496 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001497 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001498 call->offset = 0;
1499 call->unmarshall++;
1500
1501 /* extract the volume name length */
1502 case 2:
David Howellsd0016482016-08-30 20:42:14 +01001503 ret = afs_extract_data(call, &call->tmp, 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 call->count = ntohl(call->tmp);
1508 _debug("volname length: %u", call->count);
1509 if (call->count >= AFSNAMEMAX)
1510 return -EBADMSG;
1511 call->offset = 0;
1512 call->unmarshall++;
1513
1514 /* extract the volume name */
1515 case 3:
1516 _debug("extract volname");
1517 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001518 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001519 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001520 if (ret < 0)
1521 return ret;
David Howells45222b92007-05-10 22:22:20 -07001522 }
1523
David Howells97e30432017-11-02 15:27:48 +00001524 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001525 p[call->count] = 0;
1526 _debug("volname '%s'", p);
1527
1528 call->offset = 0;
1529 call->unmarshall++;
1530
1531 /* extract the volume name padding */
1532 if ((call->count & 3) == 0) {
1533 call->unmarshall++;
1534 goto no_volname_padding;
1535 }
1536 call->count = 4 - (call->count & 3);
1537
1538 case 4:
David Howellsd0016482016-08-30 20:42:14 +01001539 ret = afs_extract_data(call, call->buffer,
1540 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001541 if (ret < 0)
1542 return ret;
David Howells45222b92007-05-10 22:22:20 -07001543
1544 call->offset = 0;
1545 call->unmarshall++;
1546 no_volname_padding:
1547
1548 /* extract the offline message length */
1549 case 5:
David Howellsd0016482016-08-30 20:42:14 +01001550 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001551 if (ret < 0)
1552 return ret;
David Howells45222b92007-05-10 22:22:20 -07001553
1554 call->count = ntohl(call->tmp);
1555 _debug("offline msg length: %u", call->count);
1556 if (call->count >= AFSNAMEMAX)
1557 return -EBADMSG;
1558 call->offset = 0;
1559 call->unmarshall++;
1560
1561 /* extract the offline message */
1562 case 6:
1563 _debug("extract offline");
1564 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001565 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001566 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001567 if (ret < 0)
1568 return ret;
David Howells45222b92007-05-10 22:22:20 -07001569 }
1570
David Howells97e30432017-11-02 15:27:48 +00001571 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001572 p[call->count] = 0;
1573 _debug("offline '%s'", p);
1574
1575 call->offset = 0;
1576 call->unmarshall++;
1577
1578 /* extract the offline message padding */
1579 if ((call->count & 3) == 0) {
1580 call->unmarshall++;
1581 goto no_offline_padding;
1582 }
1583 call->count = 4 - (call->count & 3);
1584
1585 case 7:
David Howellsd0016482016-08-30 20:42:14 +01001586 ret = afs_extract_data(call, call->buffer,
1587 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001588 if (ret < 0)
1589 return ret;
David Howells45222b92007-05-10 22:22:20 -07001590
1591 call->offset = 0;
1592 call->unmarshall++;
1593 no_offline_padding:
1594
1595 /* extract the message of the day length */
1596 case 8:
David Howellsd0016482016-08-30 20:42:14 +01001597 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001598 if (ret < 0)
1599 return ret;
David Howells45222b92007-05-10 22:22:20 -07001600
1601 call->count = ntohl(call->tmp);
1602 _debug("motd length: %u", call->count);
1603 if (call->count >= AFSNAMEMAX)
1604 return -EBADMSG;
1605 call->offset = 0;
1606 call->unmarshall++;
1607
1608 /* extract the message of the day */
1609 case 9:
1610 _debug("extract motd");
1611 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001612 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001613 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001614 if (ret < 0)
1615 return ret;
David Howells45222b92007-05-10 22:22:20 -07001616 }
1617
David Howells97e30432017-11-02 15:27:48 +00001618 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001619 p[call->count] = 0;
1620 _debug("motd '%s'", p);
1621
1622 call->offset = 0;
1623 call->unmarshall++;
1624
1625 /* extract the message of the day padding */
David Howellsd0016482016-08-30 20:42:14 +01001626 call->count = (4 - (call->count & 3)) & 3;
David Howells45222b92007-05-10 22:22:20 -07001627
1628 case 10:
David Howellsd0016482016-08-30 20:42:14 +01001629 ret = afs_extract_data(call, call->buffer,
1630 call->count, false);
David Howells372ee162016-08-03 14:11:40 +01001631 if (ret < 0)
1632 return ret;
David Howells45222b92007-05-10 22:22:20 -07001633
1634 call->offset = 0;
1635 call->unmarshall++;
David Howells45222b92007-05-10 22:22:20 -07001636 case 11:
David Howells45222b92007-05-10 22:22:20 -07001637 break;
1638 }
1639
David Howells45222b92007-05-10 22:22:20 -07001640 _leave(" = 0 [done]");
1641 return 0;
1642}
1643
1644/*
1645 * destroy an FS.GetVolumeStatus call
1646 */
1647static void afs_get_volume_status_call_destructor(struct afs_call *call)
1648{
David Howells97e30432017-11-02 15:27:48 +00001649 kfree(call->reply[2]);
1650 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001651 afs_flat_call_destructor(call);
1652}
1653
1654/*
1655 * FS.GetVolumeStatus operation type
1656 */
1657static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1658 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001659 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001660 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001661 .destructor = afs_get_volume_status_call_destructor,
1662};
1663
1664/*
1665 * fetch the status of a volume
1666 */
David Howells8b2a4642017-11-02 15:27:50 +00001667int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001668 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001669{
David Howellsd2ddc772017-11-02 15:27:50 +00001670 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001671 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001672 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001673 __be32 *bp;
1674 void *tmpbuf;
1675
1676 _enter("");
1677
1678 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1679 if (!tmpbuf)
1680 return -ENOMEM;
1681
David Howellsf044c882017-11-02 15:27:45 +00001682 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001683 if (!call) {
1684 kfree(tmpbuf);
1685 return -ENOMEM;
1686 }
1687
David Howellsd2ddc772017-11-02 15:27:50 +00001688 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001689 call->reply[0] = vnode;
1690 call->reply[1] = vs;
1691 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001692
1693 /* marshall the parameters */
1694 bp = call->request;
1695 bp[0] = htonl(FSGETVOLUMESTATUS);
1696 bp[1] = htonl(vnode->fid.vid);
1697
David Howellsd2ddc772017-11-02 15:27:50 +00001698 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001699 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001700 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells45222b92007-05-10 22:22:20 -07001701}
David Howellse8d6c552007-07-15 23:40:12 -07001702
1703/*
1704 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1705 */
David Howellsd0016482016-08-30 20:42:14 +01001706static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001707{
1708 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001709 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001710
David Howellsd0016482016-08-30 20:42:14 +01001711 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001712
David Howellsd0016482016-08-30 20:42:14 +01001713 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001714 if (ret < 0)
1715 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001716
1717 /* unmarshall the reply once we've received all of it */
1718 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001719 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001720
1721 _leave(" = 0 [done]");
1722 return 0;
1723}
1724
1725/*
1726 * FS.SetLock operation type
1727 */
1728static const struct afs_call_type afs_RXFSSetLock = {
1729 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001730 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001731 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001732 .destructor = afs_flat_call_destructor,
1733};
1734
1735/*
1736 * FS.ExtendLock operation type
1737 */
1738static const struct afs_call_type afs_RXFSExtendLock = {
1739 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001740 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001741 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001742 .destructor = afs_flat_call_destructor,
1743};
1744
1745/*
1746 * FS.ReleaseLock operation type
1747 */
1748static const struct afs_call_type afs_RXFSReleaseLock = {
1749 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001750 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001751 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001752 .destructor = afs_flat_call_destructor,
1753};
1754
1755/*
David Howellsd2ddc772017-11-02 15:27:50 +00001756 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001757 */
David Howellsd2ddc772017-11-02 15:27:50 +00001758int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001759{
David Howellsd2ddc772017-11-02 15:27:50 +00001760 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001761 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001762 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001763 __be32 *bp;
1764
1765 _enter("");
1766
David Howellsf044c882017-11-02 15:27:45 +00001767 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001768 if (!call)
1769 return -ENOMEM;
1770
David Howellsd2ddc772017-11-02 15:27:50 +00001771 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001772 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001773
1774 /* marshall the parameters */
1775 bp = call->request;
1776 *bp++ = htonl(FSSETLOCK);
1777 *bp++ = htonl(vnode->fid.vid);
1778 *bp++ = htonl(vnode->fid.vnode);
1779 *bp++ = htonl(vnode->fid.unique);
1780 *bp++ = htonl(type);
1781
David Howellsd2ddc772017-11-02 15:27:50 +00001782 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001783 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001784 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001785}
1786
1787/*
1788 * extend a lock on a file
1789 */
David Howellsd2ddc772017-11-02 15:27:50 +00001790int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001791{
David Howellsd2ddc772017-11-02 15:27:50 +00001792 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001793 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001794 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001795 __be32 *bp;
1796
1797 _enter("");
1798
David Howellsf044c882017-11-02 15:27:45 +00001799 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001800 if (!call)
1801 return -ENOMEM;
1802
David Howellsd2ddc772017-11-02 15:27:50 +00001803 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001804 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001805
1806 /* marshall the parameters */
1807 bp = call->request;
1808 *bp++ = htonl(FSEXTENDLOCK);
1809 *bp++ = htonl(vnode->fid.vid);
1810 *bp++ = htonl(vnode->fid.vnode);
1811 *bp++ = htonl(vnode->fid.unique);
1812
David Howellsd2ddc772017-11-02 15:27:50 +00001813 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001814 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001815 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001816}
1817
1818/*
1819 * release a lock on a file
1820 */
David Howellsd2ddc772017-11-02 15:27:50 +00001821int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001822{
David Howellsd2ddc772017-11-02 15:27:50 +00001823 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001824 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001825 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001826 __be32 *bp;
1827
1828 _enter("");
1829
David Howellsf044c882017-11-02 15:27:45 +00001830 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001831 if (!call)
1832 return -ENOMEM;
1833
David Howellsd2ddc772017-11-02 15:27:50 +00001834 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001835 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001836
1837 /* marshall the parameters */
1838 bp = call->request;
1839 *bp++ = htonl(FSRELEASELOCK);
1840 *bp++ = htonl(vnode->fid.vid);
1841 *bp++ = htonl(vnode->fid.vnode);
1842 *bp++ = htonl(vnode->fid.unique);
1843
David Howellsd2ddc772017-11-02 15:27:50 +00001844 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001845 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001846 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsc435ee32017-11-02 15:27:49 +00001847}
1848
1849/*
1850 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1851 */
1852static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1853{
1854 return afs_transfer_reply(call);
1855}
1856
1857/*
1858 * FS.GiveUpAllCallBacks operation type
1859 */
1860static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1861 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001862 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001863 .deliver = afs_deliver_fs_give_up_all_callbacks,
1864 .destructor = afs_flat_call_destructor,
1865};
1866
1867/*
1868 * Flush all the callbacks we have on a server.
1869 */
David Howellsd2ddc772017-11-02 15:27:50 +00001870int afs_fs_give_up_all_callbacks(struct afs_net *net,
1871 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001872 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001873 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001874{
1875 struct afs_call *call;
1876 __be32 *bp;
1877
1878 _enter("");
1879
David Howellsd2ddc772017-11-02 15:27:50 +00001880 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001881 if (!call)
1882 return -ENOMEM;
1883
1884 call->key = key;
1885
1886 /* marshall the parameters */
1887 bp = call->request;
1888 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1889
1890 /* Can't take a ref on server */
David Howellsd2ddc772017-11-02 15:27:50 +00001891 return afs_make_call(ac, call, GFP_NOFS, false);
1892}
1893
1894/*
1895 * Deliver reply data to an FS.GetCapabilities operation.
1896 */
1897static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1898{
1899 u32 count;
1900 int ret;
1901
1902 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count);
1903
1904again:
1905 switch (call->unmarshall) {
1906 case 0:
1907 call->offset = 0;
1908 call->unmarshall++;
1909
1910 /* Extract the capabilities word count */
1911 case 1:
1912 ret = afs_extract_data(call, &call->tmp,
1913 1 * sizeof(__be32),
1914 true);
1915 if (ret < 0)
1916 return ret;
1917
1918 count = ntohl(call->tmp);
1919
1920 call->count = count;
1921 call->count2 = count;
1922 call->offset = 0;
1923 call->unmarshall++;
1924
1925 /* Extract capabilities words */
1926 case 2:
1927 count = min(call->count, 16U);
1928 ret = afs_extract_data(call, call->buffer,
1929 count * sizeof(__be32),
1930 call->count > 16);
1931 if (ret < 0)
1932 return ret;
1933
1934 /* TODO: Examine capabilities */
1935
1936 call->count -= count;
1937 if (call->count > 0)
1938 goto again;
1939 call->offset = 0;
1940 call->unmarshall++;
1941 break;
1942 }
1943
1944 _leave(" = 0 [done]");
1945 return 0;
1946}
1947
1948/*
1949 * FS.GetCapabilities operation type
1950 */
1951static const struct afs_call_type afs_RXFSGetCapabilities = {
1952 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001953 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001954 .deliver = afs_deliver_fs_get_capabilities,
1955 .destructor = afs_flat_call_destructor,
1956};
1957
1958/*
1959 * Probe a fileserver for the capabilities that it supports. This can
1960 * return up to 196 words.
1961 */
1962int afs_fs_get_capabilities(struct afs_net *net,
1963 struct afs_server *server,
1964 struct afs_addr_cursor *ac,
1965 struct key *key)
1966{
1967 struct afs_call *call;
1968 __be32 *bp;
1969
1970 _enter("");
1971
1972 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1973 if (!call)
1974 return -ENOMEM;
1975
1976 call->key = key;
1977
1978 /* marshall the parameters */
1979 bp = call->request;
1980 *bp++ = htonl(FSGETCAPABILITIES);
1981
1982 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00001983 trace_afs_make_fs_call(call, NULL);
David Howellsd2ddc772017-11-02 15:27:50 +00001984 return afs_make_call(ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001985}
David Howells5cf9dd52018-04-09 21:12:31 +01001986
1987/*
1988 * Deliver reply data to an FS.FetchStatus with no vnode.
1989 */
1990static int afs_deliver_fs_fetch_status(struct afs_call *call)
1991{
1992 struct afs_file_status *status = call->reply[1];
1993 struct afs_callback *callback = call->reply[2];
1994 struct afs_volsync *volsync = call->reply[3];
1995 struct afs_vnode *vnode = call->reply[0];
1996 const __be32 *bp;
1997 int ret;
1998
1999 ret = afs_transfer_reply(call);
2000 if (ret < 0)
2001 return ret;
2002
2003 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
2004
2005 /* unmarshall the reply once we've received all of it */
2006 bp = call->buffer;
2007 xdr_decode_AFSFetchStatus(&bp, status, vnode, NULL);
2008 callback[call->count].version = ntohl(bp[0]);
2009 callback[call->count].expiry = ntohl(bp[1]);
2010 callback[call->count].type = ntohl(bp[2]);
2011 if (vnode)
2012 xdr_decode_AFSCallBack(call, vnode, &bp);
2013 else
2014 bp += 3;
2015 if (volsync)
2016 xdr_decode_AFSVolSync(&bp, volsync);
2017
2018 _leave(" = 0 [done]");
2019 return 0;
2020}
2021
2022/*
2023 * FS.FetchStatus operation type
2024 */
2025static const struct afs_call_type afs_RXFSFetchStatus = {
2026 .name = "FS.FetchStatus",
2027 .op = afs_FS_FetchStatus,
2028 .deliver = afs_deliver_fs_fetch_status,
2029 .destructor = afs_flat_call_destructor,
2030};
2031
2032/*
2033 * Fetch the status information for a fid without needing a vnode handle.
2034 */
2035int afs_fs_fetch_status(struct afs_fs_cursor *fc,
2036 struct afs_net *net,
2037 struct afs_fid *fid,
2038 struct afs_file_status *status,
2039 struct afs_callback *callback,
2040 struct afs_volsync *volsync)
2041{
2042 struct afs_call *call;
2043 __be32 *bp;
2044
2045 _enter(",%x,{%x:%u},,",
2046 key_serial(fc->key), fid->vid, fid->vnode);
2047
2048 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
2049 if (!call) {
2050 fc->ac.error = -ENOMEM;
2051 return -ENOMEM;
2052 }
2053
2054 call->key = fc->key;
2055 call->reply[0] = NULL; /* vnode for fid[0] */
2056 call->reply[1] = status;
2057 call->reply[2] = callback;
2058 call->reply[3] = volsync;
2059
2060 /* marshall the parameters */
2061 bp = call->request;
2062 bp[0] = htonl(FSFETCHSTATUS);
2063 bp[1] = htonl(fid->vid);
2064 bp[2] = htonl(fid->vnode);
2065 bp[3] = htonl(fid->unique);
2066
2067 call->cb_break = fc->cb_break;
2068 afs_use_fs_server(call, fc->cbi);
2069 trace_afs_make_fs_call(call, fid);
2070 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2071}
2072
2073/*
2074 * Deliver reply data to an FS.InlineBulkStatus call
2075 */
2076static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2077{
2078 struct afs_file_status *statuses;
2079 struct afs_callback *callbacks;
2080 struct afs_vnode *vnode = call->reply[0];
2081 const __be32 *bp;
2082 u32 tmp;
2083 int ret;
2084
2085 _enter("{%u}", call->unmarshall);
2086
2087 switch (call->unmarshall) {
2088 case 0:
2089 call->offset = 0;
2090 call->unmarshall++;
2091
2092 /* Extract the file status count and array in two steps */
2093 case 1:
2094 _debug("extract status count");
2095 ret = afs_extract_data(call, &call->tmp, 4, true);
2096 if (ret < 0)
2097 return ret;
2098
2099 tmp = ntohl(call->tmp);
2100 _debug("status count: %u/%u", tmp, call->count2);
2101 if (tmp != call->count2)
2102 return -EBADMSG;
2103
2104 call->count = 0;
2105 call->unmarshall++;
2106 more_counts:
2107 call->offset = 0;
2108
2109 case 2:
2110 _debug("extract status array %u", call->count);
2111 ret = afs_extract_data(call, call->buffer, 21 * 4, true);
2112 if (ret < 0)
2113 return ret;
2114
2115 bp = call->buffer;
2116 statuses = call->reply[1];
2117 xdr_decode_AFSFetchStatus(&bp, &statuses[call->count],
2118 call->count == 0 ? vnode : NULL,
2119 NULL);
2120
2121 call->count++;
2122 if (call->count < call->count2)
2123 goto more_counts;
2124
2125 call->count = 0;
2126 call->unmarshall++;
2127 call->offset = 0;
2128
2129 /* Extract the callback count and array in two steps */
2130 case 3:
2131 _debug("extract CB count");
2132 ret = afs_extract_data(call, &call->tmp, 4, true);
2133 if (ret < 0)
2134 return ret;
2135
2136 tmp = ntohl(call->tmp);
2137 _debug("CB count: %u", tmp);
2138 if (tmp != call->count2)
2139 return -EBADMSG;
2140 call->count = 0;
2141 call->unmarshall++;
2142 more_cbs:
2143 call->offset = 0;
2144
2145 case 4:
2146 _debug("extract CB array");
2147 ret = afs_extract_data(call, call->buffer, 3 * 4, true);
2148 if (ret < 0)
2149 return ret;
2150
2151 _debug("unmarshall CB array");
2152 bp = call->buffer;
2153 callbacks = call->reply[2];
2154 callbacks[call->count].version = ntohl(bp[0]);
2155 callbacks[call->count].expiry = ntohl(bp[1]);
2156 callbacks[call->count].type = ntohl(bp[2]);
2157 statuses = call->reply[1];
2158 if (call->count == 0 && vnode && statuses[0].abort_code == 0)
2159 xdr_decode_AFSCallBack(call, vnode, &bp);
2160 call->count++;
2161 if (call->count < call->count2)
2162 goto more_cbs;
2163
2164 call->offset = 0;
2165 call->unmarshall++;
2166
2167 case 5:
2168 ret = afs_extract_data(call, call->buffer, 6 * 4, false);
2169 if (ret < 0)
2170 return ret;
2171
2172 bp = call->buffer;
2173 if (call->reply[3])
2174 xdr_decode_AFSVolSync(&bp, call->reply[3]);
2175
2176 call->offset = 0;
2177 call->unmarshall++;
2178
2179 case 6:
2180 break;
2181 }
2182
2183 _leave(" = 0 [done]");
2184 return 0;
2185}
2186
2187/*
2188 * FS.InlineBulkStatus operation type
2189 */
2190static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2191 .name = "FS.InlineBulkStatus",
2192 .op = afs_FS_InlineBulkStatus,
2193 .deliver = afs_deliver_fs_inline_bulk_status,
2194 .destructor = afs_flat_call_destructor,
2195};
2196
2197/*
2198 * Fetch the status information for up to 50 files
2199 */
2200int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2201 struct afs_net *net,
2202 struct afs_fid *fids,
2203 struct afs_file_status *statuses,
2204 struct afs_callback *callbacks,
2205 unsigned int nr_fids,
2206 struct afs_volsync *volsync)
2207{
2208 struct afs_call *call;
2209 __be32 *bp;
2210 int i;
2211
2212 _enter(",%x,{%x:%u},%u",
2213 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2214
2215 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2216 (2 + nr_fids * 3) * 4,
2217 21 * 4);
2218 if (!call) {
2219 fc->ac.error = -ENOMEM;
2220 return -ENOMEM;
2221 }
2222
2223 call->key = fc->key;
2224 call->reply[0] = NULL; /* vnode for fid[0] */
2225 call->reply[1] = statuses;
2226 call->reply[2] = callbacks;
2227 call->reply[3] = volsync;
2228 call->count2 = nr_fids;
2229
2230 /* marshall the parameters */
2231 bp = call->request;
2232 *bp++ = htonl(FSINLINEBULKSTATUS);
2233 *bp++ = htonl(nr_fids);
2234 for (i = 0; i < nr_fids; i++) {
2235 *bp++ = htonl(fids[i].vid);
2236 *bp++ = htonl(fids[i].vnode);
2237 *bp++ = htonl(fids[i].unique);
2238 }
2239
2240 call->cb_break = fc->cb_break;
2241 afs_use_fs_server(call, fc->cbi);
2242 trace_afs_make_fs_call(call, &fids[0]);
2243 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2244}