blob: 75554ee98d0261e26ebda0dcd068bf8768c62261 [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 Howells08e0e7c2007-04-26 15:55:03 -070047 * decode an AFSFetchStatus block
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 */
David Howells08e0e7c2007-04-26 15:55:03 -070049static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
David Howells260a9802007-04-26 15:59:35 -070050 struct afs_file_status *status,
David Howells31143d52007-05-09 02:33:46 -070051 struct afs_vnode *vnode,
52 afs_dataversion_t *store_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -070053{
David Howells31143d52007-05-09 02:33:46 -070054 afs_dataversion_t expected_version;
David Howells08e0e7c2007-04-26 15:55:03 -070055 const __be32 *bp = *_bp;
56 umode_t mode;
David Howells260a9802007-04-26 15:59:35 -070057 u64 data_version, size;
David Howellsc435ee32017-11-02 15:27:49 +000058 bool changed = false;
Eric W. Biedermana0a53862012-02-07 16:20:48 -080059 kuid_t owner;
60 kgid_t group;
David Howells08e0e7c2007-04-26 15:55:03 -070061
David Howellsd2ddc772017-11-02 15:27:50 +000062 if (vnode)
63 write_seqlock(&vnode->cb_lock);
David Howellsc435ee32017-11-02 15:27:49 +000064
David Howells08e0e7c2007-04-26 15:55:03 -070065#define EXTRACT(DST) \
66 do { \
67 u32 x = ntohl(*bp++); \
David Howellsc435ee32017-11-02 15:27:49 +000068 if (DST != x) \
69 changed |= true; \
David Howells08e0e7c2007-04-26 15:55:03 -070070 DST = x; \
71 } while (0)
72
David Howells260a9802007-04-26 15:59:35 -070073 status->if_version = ntohl(*bp++);
74 EXTRACT(status->type);
75 EXTRACT(status->nlink);
76 size = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -070077 data_version = ntohl(*bp++);
David Howells260a9802007-04-26 15:59:35 -070078 EXTRACT(status->author);
Eric W. Biedermana0a53862012-02-07 16:20:48 -080079 owner = make_kuid(&init_user_ns, ntohl(*bp++));
80 changed |= !uid_eq(owner, status->owner);
81 status->owner = owner;
David Howells260a9802007-04-26 15:59:35 -070082 EXTRACT(status->caller_access); /* call ticket dependent */
83 EXTRACT(status->anon_access);
84 EXTRACT(status->mode);
David Howellsbe080a62017-11-02 15:27:49 +000085 bp++; /* parent.vnode */
86 bp++; /* parent.unique */
David Howells08e0e7c2007-04-26 15:55:03 -070087 bp++; /* seg size */
David Howells260a9802007-04-26 15:59:35 -070088 status->mtime_client = ntohl(*bp++);
89 status->mtime_server = ntohl(*bp++);
Eric W. Biedermana0a53862012-02-07 16:20:48 -080090 group = make_kgid(&init_user_ns, ntohl(*bp++));
91 changed |= !gid_eq(group, status->group);
92 status->group = group;
David Howells08e0e7c2007-04-26 15:55:03 -070093 bp++; /* sync counter */
94 data_version |= (u64) ntohl(*bp++) << 32;
David Howellse8d6c552007-07-15 23:40:12 -070095 EXTRACT(status->lock_count);
David Howells260a9802007-04-26 15:59:35 -070096 size |= (u64) ntohl(*bp++) << 32;
David Howells5cf9dd52018-04-09 21:12:31 +010097 EXTRACT(status->abort_code); /* spare 4 */
David Howells08e0e7c2007-04-26 15:55:03 -070098 *_bp = bp;
99
David Howells260a9802007-04-26 15:59:35 -0700100 if (size != status->size) {
101 status->size = size;
102 changed |= true;
David Howells08e0e7c2007-04-26 15:55:03 -0700103 }
David Howells260a9802007-04-26 15:59:35 -0700104 status->mode &= S_IALLUGO;
David Howells08e0e7c2007-04-26 15:55:03 -0700105
106 _debug("vnode time %lx, %lx",
David Howells260a9802007-04-26 15:59:35 -0700107 status->mtime_client, status->mtime_server);
David Howells08e0e7c2007-04-26 15:55:03 -0700108
David Howells260a9802007-04-26 15:59:35 -0700109 if (vnode) {
David Howells260a9802007-04-26 15:59:35 -0700110 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
111 _debug("vnode changed");
112 i_size_write(&vnode->vfs_inode, size);
113 vnode->vfs_inode.i_uid = status->owner;
114 vnode->vfs_inode.i_gid = status->group;
David Howellsd6e43f72011-06-14 00:45:44 +0100115 vnode->vfs_inode.i_generation = vnode->fid.unique;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200116 set_nlink(&vnode->vfs_inode, status->nlink);
David Howells260a9802007-04-26 15:59:35 -0700117
118 mode = vnode->vfs_inode.i_mode;
119 mode &= ~S_IALLUGO;
120 mode |= status->mode;
121 barrier();
122 vnode->vfs_inode.i_mode = mode;
123 }
124
Marc Dionneab94f5d2017-03-16 16:27:47 +0000125 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
David Howells260a9802007-04-26 15:59:35 -0700126 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
127 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
Jeff Laytona01179e2017-12-11 06:35:11 -0500128 inode_set_iversion_raw(&vnode->vfs_inode, data_version);
David Howells260a9802007-04-26 15:59:35 -0700129 }
130
David Howells31143d52007-05-09 02:33:46 -0700131 expected_version = status->data_version;
132 if (store_version)
133 expected_version = *store_version;
134
135 if (expected_version != data_version) {
David Howells260a9802007-04-26 15:59:35 -0700136 status->data_version = data_version;
137 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
138 _debug("vnode modified %llx on {%x:%u}",
David S. Millerba3e0e12007-04-26 16:06:22 -0700139 (unsigned long long) data_version,
140 vnode->fid.vid, vnode->fid.vnode);
David Howellsc435ee32017-11-02 15:27:49 +0000141 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
David Howells260a9802007-04-26 15:59:35 -0700142 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
143 }
David Howells31143d52007-05-09 02:33:46 -0700144 } else if (store_version) {
145 status->data_version = data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 }
David Howellsc435ee32017-11-02 15:27:49 +0000147
David Howellsd2ddc772017-11-02 15:27:50 +0000148 if (vnode)
149 write_sequnlock(&vnode->cb_lock);
David Howellsec268152007-04-26 15:49:28 -0700150}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152/*
David Howells08e0e7c2007-04-26 15:55:03 -0700153 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 */
David Howellsc435ee32017-11-02 15:27:49 +0000155static void xdr_decode_AFSCallBack(struct afs_call *call,
156 struct afs_vnode *vnode,
157 const __be32 **_bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158{
David Howellsd2ddc772017-11-02 15:27:50 +0000159 struct afs_cb_interest *old, *cbi = call->cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700160 const __be32 *bp = *_bp;
David Howellsc435ee32017-11-02 15:27:49 +0000161 u32 cb_expiry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
David Howellsc435ee32017-11-02 15:27:49 +0000163 write_seqlock(&vnode->cb_lock);
164
David Howellsd2ddc772017-11-02 15:27:50 +0000165 if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) {
David Howellsc435ee32017-11-02 15:27:49 +0000166 vnode->cb_version = ntohl(*bp++);
167 cb_expiry = ntohl(*bp++);
168 vnode->cb_type = ntohl(*bp++);
169 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
David Howellsd2ddc772017-11-02 15:27:50 +0000170 old = vnode->cb_interest;
171 if (old != call->cbi) {
172 vnode->cb_interest = cbi;
173 cbi = old;
174 }
David Howellsc435ee32017-11-02 15:27:49 +0000175 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
176 } else {
177 bp += 3;
178 }
179
180 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +0000181 call->cbi = cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700182 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700183}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
David Howells260a9802007-04-26 15:59:35 -0700185static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
186 struct afs_callback *cb)
187{
188 const __be32 *bp = *_bp;
189
190 cb->version = ntohl(*bp++);
191 cb->expiry = ntohl(*bp++);
192 cb->type = ntohl(*bp++);
193 *_bp = bp;
194}
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196/*
David Howells08e0e7c2007-04-26 15:55:03 -0700197 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 */
David Howells08e0e7c2007-04-26 15:55:03 -0700199static void xdr_decode_AFSVolSync(const __be32 **_bp,
200 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
David Howells08e0e7c2007-04-26 15:55:03 -0700202 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
David Howells08e0e7c2007-04-26 15:55:03 -0700204 volsync->creation = ntohl(*bp++);
205 bp++; /* spare2 */
206 bp++; /* spare3 */
207 bp++; /* spare4 */
208 bp++; /* spare5 */
209 bp++; /* spare6 */
210 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700211}
David Howells08e0e7c2007-04-26 15:55:03 -0700212
213/*
David Howells31143d52007-05-09 02:33:46 -0700214 * encode the requested attributes into an AFSStoreStatus block
215 */
216static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
217{
218 __be32 *bp = *_bp;
219 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
220
221 mask = 0;
222 if (attr->ia_valid & ATTR_MTIME) {
223 mask |= AFS_SET_MTIME;
224 mtime = attr->ia_mtime.tv_sec;
225 }
226
227 if (attr->ia_valid & ATTR_UID) {
228 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800229 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700230 }
231
232 if (attr->ia_valid & ATTR_GID) {
233 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800234 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700235 }
236
237 if (attr->ia_valid & ATTR_MODE) {
238 mask |= AFS_SET_MODE;
239 mode = attr->ia_mode & S_IALLUGO;
240 }
241
242 *bp++ = htonl(mask);
243 *bp++ = htonl(mtime);
244 *bp++ = htonl(owner);
245 *bp++ = htonl(group);
246 *bp++ = htonl(mode);
247 *bp++ = 0; /* segment size */
248 *_bp = bp;
249}
250
251/*
David Howells45222b92007-05-10 22:22:20 -0700252 * decode an AFSFetchVolumeStatus block
253 */
254static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
255 struct afs_volume_status *vs)
256{
257 const __be32 *bp = *_bp;
258
259 vs->vid = ntohl(*bp++);
260 vs->parent_id = ntohl(*bp++);
261 vs->online = ntohl(*bp++);
262 vs->in_service = ntohl(*bp++);
263 vs->blessed = ntohl(*bp++);
264 vs->needs_salvage = ntohl(*bp++);
265 vs->type = ntohl(*bp++);
266 vs->min_quota = ntohl(*bp++);
267 vs->max_quota = ntohl(*bp++);
268 vs->blocks_in_use = ntohl(*bp++);
269 vs->part_blocks_avail = ntohl(*bp++);
270 vs->part_max_blocks = ntohl(*bp++);
271 *_bp = bp;
272}
273
274/*
David Howells08e0e7c2007-04-26 15:55:03 -0700275 * deliver reply data to an FS.FetchStatus
276 */
David Howells5cf9dd52018-04-09 21:12:31 +0100277static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700278{
David Howells97e30432017-11-02 15:27:48 +0000279 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700280 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100281 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700282
David Howellsd0016482016-08-30 20:42:14 +0100283 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100284 if (ret < 0)
285 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700286
David Howellsc435ee32017-11-02 15:27:49 +0000287 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
288
David Howells08e0e7c2007-04-26 15:55:03 -0700289 /* unmarshall the reply once we've received all of it */
290 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700291 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howellsc435ee32017-11-02 15:27:49 +0000292 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000293 if (call->reply[1])
294 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700295
296 _leave(" = 0 [done]");
297 return 0;
298}
299
300/*
301 * FS.FetchStatus operation type
302 */
David Howells5cf9dd52018-04-09 21:12:31 +0100303static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
304 .name = "FS.FetchStatus(vnode)",
David Howells025db802017-11-02 15:27:51 +0000305 .op = afs_FS_FetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100306 .deliver = afs_deliver_fs_fetch_status_vnode,
David Howells08e0e7c2007-04-26 15:55:03 -0700307 .destructor = afs_flat_call_destructor,
308};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310/*
311 * fetch the status information for a file
312 */
David Howellsd2ddc772017-11-02 15:27:50 +0000313int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314{
David Howellsd2ddc772017-11-02 15:27:50 +0000315 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700316 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000317 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 __be32 *bp;
319
David Howells416351f2007-05-09 02:33:45 -0700320 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000321 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
David Howells5cf9dd52018-04-09 21:12:31 +0100323 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
324 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000325 if (!call) {
326 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700327 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
David Howellsd2ddc772017-11-02 15:27:50 +0000330 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000331 call->reply[0] = vnode;
332 call->reply[1] = volsync;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700335 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 bp[0] = htonl(FSFETCHSTATUS);
337 bp[1] = htonl(vnode->fid.vid);
338 bp[2] = htonl(vnode->fid.vnode);
339 bp[3] = htonl(vnode->fid.unique);
340
David Howellsd2ddc772017-11-02 15:27:50 +0000341 call->cb_break = fc->cb_break;
342 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000343 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000344 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700345}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347/*
David Howells08e0e7c2007-04-26 15:55:03 -0700348 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 */
David Howellsd0016482016-08-30 20:42:14 +0100350static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351{
David Howells97e30432017-11-02 15:27:48 +0000352 struct afs_vnode *vnode = call->reply[0];
353 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700354 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000355 unsigned int size;
David Howells08e0e7c2007-04-26 15:55:03 -0700356 void *buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700358
David Howells6a0e3992017-03-16 16:27:46 +0000359 _enter("{%u,%zu/%u;%llu/%llu}",
David Howells196ee9c2017-01-05 10:38:34 +0000360 call->unmarshall, call->offset, call->count,
361 req->remain, req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700362
363 switch (call->unmarshall) {
364 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000365 req->actual_len = 0;
David Howells08e0e7c2007-04-26 15:55:03 -0700366 call->offset = 0;
367 call->unmarshall++;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700368 if (call->operation_ID != FSFETCHDATA64) {
369 call->unmarshall++;
370 goto no_msw;
371 }
David Howells08e0e7c2007-04-26 15:55:03 -0700372
David Howellsb9b1f8d2007-05-10 03:15:21 -0700373 /* extract the upper part of the returned data length of an
374 * FSFETCHDATA64 op (which should always be 0 using this
375 * client) */
David Howells08e0e7c2007-04-26 15:55:03 -0700376 case 1:
David Howellsb9b1f8d2007-05-10 03:15:21 -0700377 _debug("extract data length (MSW)");
David Howellsd0016482016-08-30 20:42:14 +0100378 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100379 if (ret < 0)
380 return ret;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700381
David Howells196ee9c2017-01-05 10:38:34 +0000382 req->actual_len = ntohl(call->tmp);
383 req->actual_len <<= 32;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700384 call->offset = 0;
385 call->unmarshall++;
386
387 no_msw:
388 /* extract the returned data length */
389 case 2:
David Howells08e0e7c2007-04-26 15:55:03 -0700390 _debug("extract data length");
David Howellsd0016482016-08-30 20:42:14 +0100391 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100392 if (ret < 0)
393 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700394
David Howells196ee9c2017-01-05 10:38:34 +0000395 req->actual_len |= ntohl(call->tmp);
396 _debug("DATA length: %llu", req->actual_len);
David Howells196ee9c2017-01-05 10:38:34 +0000397
398 req->remain = req->actual_len;
399 call->offset = req->pos & (PAGE_SIZE - 1);
400 req->index = 0;
401 if (req->actual_len == 0)
402 goto no_more_data;
David Howells08e0e7c2007-04-26 15:55:03 -0700403 call->unmarshall++;
404
David Howells196ee9c2017-01-05 10:38:34 +0000405 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000406 ASSERTCMP(req->index, <, req->nr_pages);
David Howells196ee9c2017-01-05 10:38:34 +0000407 if (req->remain > PAGE_SIZE - call->offset)
408 size = PAGE_SIZE - call->offset;
409 else
410 size = req->remain;
411 call->count = call->offset + size;
412 ASSERTCMP(call->count, <=, PAGE_SIZE);
413 req->remain -= size;
414
David Howells08e0e7c2007-04-26 15:55:03 -0700415 /* extract the returned data */
David Howellsb9b1f8d2007-05-10 03:15:21 -0700416 case 3:
David Howells6a0e3992017-03-16 16:27:46 +0000417 _debug("extract data %llu/%llu %zu/%u",
David Howells196ee9c2017-01-05 10:38:34 +0000418 req->remain, req->actual_len, call->offset, call->count);
419
420 buffer = kmap(req->pages[req->index]);
421 ret = afs_extract_data(call, buffer, call->count, true);
422 kunmap(req->pages[req->index]);
423 if (ret < 0)
424 return ret;
425 if (call->offset == PAGE_SIZE) {
426 if (req->page_done)
427 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000428 req->index++;
David Howells196ee9c2017-01-05 10:38:34 +0000429 if (req->remain > 0) {
David Howells196ee9c2017-01-05 10:38:34 +0000430 call->offset = 0;
David Howellse8e581a2017-03-16 16:27:44 +0000431 if (req->index >= req->nr_pages) {
432 call->unmarshall = 4;
David Howells6db3ac32017-03-16 16:27:44 +0000433 goto begin_discard;
David Howellse8e581a2017-03-16 16:27:44 +0000434 }
David Howells196ee9c2017-01-05 10:38:34 +0000435 goto begin_page;
436 }
David Howells08e0e7c2007-04-26 15:55:03 -0700437 }
David Howells6db3ac32017-03-16 16:27:44 +0000438 goto no_more_data;
439
440 /* Discard any excess data the server gave us */
441 begin_discard:
442 case 4:
David Howells6a0e3992017-03-16 16:27:46 +0000443 size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
David Howells6db3ac32017-03-16 16:27:44 +0000444 call->count = size;
David Howells6a0e3992017-03-16 16:27:46 +0000445 _debug("extract discard %llu/%llu %zu/%u",
David Howells6db3ac32017-03-16 16:27:44 +0000446 req->remain, req->actual_len, call->offset, call->count);
447
448 call->offset = 0;
449 ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
450 req->remain -= call->offset;
451 if (ret < 0)
452 return ret;
453 if (req->remain > 0)
454 goto begin_discard;
David Howells08e0e7c2007-04-26 15:55:03 -0700455
David Howells196ee9c2017-01-05 10:38:34 +0000456 no_more_data:
David Howells08e0e7c2007-04-26 15:55:03 -0700457 call->offset = 0;
David Howells6db3ac32017-03-16 16:27:44 +0000458 call->unmarshall = 5;
David Howells08e0e7c2007-04-26 15:55:03 -0700459
460 /* extract the metadata */
David Howells6db3ac32017-03-16 16:27:44 +0000461 case 5:
David Howellsd0016482016-08-30 20:42:14 +0100462 ret = afs_extract_data(call, call->buffer,
463 (21 + 3 + 6) * 4, false);
David Howells372ee162016-08-03 14:11:40 +0100464 if (ret < 0)
465 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700466
467 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700468 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howellsc435ee32017-11-02 15:27:49 +0000469 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000470 if (call->reply[1])
471 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700472
473 call->offset = 0;
474 call->unmarshall++;
475
David Howells6db3ac32017-03-16 16:27:44 +0000476 case 6:
David Howells08e0e7c2007-04-26 15:55:03 -0700477 break;
478 }
479
David Howells6db3ac32017-03-16 16:27:44 +0000480 for (; req->index < req->nr_pages; req->index++) {
481 if (call->count < PAGE_SIZE)
482 zero_user_segment(req->pages[req->index],
483 call->count, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000484 if (req->page_done)
485 req->page_done(call, req);
David Howells6db3ac32017-03-16 16:27:44 +0000486 call->count = 0;
David Howells416351f2007-05-09 02:33:45 -0700487 }
488
David Howells08e0e7c2007-04-26 15:55:03 -0700489 _leave(" = 0 [done]");
490 return 0;
491}
492
David Howells196ee9c2017-01-05 10:38:34 +0000493static void afs_fetch_data_destructor(struct afs_call *call)
494{
David Howells97e30432017-11-02 15:27:48 +0000495 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000496
497 afs_put_read(req);
498 afs_flat_call_destructor(call);
499}
500
David Howells08e0e7c2007-04-26 15:55:03 -0700501/*
502 * FS.FetchData operation type
503 */
504static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700505 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000506 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700507 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000508 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700509};
510
David Howellsb9b1f8d2007-05-10 03:15:21 -0700511static const struct afs_call_type afs_RXFSFetchData64 = {
512 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000513 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700514 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000515 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700516};
517
518/*
519 * fetch data from a very large file
520 */
David Howellsd2ddc772017-11-02 15:27:50 +0000521static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700522{
David Howellsd2ddc772017-11-02 15:27:50 +0000523 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700524 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000525 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700526 __be32 *bp;
527
528 _enter("");
529
David Howellsf044c882017-11-02 15:27:45 +0000530 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700531 if (!call)
532 return -ENOMEM;
533
David Howellsd2ddc772017-11-02 15:27:50 +0000534 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000535 call->reply[0] = vnode;
536 call->reply[1] = NULL; /* volsync */
537 call->reply[2] = req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700538
539 /* marshall the parameters */
540 bp = call->request;
541 bp[0] = htonl(FSFETCHDATA64);
542 bp[1] = htonl(vnode->fid.vid);
543 bp[2] = htonl(vnode->fid.vnode);
544 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000545 bp[4] = htonl(upper_32_bits(req->pos));
546 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700547 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000548 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700549
David Howells196ee9c2017-01-05 10:38:34 +0000550 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000551 call->cb_break = fc->cb_break;
552 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000553 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000554 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700555}
556
David Howells08e0e7c2007-04-26 15:55:03 -0700557/*
558 * fetch data from a file
559 */
David Howellsd2ddc772017-11-02 15:27:50 +0000560int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700561{
David Howellsd2ddc772017-11-02 15:27:50 +0000562 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700563 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000564 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 __be32 *bp;
566
David Howells196ee9c2017-01-05 10:38:34 +0000567 if (upper_32_bits(req->pos) ||
568 upper_32_bits(req->len) ||
569 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000570 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700571
David Howells08e0e7c2007-04-26 15:55:03 -0700572 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
David Howellsf044c882017-11-02 15:27:45 +0000574 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700575 if (!call)
576 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
David Howellsd2ddc772017-11-02 15:27:50 +0000578 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000579 call->reply[0] = vnode;
580 call->reply[1] = NULL; /* volsync */
581 call->reply[2] = req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
583 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700584 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700586 bp[1] = htonl(vnode->fid.vid);
587 bp[2] = htonl(vnode->fid.vnode);
588 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000589 bp[4] = htonl(lower_32_bits(req->pos));
590 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
David Howells196ee9c2017-01-05 10:38:34 +0000592 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000593 call->cb_break = fc->cb_break;
594 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000595 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000596 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700597}
David Howells260a9802007-04-26 15:59:35 -0700598
599/*
600 * deliver reply data to an FS.CreateFile or an FS.MakeDir
601 */
David Howellsd0016482016-08-30 20:42:14 +0100602static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700603{
David Howells97e30432017-11-02 15:27:48 +0000604 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700605 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100606 int ret;
David Howells260a9802007-04-26 15:59:35 -0700607
David Howellsd0016482016-08-30 20:42:14 +0100608 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700609
David Howellsd0016482016-08-30 20:42:14 +0100610 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100611 if (ret < 0)
612 return ret;
David Howells260a9802007-04-26 15:59:35 -0700613
614 /* unmarshall the reply once we've received all of it */
615 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000616 xdr_decode_AFSFid(&bp, call->reply[1]);
617 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700618 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000619 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
620 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700621
622 _leave(" = 0 [done]");
623 return 0;
624}
625
626/*
627 * FS.CreateFile and FS.MakeDir operation type
628 */
David Howells025db802017-11-02 15:27:51 +0000629static const struct afs_call_type afs_RXFSCreateFile = {
630 .name = "FS.CreateFile",
631 .op = afs_FS_CreateFile,
632 .deliver = afs_deliver_fs_create_vnode,
633 .destructor = afs_flat_call_destructor,
634};
635
636static const struct afs_call_type afs_RXFSMakeDir = {
637 .name = "FS.MakeDir",
638 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700639 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700640 .destructor = afs_flat_call_destructor,
641};
642
643/*
644 * create a file or make a directory
645 */
David Howells8b2a4642017-11-02 15:27:50 +0000646int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700647 const char *name,
648 umode_t mode,
649 struct afs_fid *newfid,
650 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000651 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700652{
David Howellsd2ddc772017-11-02 15:27:50 +0000653 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700654 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000655 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700656 size_t namesz, reqsz, padsz;
657 __be32 *bp;
658
659 _enter("");
660
661 namesz = strlen(name);
662 padsz = (4 - (namesz & 3)) & 3;
663 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
664
David Howells025db802017-11-02 15:27:51 +0000665 call = afs_alloc_flat_call(
666 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
667 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700668 if (!call)
669 return -ENOMEM;
670
David Howellsd2ddc772017-11-02 15:27:50 +0000671 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000672 call->reply[0] = vnode;
673 call->reply[1] = newfid;
674 call->reply[2] = newstatus;
675 call->reply[3] = newcb;
David Howells260a9802007-04-26 15:59:35 -0700676
677 /* marshall the parameters */
678 bp = call->request;
679 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
680 *bp++ = htonl(vnode->fid.vid);
681 *bp++ = htonl(vnode->fid.vnode);
682 *bp++ = htonl(vnode->fid.unique);
683 *bp++ = htonl(namesz);
684 memcpy(bp, name, namesz);
685 bp = (void *) bp + namesz;
686 if (padsz > 0) {
687 memset(bp, 0, padsz);
688 bp = (void *) bp + padsz;
689 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000690 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
691 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700692 *bp++ = 0; /* owner */
693 *bp++ = 0; /* group */
694 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
695 *bp++ = 0; /* segment size */
696
David Howellsd2ddc772017-11-02 15:27:50 +0000697 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000698 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000699 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700700}
701
702/*
703 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
704 */
David Howellsd0016482016-08-30 20:42:14 +0100705static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700706{
David Howells97e30432017-11-02 15:27:48 +0000707 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700708 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100709 int ret;
David Howells260a9802007-04-26 15:59:35 -0700710
David Howellsd0016482016-08-30 20:42:14 +0100711 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700712
David Howellsd0016482016-08-30 20:42:14 +0100713 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100714 if (ret < 0)
715 return ret;
David Howells260a9802007-04-26 15:59:35 -0700716
717 /* unmarshall the reply once we've received all of it */
718 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700719 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000720 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700721
722 _leave(" = 0 [done]");
723 return 0;
724}
725
726/*
727 * FS.RemoveDir/FS.RemoveFile operation type
728 */
David Howells025db802017-11-02 15:27:51 +0000729static const struct afs_call_type afs_RXFSRemoveFile = {
730 .name = "FS.RemoveFile",
731 .op = afs_FS_RemoveFile,
732 .deliver = afs_deliver_fs_remove,
733 .destructor = afs_flat_call_destructor,
734};
735
736static const struct afs_call_type afs_RXFSRemoveDir = {
737 .name = "FS.RemoveDir",
738 .op = afs_FS_RemoveDir,
David Howells260a9802007-04-26 15:59:35 -0700739 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700740 .destructor = afs_flat_call_destructor,
741};
742
743/*
744 * remove a file or directory
745 */
David Howellsd2ddc772017-11-02 15:27:50 +0000746int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir)
David Howells260a9802007-04-26 15:59:35 -0700747{
David Howellsd2ddc772017-11-02 15:27:50 +0000748 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700749 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000750 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700751 size_t namesz, reqsz, padsz;
752 __be32 *bp;
753
754 _enter("");
755
756 namesz = strlen(name);
757 padsz = (4 - (namesz & 3)) & 3;
758 reqsz = (5 * 4) + namesz + padsz;
759
David Howells025db802017-11-02 15:27:51 +0000760 call = afs_alloc_flat_call(
761 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
762 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700763 if (!call)
764 return -ENOMEM;
765
David Howellsd2ddc772017-11-02 15:27:50 +0000766 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000767 call->reply[0] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700768
769 /* marshall the parameters */
770 bp = call->request;
771 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
772 *bp++ = htonl(vnode->fid.vid);
773 *bp++ = htonl(vnode->fid.vnode);
774 *bp++ = htonl(vnode->fid.unique);
775 *bp++ = htonl(namesz);
776 memcpy(bp, name, namesz);
777 bp = (void *) bp + namesz;
778 if (padsz > 0) {
779 memset(bp, 0, padsz);
780 bp = (void *) bp + padsz;
781 }
782
David Howellsd2ddc772017-11-02 15:27:50 +0000783 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000784 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000785 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700786}
787
788/*
789 * deliver reply data to an FS.Link
790 */
David Howellsd0016482016-08-30 20:42:14 +0100791static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700792{
David Howells97e30432017-11-02 15:27:48 +0000793 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700794 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100795 int ret;
David Howells260a9802007-04-26 15:59:35 -0700796
David Howellsd0016482016-08-30 20:42:14 +0100797 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700798
David Howellsd0016482016-08-30 20:42:14 +0100799 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100800 if (ret < 0)
801 return ret;
David Howells260a9802007-04-26 15:59:35 -0700802
803 /* unmarshall the reply once we've received all of it */
804 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700805 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
806 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000807 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700808
809 _leave(" = 0 [done]");
810 return 0;
811}
812
813/*
814 * FS.Link operation type
815 */
816static const struct afs_call_type afs_RXFSLink = {
817 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000818 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700819 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700820 .destructor = afs_flat_call_destructor,
821};
822
823/*
824 * make a hard link
825 */
David Howellsd2ddc772017-11-02 15:27:50 +0000826int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
827 const char *name)
David Howells260a9802007-04-26 15:59:35 -0700828{
David Howellsd2ddc772017-11-02 15:27:50 +0000829 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700830 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000831 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700832 size_t namesz, reqsz, padsz;
833 __be32 *bp;
834
835 _enter("");
836
837 namesz = strlen(name);
838 padsz = (4 - (namesz & 3)) & 3;
839 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
840
David Howellsf044c882017-11-02 15:27:45 +0000841 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700842 if (!call)
843 return -ENOMEM;
844
David Howellsd2ddc772017-11-02 15:27:50 +0000845 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000846 call->reply[0] = dvnode;
847 call->reply[1] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700848
849 /* marshall the parameters */
850 bp = call->request;
851 *bp++ = htonl(FSLINK);
852 *bp++ = htonl(dvnode->fid.vid);
853 *bp++ = htonl(dvnode->fid.vnode);
854 *bp++ = htonl(dvnode->fid.unique);
855 *bp++ = htonl(namesz);
856 memcpy(bp, name, namesz);
857 bp = (void *) bp + namesz;
858 if (padsz > 0) {
859 memset(bp, 0, padsz);
860 bp = (void *) bp + padsz;
861 }
862 *bp++ = htonl(vnode->fid.vid);
863 *bp++ = htonl(vnode->fid.vnode);
864 *bp++ = htonl(vnode->fid.unique);
865
David Howellsd2ddc772017-11-02 15:27:50 +0000866 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000867 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000868 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700869}
870
871/*
872 * deliver reply data to an FS.Symlink
873 */
David Howellsd0016482016-08-30 20:42:14 +0100874static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700875{
David Howells97e30432017-11-02 15:27:48 +0000876 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700877 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100878 int ret;
David Howells260a9802007-04-26 15:59:35 -0700879
David Howellsd0016482016-08-30 20:42:14 +0100880 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700881
David Howellsd0016482016-08-30 20:42:14 +0100882 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100883 if (ret < 0)
884 return ret;
David Howells260a9802007-04-26 15:59:35 -0700885
886 /* unmarshall the reply once we've received all of it */
887 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000888 xdr_decode_AFSFid(&bp, call->reply[1]);
889 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700890 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000891 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700892
893 _leave(" = 0 [done]");
894 return 0;
895}
896
897/*
898 * FS.Symlink operation type
899 */
900static const struct afs_call_type afs_RXFSSymlink = {
901 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +0000902 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -0700903 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700904 .destructor = afs_flat_call_destructor,
905};
906
907/*
908 * create a symbolic link
909 */
David Howells8b2a4642017-11-02 15:27:50 +0000910int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700911 const char *name,
912 const char *contents,
913 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +0000914 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -0700915{
David Howellsd2ddc772017-11-02 15:27:50 +0000916 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700917 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000918 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700919 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
920 __be32 *bp;
921
922 _enter("");
923
924 namesz = strlen(name);
925 padsz = (4 - (namesz & 3)) & 3;
926
927 c_namesz = strlen(contents);
928 c_padsz = (4 - (c_namesz & 3)) & 3;
929
930 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
931
David Howellsf044c882017-11-02 15:27:45 +0000932 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700933 (3 + 21 + 21 + 6) * 4);
934 if (!call)
935 return -ENOMEM;
936
David Howellsd2ddc772017-11-02 15:27:50 +0000937 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000938 call->reply[0] = vnode;
939 call->reply[1] = newfid;
940 call->reply[2] = newstatus;
David Howells260a9802007-04-26 15:59:35 -0700941
942 /* marshall the parameters */
943 bp = call->request;
944 *bp++ = htonl(FSSYMLINK);
945 *bp++ = htonl(vnode->fid.vid);
946 *bp++ = htonl(vnode->fid.vnode);
947 *bp++ = htonl(vnode->fid.unique);
948 *bp++ = htonl(namesz);
949 memcpy(bp, name, namesz);
950 bp = (void *) bp + namesz;
951 if (padsz > 0) {
952 memset(bp, 0, padsz);
953 bp = (void *) bp + padsz;
954 }
955 *bp++ = htonl(c_namesz);
956 memcpy(bp, contents, c_namesz);
957 bp = (void *) bp + c_namesz;
958 if (c_padsz > 0) {
959 memset(bp, 0, c_padsz);
960 bp = (void *) bp + c_padsz;
961 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000962 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
963 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700964 *bp++ = 0; /* owner */
965 *bp++ = 0; /* group */
966 *bp++ = htonl(S_IRWXUGO); /* unix mode */
967 *bp++ = 0; /* segment size */
968
David Howellsd2ddc772017-11-02 15:27:50 +0000969 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000970 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000971 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700972}
973
974/*
975 * deliver reply data to an FS.Rename
976 */
David Howellsd0016482016-08-30 20:42:14 +0100977static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700978{
David Howells97e30432017-11-02 15:27:48 +0000979 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700980 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100981 int ret;
David Howells260a9802007-04-26 15:59:35 -0700982
David Howellsd0016482016-08-30 20:42:14 +0100983 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700984
David Howellsd0016482016-08-30 20:42:14 +0100985 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100986 if (ret < 0)
987 return ret;
David Howells260a9802007-04-26 15:59:35 -0700988
989 /* unmarshall the reply once we've received all of it */
990 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700991 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700992 if (new_dvnode != orig_dvnode)
David Howells31143d52007-05-09 02:33:46 -0700993 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
994 NULL);
David Howells97e30432017-11-02 15:27:48 +0000995 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700996
997 _leave(" = 0 [done]");
998 return 0;
999}
1000
1001/*
1002 * FS.Rename operation type
1003 */
1004static const struct afs_call_type afs_RXFSRename = {
1005 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001006 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001007 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001008 .destructor = afs_flat_call_destructor,
1009};
1010
1011/*
1012 * create a symbolic link
1013 */
David Howells8b2a4642017-11-02 15:27:50 +00001014int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001015 const char *orig_name,
1016 struct afs_vnode *new_dvnode,
David Howellsd2ddc772017-11-02 15:27:50 +00001017 const char *new_name)
David Howells260a9802007-04-26 15:59:35 -07001018{
David Howellsd2ddc772017-11-02 15:27:50 +00001019 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001020 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001021 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001022 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1023 __be32 *bp;
1024
1025 _enter("");
1026
1027 o_namesz = strlen(orig_name);
1028 o_padsz = (4 - (o_namesz & 3)) & 3;
1029
1030 n_namesz = strlen(new_name);
1031 n_padsz = (4 - (n_namesz & 3)) & 3;
1032
1033 reqsz = (4 * 4) +
1034 4 + o_namesz + o_padsz +
1035 (3 * 4) +
1036 4 + n_namesz + n_padsz;
1037
David Howellsf044c882017-11-02 15:27:45 +00001038 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001039 if (!call)
1040 return -ENOMEM;
1041
David Howellsd2ddc772017-11-02 15:27:50 +00001042 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001043 call->reply[0] = orig_dvnode;
1044 call->reply[1] = new_dvnode;
David Howells260a9802007-04-26 15:59:35 -07001045
1046 /* marshall the parameters */
1047 bp = call->request;
1048 *bp++ = htonl(FSRENAME);
1049 *bp++ = htonl(orig_dvnode->fid.vid);
1050 *bp++ = htonl(orig_dvnode->fid.vnode);
1051 *bp++ = htonl(orig_dvnode->fid.unique);
1052 *bp++ = htonl(o_namesz);
1053 memcpy(bp, orig_name, o_namesz);
1054 bp = (void *) bp + o_namesz;
1055 if (o_padsz > 0) {
1056 memset(bp, 0, o_padsz);
1057 bp = (void *) bp + o_padsz;
1058 }
1059
1060 *bp++ = htonl(new_dvnode->fid.vid);
1061 *bp++ = htonl(new_dvnode->fid.vnode);
1062 *bp++ = htonl(new_dvnode->fid.unique);
1063 *bp++ = htonl(n_namesz);
1064 memcpy(bp, new_name, n_namesz);
1065 bp = (void *) bp + n_namesz;
1066 if (n_padsz > 0) {
1067 memset(bp, 0, n_padsz);
1068 bp = (void *) bp + n_padsz;
1069 }
1070
David Howellsd2ddc772017-11-02 15:27:50 +00001071 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001072 trace_afs_make_fs_call(call, &orig_dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001073 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001074}
David Howells31143d52007-05-09 02:33:46 -07001075
1076/*
1077 * deliver reply data to an FS.StoreData
1078 */
David Howellsd0016482016-08-30 20:42:14 +01001079static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001080{
David Howells97e30432017-11-02 15:27:48 +00001081 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001082 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001083 int ret;
David Howells31143d52007-05-09 02:33:46 -07001084
David Howellsd0016482016-08-30 20:42:14 +01001085 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001086
David Howellsd0016482016-08-30 20:42:14 +01001087 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001088 if (ret < 0)
1089 return ret;
David Howells31143d52007-05-09 02:33:46 -07001090
1091 /* unmarshall the reply once we've received all of it */
1092 bp = call->buffer;
1093 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1094 &call->store_version);
David Howells97e30432017-11-02 15:27:48 +00001095 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001096
1097 afs_pages_written_back(vnode, call);
1098
1099 _leave(" = 0 [done]");
1100 return 0;
1101}
1102
1103/*
1104 * FS.StoreData operation type
1105 */
1106static const struct afs_call_type afs_RXFSStoreData = {
1107 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001108 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001109 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001110 .destructor = afs_flat_call_destructor,
1111};
1112
David Howellsb9b1f8d2007-05-10 03:15:21 -07001113static const struct afs_call_type afs_RXFSStoreData64 = {
1114 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001115 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001116 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001117 .destructor = afs_flat_call_destructor,
1118};
1119
1120/*
1121 * store a set of pages to a very large file
1122 */
David Howells8b2a4642017-11-02 15:27:50 +00001123static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001124 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001125 pgoff_t first, pgoff_t last,
1126 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001127 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001128{
David Howells4343d002017-11-02 15:27:52 +00001129 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001130 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001131 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001132 __be32 *bp;
1133
1134 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001135 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001136
David Howellsf044c882017-11-02 15:27:45 +00001137 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001138 (4 + 6 + 3 * 2) * 4,
1139 (21 + 6) * 4);
1140 if (!call)
1141 return -ENOMEM;
1142
David Howells4343d002017-11-02 15:27:52 +00001143 call->key = fc->key;
1144 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001145 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001146 call->first = first;
1147 call->last = last;
1148 call->first_offset = offset;
1149 call->last_to = to;
1150 call->send_pages = true;
1151 call->store_version = vnode->status.data_version + 1;
1152
1153 /* marshall the parameters */
1154 bp = call->request;
1155 *bp++ = htonl(FSSTOREDATA64);
1156 *bp++ = htonl(vnode->fid.vid);
1157 *bp++ = htonl(vnode->fid.vnode);
1158 *bp++ = htonl(vnode->fid.unique);
1159
Marc Dionneab94f5d2017-03-16 16:27:47 +00001160 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1161 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001162 *bp++ = 0; /* owner */
1163 *bp++ = 0; /* group */
1164 *bp++ = 0; /* unix mode */
1165 *bp++ = 0; /* segment size */
1166
1167 *bp++ = htonl(pos >> 32);
1168 *bp++ = htonl((u32) pos);
1169 *bp++ = htonl(size >> 32);
1170 *bp++ = htonl((u32) size);
1171 *bp++ = htonl(i_size >> 32);
1172 *bp++ = htonl((u32) i_size);
1173
David Howells025db802017-11-02 15:27:51 +00001174 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001175 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001176}
1177
David Howells31143d52007-05-09 02:33:46 -07001178/*
1179 * store a set of pages
1180 */
David Howells4343d002017-11-02 15:27:52 +00001181int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001182 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001183 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001184{
David Howells4343d002017-11-02 15:27:52 +00001185 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001186 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001187 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001188 loff_t size, pos, i_size;
1189 __be32 *bp;
1190
1191 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001192 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001193
David Howells146a1192017-03-16 16:27:47 +00001194 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001195 if (first != last)
1196 size += (loff_t)(last - first) << PAGE_SHIFT;
1197 pos = (loff_t)first << PAGE_SHIFT;
1198 pos += offset;
1199
1200 i_size = i_size_read(&vnode->vfs_inode);
1201 if (pos + size > i_size)
1202 i_size = size + pos;
1203
1204 _debug("size %llx, at %llx, i_size %llx",
1205 (unsigned long long) size, (unsigned long long) pos,
1206 (unsigned long long) i_size);
1207
David Howellsb9b1f8d2007-05-10 03:15:21 -07001208 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001209 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001210 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001211
David Howellsf044c882017-11-02 15:27:45 +00001212 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001213 (4 + 6 + 3) * 4,
1214 (21 + 6) * 4);
1215 if (!call)
1216 return -ENOMEM;
1217
David Howells4343d002017-11-02 15:27:52 +00001218 call->key = fc->key;
1219 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001220 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001221 call->first = first;
1222 call->last = last;
1223 call->first_offset = offset;
1224 call->last_to = to;
1225 call->send_pages = true;
1226 call->store_version = vnode->status.data_version + 1;
1227
1228 /* marshall the parameters */
1229 bp = call->request;
1230 *bp++ = htonl(FSSTOREDATA);
1231 *bp++ = htonl(vnode->fid.vid);
1232 *bp++ = htonl(vnode->fid.vnode);
1233 *bp++ = htonl(vnode->fid.unique);
1234
Marc Dionneab94f5d2017-03-16 16:27:47 +00001235 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1236 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001237 *bp++ = 0; /* owner */
1238 *bp++ = 0; /* group */
1239 *bp++ = 0; /* unix mode */
1240 *bp++ = 0; /* segment size */
1241
1242 *bp++ = htonl(pos);
1243 *bp++ = htonl(size);
1244 *bp++ = htonl(i_size);
1245
David Howellsd2ddc772017-11-02 15:27:50 +00001246 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001247 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001248 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001249}
1250
1251/*
1252 * deliver reply data to an FS.StoreStatus
1253 */
David Howellsd0016482016-08-30 20:42:14 +01001254static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001255{
1256 afs_dataversion_t *store_version;
David Howells97e30432017-11-02 15:27:48 +00001257 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001258 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001259 int ret;
David Howells31143d52007-05-09 02:33:46 -07001260
David Howellsd0016482016-08-30 20:42:14 +01001261 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001262
David Howellsd0016482016-08-30 20:42:14 +01001263 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001264 if (ret < 0)
1265 return ret;
David Howells31143d52007-05-09 02:33:46 -07001266
1267 /* unmarshall the reply once we've received all of it */
1268 store_version = NULL;
1269 if (call->operation_ID == FSSTOREDATA)
1270 store_version = &call->store_version;
1271
1272 bp = call->buffer;
1273 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
David Howells97e30432017-11-02 15:27:48 +00001274 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001275
1276 _leave(" = 0 [done]");
1277 return 0;
1278}
1279
1280/*
1281 * FS.StoreStatus operation type
1282 */
1283static const struct afs_call_type afs_RXFSStoreStatus = {
1284 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001285 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001286 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001287 .destructor = afs_flat_call_destructor,
1288};
1289
1290static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1291 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001292 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001293 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001294 .destructor = afs_flat_call_destructor,
1295};
1296
David Howellsb9b1f8d2007-05-10 03:15:21 -07001297static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1298 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001299 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001300 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001301 .destructor = afs_flat_call_destructor,
1302};
1303
1304/*
1305 * set the attributes on a very large file, using FS.StoreData rather than
1306 * FS.StoreStatus so as to alter the file size also
1307 */
David Howellsd2ddc772017-11-02 15:27:50 +00001308static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001309{
David Howellsd2ddc772017-11-02 15:27:50 +00001310 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001311 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001312 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001313 __be32 *bp;
1314
1315 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001316 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001317
1318 ASSERT(attr->ia_valid & ATTR_SIZE);
1319
David Howellsf044c882017-11-02 15:27:45 +00001320 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001321 (4 + 6 + 3 * 2) * 4,
1322 (21 + 6) * 4);
1323 if (!call)
1324 return -ENOMEM;
1325
David Howellsd2ddc772017-11-02 15:27:50 +00001326 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001327 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001328 call->store_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001329
1330 /* marshall the parameters */
1331 bp = call->request;
1332 *bp++ = htonl(FSSTOREDATA64);
1333 *bp++ = htonl(vnode->fid.vid);
1334 *bp++ = htonl(vnode->fid.vnode);
1335 *bp++ = htonl(vnode->fid.unique);
1336
1337 xdr_encode_AFS_StoreStatus(&bp, attr);
1338
1339 *bp++ = 0; /* position of start of write */
1340 *bp++ = 0;
1341 *bp++ = 0; /* size of write */
1342 *bp++ = 0;
1343 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1344 *bp++ = htonl((u32) attr->ia_size);
1345
David Howellsd2ddc772017-11-02 15:27:50 +00001346 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001347 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001348 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001349}
1350
David Howells31143d52007-05-09 02:33:46 -07001351/*
1352 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1353 * so as to alter the file size also
1354 */
David Howellsd2ddc772017-11-02 15:27:50 +00001355static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001356{
David Howellsd2ddc772017-11-02 15:27:50 +00001357 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001358 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001359 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001360 __be32 *bp;
1361
1362 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001363 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001364
1365 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001366 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001367 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001368
David Howellsf044c882017-11-02 15:27:45 +00001369 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001370 (4 + 6 + 3) * 4,
1371 (21 + 6) * 4);
1372 if (!call)
1373 return -ENOMEM;
1374
David Howellsd2ddc772017-11-02 15:27:50 +00001375 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001376 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001377 call->store_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001378
1379 /* marshall the parameters */
1380 bp = call->request;
1381 *bp++ = htonl(FSSTOREDATA);
1382 *bp++ = htonl(vnode->fid.vid);
1383 *bp++ = htonl(vnode->fid.vnode);
1384 *bp++ = htonl(vnode->fid.unique);
1385
1386 xdr_encode_AFS_StoreStatus(&bp, attr);
1387
1388 *bp++ = 0; /* position of start of write */
1389 *bp++ = 0; /* size of write */
1390 *bp++ = htonl(attr->ia_size); /* new file length */
1391
David Howellsd2ddc772017-11-02 15:27:50 +00001392 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001393 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001394 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001395}
1396
1397/*
1398 * set the attributes on a file, using FS.StoreData if there's a change in file
1399 * size, and FS.StoreStatus otherwise
1400 */
David Howellsd2ddc772017-11-02 15:27:50 +00001401int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001402{
David Howellsd2ddc772017-11-02 15:27:50 +00001403 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001404 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001405 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001406 __be32 *bp;
1407
1408 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001409 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001410
1411 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001412 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001413
David Howellsf044c882017-11-02 15:27:45 +00001414 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001415 (4 + 6) * 4,
1416 (21 + 6) * 4);
1417 if (!call)
1418 return -ENOMEM;
1419
David Howellsd2ddc772017-11-02 15:27:50 +00001420 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001421 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001422
1423 /* marshall the parameters */
1424 bp = call->request;
1425 *bp++ = htonl(FSSTORESTATUS);
1426 *bp++ = htonl(vnode->fid.vid);
1427 *bp++ = htonl(vnode->fid.vnode);
1428 *bp++ = htonl(vnode->fid.unique);
1429
1430 xdr_encode_AFS_StoreStatus(&bp, attr);
1431
David Howellsd2ddc772017-11-02 15:27:50 +00001432 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001433 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001434 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001435}
David Howells45222b92007-05-10 22:22:20 -07001436
1437/*
1438 * deliver reply data to an FS.GetVolumeStatus
1439 */
David Howellsd0016482016-08-30 20:42:14 +01001440static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001441{
1442 const __be32 *bp;
1443 char *p;
1444 int ret;
1445
David Howellsd0016482016-08-30 20:42:14 +01001446 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001447
1448 switch (call->unmarshall) {
1449 case 0:
1450 call->offset = 0;
1451 call->unmarshall++;
1452
1453 /* extract the returned status record */
1454 case 1:
1455 _debug("extract status");
David Howellsd0016482016-08-30 20:42:14 +01001456 ret = afs_extract_data(call, call->buffer,
1457 12 * 4, true);
David Howells372ee162016-08-03 14:11:40 +01001458 if (ret < 0)
1459 return ret;
David Howells45222b92007-05-10 22:22:20 -07001460
1461 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001462 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001463 call->offset = 0;
1464 call->unmarshall++;
1465
1466 /* extract the volume name length */
1467 case 2:
David Howellsd0016482016-08-30 20:42:14 +01001468 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001469 if (ret < 0)
1470 return ret;
David Howells45222b92007-05-10 22:22:20 -07001471
1472 call->count = ntohl(call->tmp);
1473 _debug("volname length: %u", call->count);
1474 if (call->count >= AFSNAMEMAX)
1475 return -EBADMSG;
1476 call->offset = 0;
1477 call->unmarshall++;
1478
1479 /* extract the volume name */
1480 case 3:
1481 _debug("extract volname");
1482 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001483 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001484 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001485 if (ret < 0)
1486 return ret;
David Howells45222b92007-05-10 22:22:20 -07001487 }
1488
David Howells97e30432017-11-02 15:27:48 +00001489 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001490 p[call->count] = 0;
1491 _debug("volname '%s'", p);
1492
1493 call->offset = 0;
1494 call->unmarshall++;
1495
1496 /* extract the volume name padding */
1497 if ((call->count & 3) == 0) {
1498 call->unmarshall++;
1499 goto no_volname_padding;
1500 }
1501 call->count = 4 - (call->count & 3);
1502
1503 case 4:
David Howellsd0016482016-08-30 20:42:14 +01001504 ret = afs_extract_data(call, call->buffer,
1505 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001506 if (ret < 0)
1507 return ret;
David Howells45222b92007-05-10 22:22:20 -07001508
1509 call->offset = 0;
1510 call->unmarshall++;
1511 no_volname_padding:
1512
1513 /* extract the offline message length */
1514 case 5:
David Howellsd0016482016-08-30 20:42:14 +01001515 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001516 if (ret < 0)
1517 return ret;
David Howells45222b92007-05-10 22:22:20 -07001518
1519 call->count = ntohl(call->tmp);
1520 _debug("offline msg length: %u", call->count);
1521 if (call->count >= AFSNAMEMAX)
1522 return -EBADMSG;
1523 call->offset = 0;
1524 call->unmarshall++;
1525
1526 /* extract the offline message */
1527 case 6:
1528 _debug("extract offline");
1529 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001530 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001531 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001532 if (ret < 0)
1533 return ret;
David Howells45222b92007-05-10 22:22:20 -07001534 }
1535
David Howells97e30432017-11-02 15:27:48 +00001536 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001537 p[call->count] = 0;
1538 _debug("offline '%s'", p);
1539
1540 call->offset = 0;
1541 call->unmarshall++;
1542
1543 /* extract the offline message padding */
1544 if ((call->count & 3) == 0) {
1545 call->unmarshall++;
1546 goto no_offline_padding;
1547 }
1548 call->count = 4 - (call->count & 3);
1549
1550 case 7:
David Howellsd0016482016-08-30 20:42:14 +01001551 ret = afs_extract_data(call, call->buffer,
1552 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001553 if (ret < 0)
1554 return ret;
David Howells45222b92007-05-10 22:22:20 -07001555
1556 call->offset = 0;
1557 call->unmarshall++;
1558 no_offline_padding:
1559
1560 /* extract the message of the day length */
1561 case 8:
David Howellsd0016482016-08-30 20:42:14 +01001562 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001563 if (ret < 0)
1564 return ret;
David Howells45222b92007-05-10 22:22:20 -07001565
1566 call->count = ntohl(call->tmp);
1567 _debug("motd length: %u", call->count);
1568 if (call->count >= AFSNAMEMAX)
1569 return -EBADMSG;
1570 call->offset = 0;
1571 call->unmarshall++;
1572
1573 /* extract the message of the day */
1574 case 9:
1575 _debug("extract motd");
1576 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001577 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001578 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001579 if (ret < 0)
1580 return ret;
David Howells45222b92007-05-10 22:22:20 -07001581 }
1582
David Howells97e30432017-11-02 15:27:48 +00001583 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001584 p[call->count] = 0;
1585 _debug("motd '%s'", p);
1586
1587 call->offset = 0;
1588 call->unmarshall++;
1589
1590 /* extract the message of the day padding */
David Howellsd0016482016-08-30 20:42:14 +01001591 call->count = (4 - (call->count & 3)) & 3;
David Howells45222b92007-05-10 22:22:20 -07001592
1593 case 10:
David Howellsd0016482016-08-30 20:42:14 +01001594 ret = afs_extract_data(call, call->buffer,
1595 call->count, false);
David Howells372ee162016-08-03 14:11:40 +01001596 if (ret < 0)
1597 return ret;
David Howells45222b92007-05-10 22:22:20 -07001598
1599 call->offset = 0;
1600 call->unmarshall++;
David Howells45222b92007-05-10 22:22:20 -07001601 case 11:
David Howells45222b92007-05-10 22:22:20 -07001602 break;
1603 }
1604
David Howells45222b92007-05-10 22:22:20 -07001605 _leave(" = 0 [done]");
1606 return 0;
1607}
1608
1609/*
1610 * destroy an FS.GetVolumeStatus call
1611 */
1612static void afs_get_volume_status_call_destructor(struct afs_call *call)
1613{
David Howells97e30432017-11-02 15:27:48 +00001614 kfree(call->reply[2]);
1615 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001616 afs_flat_call_destructor(call);
1617}
1618
1619/*
1620 * FS.GetVolumeStatus operation type
1621 */
1622static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1623 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001624 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001625 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001626 .destructor = afs_get_volume_status_call_destructor,
1627};
1628
1629/*
1630 * fetch the status of a volume
1631 */
David Howells8b2a4642017-11-02 15:27:50 +00001632int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001633 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001634{
David Howellsd2ddc772017-11-02 15:27:50 +00001635 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001636 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001637 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001638 __be32 *bp;
1639 void *tmpbuf;
1640
1641 _enter("");
1642
1643 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1644 if (!tmpbuf)
1645 return -ENOMEM;
1646
David Howellsf044c882017-11-02 15:27:45 +00001647 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001648 if (!call) {
1649 kfree(tmpbuf);
1650 return -ENOMEM;
1651 }
1652
David Howellsd2ddc772017-11-02 15:27:50 +00001653 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001654 call->reply[0] = vnode;
1655 call->reply[1] = vs;
1656 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001657
1658 /* marshall the parameters */
1659 bp = call->request;
1660 bp[0] = htonl(FSGETVOLUMESTATUS);
1661 bp[1] = htonl(vnode->fid.vid);
1662
David Howellsd2ddc772017-11-02 15:27:50 +00001663 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001664 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001665 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells45222b92007-05-10 22:22:20 -07001666}
David Howellse8d6c552007-07-15 23:40:12 -07001667
1668/*
1669 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1670 */
David Howellsd0016482016-08-30 20:42:14 +01001671static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001672{
1673 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001674 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001675
David Howellsd0016482016-08-30 20:42:14 +01001676 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001677
David Howellsd0016482016-08-30 20:42:14 +01001678 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001679 if (ret < 0)
1680 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001681
1682 /* unmarshall the reply once we've received all of it */
1683 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001684 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001685
1686 _leave(" = 0 [done]");
1687 return 0;
1688}
1689
1690/*
1691 * FS.SetLock operation type
1692 */
1693static const struct afs_call_type afs_RXFSSetLock = {
1694 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001695 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001696 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001697 .destructor = afs_flat_call_destructor,
1698};
1699
1700/*
1701 * FS.ExtendLock operation type
1702 */
1703static const struct afs_call_type afs_RXFSExtendLock = {
1704 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001705 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001706 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001707 .destructor = afs_flat_call_destructor,
1708};
1709
1710/*
1711 * FS.ReleaseLock operation type
1712 */
1713static const struct afs_call_type afs_RXFSReleaseLock = {
1714 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001715 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001716 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001717 .destructor = afs_flat_call_destructor,
1718};
1719
1720/*
David Howellsd2ddc772017-11-02 15:27:50 +00001721 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001722 */
David Howellsd2ddc772017-11-02 15:27:50 +00001723int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001724{
David Howellsd2ddc772017-11-02 15:27:50 +00001725 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001726 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001727 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001728 __be32 *bp;
1729
1730 _enter("");
1731
David Howellsf044c882017-11-02 15:27:45 +00001732 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001733 if (!call)
1734 return -ENOMEM;
1735
David Howellsd2ddc772017-11-02 15:27:50 +00001736 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001737 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001738
1739 /* marshall the parameters */
1740 bp = call->request;
1741 *bp++ = htonl(FSSETLOCK);
1742 *bp++ = htonl(vnode->fid.vid);
1743 *bp++ = htonl(vnode->fid.vnode);
1744 *bp++ = htonl(vnode->fid.unique);
1745 *bp++ = htonl(type);
1746
David Howellsd2ddc772017-11-02 15:27:50 +00001747 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001748 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001749 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001750}
1751
1752/*
1753 * extend a lock on a file
1754 */
David Howellsd2ddc772017-11-02 15:27:50 +00001755int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001756{
David Howellsd2ddc772017-11-02 15:27:50 +00001757 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001758 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001759 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001760 __be32 *bp;
1761
1762 _enter("");
1763
David Howellsf044c882017-11-02 15:27:45 +00001764 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001765 if (!call)
1766 return -ENOMEM;
1767
David Howellsd2ddc772017-11-02 15:27:50 +00001768 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001769 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001770
1771 /* marshall the parameters */
1772 bp = call->request;
1773 *bp++ = htonl(FSEXTENDLOCK);
1774 *bp++ = htonl(vnode->fid.vid);
1775 *bp++ = htonl(vnode->fid.vnode);
1776 *bp++ = htonl(vnode->fid.unique);
1777
David Howellsd2ddc772017-11-02 15:27:50 +00001778 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001779 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001780 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001781}
1782
1783/*
1784 * release a lock on a file
1785 */
David Howellsd2ddc772017-11-02 15:27:50 +00001786int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001787{
David Howellsd2ddc772017-11-02 15:27:50 +00001788 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001789 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001790 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001791 __be32 *bp;
1792
1793 _enter("");
1794
David Howellsf044c882017-11-02 15:27:45 +00001795 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001796 if (!call)
1797 return -ENOMEM;
1798
David Howellsd2ddc772017-11-02 15:27:50 +00001799 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001800 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001801
1802 /* marshall the parameters */
1803 bp = call->request;
1804 *bp++ = htonl(FSRELEASELOCK);
1805 *bp++ = htonl(vnode->fid.vid);
1806 *bp++ = htonl(vnode->fid.vnode);
1807 *bp++ = htonl(vnode->fid.unique);
1808
David Howellsd2ddc772017-11-02 15:27:50 +00001809 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001810 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001811 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsc435ee32017-11-02 15:27:49 +00001812}
1813
1814/*
1815 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1816 */
1817static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1818{
1819 return afs_transfer_reply(call);
1820}
1821
1822/*
1823 * FS.GiveUpAllCallBacks operation type
1824 */
1825static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1826 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001827 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001828 .deliver = afs_deliver_fs_give_up_all_callbacks,
1829 .destructor = afs_flat_call_destructor,
1830};
1831
1832/*
1833 * Flush all the callbacks we have on a server.
1834 */
David Howellsd2ddc772017-11-02 15:27:50 +00001835int afs_fs_give_up_all_callbacks(struct afs_net *net,
1836 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001837 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001838 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001839{
1840 struct afs_call *call;
1841 __be32 *bp;
1842
1843 _enter("");
1844
David Howellsd2ddc772017-11-02 15:27:50 +00001845 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001846 if (!call)
1847 return -ENOMEM;
1848
1849 call->key = key;
1850
1851 /* marshall the parameters */
1852 bp = call->request;
1853 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1854
1855 /* Can't take a ref on server */
David Howellsd2ddc772017-11-02 15:27:50 +00001856 return afs_make_call(ac, call, GFP_NOFS, false);
1857}
1858
1859/*
1860 * Deliver reply data to an FS.GetCapabilities operation.
1861 */
1862static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1863{
1864 u32 count;
1865 int ret;
1866
1867 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count);
1868
1869again:
1870 switch (call->unmarshall) {
1871 case 0:
1872 call->offset = 0;
1873 call->unmarshall++;
1874
1875 /* Extract the capabilities word count */
1876 case 1:
1877 ret = afs_extract_data(call, &call->tmp,
1878 1 * sizeof(__be32),
1879 true);
1880 if (ret < 0)
1881 return ret;
1882
1883 count = ntohl(call->tmp);
1884
1885 call->count = count;
1886 call->count2 = count;
1887 call->offset = 0;
1888 call->unmarshall++;
1889
1890 /* Extract capabilities words */
1891 case 2:
1892 count = min(call->count, 16U);
1893 ret = afs_extract_data(call, call->buffer,
1894 count * sizeof(__be32),
1895 call->count > 16);
1896 if (ret < 0)
1897 return ret;
1898
1899 /* TODO: Examine capabilities */
1900
1901 call->count -= count;
1902 if (call->count > 0)
1903 goto again;
1904 call->offset = 0;
1905 call->unmarshall++;
1906 break;
1907 }
1908
1909 _leave(" = 0 [done]");
1910 return 0;
1911}
1912
1913/*
1914 * FS.GetCapabilities operation type
1915 */
1916static const struct afs_call_type afs_RXFSGetCapabilities = {
1917 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001918 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001919 .deliver = afs_deliver_fs_get_capabilities,
1920 .destructor = afs_flat_call_destructor,
1921};
1922
1923/*
1924 * Probe a fileserver for the capabilities that it supports. This can
1925 * return up to 196 words.
1926 */
1927int afs_fs_get_capabilities(struct afs_net *net,
1928 struct afs_server *server,
1929 struct afs_addr_cursor *ac,
1930 struct key *key)
1931{
1932 struct afs_call *call;
1933 __be32 *bp;
1934
1935 _enter("");
1936
1937 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1938 if (!call)
1939 return -ENOMEM;
1940
1941 call->key = key;
1942
1943 /* marshall the parameters */
1944 bp = call->request;
1945 *bp++ = htonl(FSGETCAPABILITIES);
1946
1947 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00001948 trace_afs_make_fs_call(call, NULL);
David Howellsd2ddc772017-11-02 15:27:50 +00001949 return afs_make_call(ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001950}
David Howells5cf9dd52018-04-09 21:12:31 +01001951
1952/*
1953 * Deliver reply data to an FS.FetchStatus with no vnode.
1954 */
1955static int afs_deliver_fs_fetch_status(struct afs_call *call)
1956{
1957 struct afs_file_status *status = call->reply[1];
1958 struct afs_callback *callback = call->reply[2];
1959 struct afs_volsync *volsync = call->reply[3];
1960 struct afs_vnode *vnode = call->reply[0];
1961 const __be32 *bp;
1962 int ret;
1963
1964 ret = afs_transfer_reply(call);
1965 if (ret < 0)
1966 return ret;
1967
1968 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
1969
1970 /* unmarshall the reply once we've received all of it */
1971 bp = call->buffer;
1972 xdr_decode_AFSFetchStatus(&bp, status, vnode, NULL);
1973 callback[call->count].version = ntohl(bp[0]);
1974 callback[call->count].expiry = ntohl(bp[1]);
1975 callback[call->count].type = ntohl(bp[2]);
1976 if (vnode)
1977 xdr_decode_AFSCallBack(call, vnode, &bp);
1978 else
1979 bp += 3;
1980 if (volsync)
1981 xdr_decode_AFSVolSync(&bp, volsync);
1982
1983 _leave(" = 0 [done]");
1984 return 0;
1985}
1986
1987/*
1988 * FS.FetchStatus operation type
1989 */
1990static const struct afs_call_type afs_RXFSFetchStatus = {
1991 .name = "FS.FetchStatus",
1992 .op = afs_FS_FetchStatus,
1993 .deliver = afs_deliver_fs_fetch_status,
1994 .destructor = afs_flat_call_destructor,
1995};
1996
1997/*
1998 * Fetch the status information for a fid without needing a vnode handle.
1999 */
2000int afs_fs_fetch_status(struct afs_fs_cursor *fc,
2001 struct afs_net *net,
2002 struct afs_fid *fid,
2003 struct afs_file_status *status,
2004 struct afs_callback *callback,
2005 struct afs_volsync *volsync)
2006{
2007 struct afs_call *call;
2008 __be32 *bp;
2009
2010 _enter(",%x,{%x:%u},,",
2011 key_serial(fc->key), fid->vid, fid->vnode);
2012
2013 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
2014 if (!call) {
2015 fc->ac.error = -ENOMEM;
2016 return -ENOMEM;
2017 }
2018
2019 call->key = fc->key;
2020 call->reply[0] = NULL; /* vnode for fid[0] */
2021 call->reply[1] = status;
2022 call->reply[2] = callback;
2023 call->reply[3] = volsync;
2024
2025 /* marshall the parameters */
2026 bp = call->request;
2027 bp[0] = htonl(FSFETCHSTATUS);
2028 bp[1] = htonl(fid->vid);
2029 bp[2] = htonl(fid->vnode);
2030 bp[3] = htonl(fid->unique);
2031
2032 call->cb_break = fc->cb_break;
2033 afs_use_fs_server(call, fc->cbi);
2034 trace_afs_make_fs_call(call, fid);
2035 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2036}
2037
2038/*
2039 * Deliver reply data to an FS.InlineBulkStatus call
2040 */
2041static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2042{
2043 struct afs_file_status *statuses;
2044 struct afs_callback *callbacks;
2045 struct afs_vnode *vnode = call->reply[0];
2046 const __be32 *bp;
2047 u32 tmp;
2048 int ret;
2049
2050 _enter("{%u}", call->unmarshall);
2051
2052 switch (call->unmarshall) {
2053 case 0:
2054 call->offset = 0;
2055 call->unmarshall++;
2056
2057 /* Extract the file status count and array in two steps */
2058 case 1:
2059 _debug("extract status count");
2060 ret = afs_extract_data(call, &call->tmp, 4, true);
2061 if (ret < 0)
2062 return ret;
2063
2064 tmp = ntohl(call->tmp);
2065 _debug("status count: %u/%u", tmp, call->count2);
2066 if (tmp != call->count2)
2067 return -EBADMSG;
2068
2069 call->count = 0;
2070 call->unmarshall++;
2071 more_counts:
2072 call->offset = 0;
2073
2074 case 2:
2075 _debug("extract status array %u", call->count);
2076 ret = afs_extract_data(call, call->buffer, 21 * 4, true);
2077 if (ret < 0)
2078 return ret;
2079
2080 bp = call->buffer;
2081 statuses = call->reply[1];
2082 xdr_decode_AFSFetchStatus(&bp, &statuses[call->count],
2083 call->count == 0 ? vnode : NULL,
2084 NULL);
2085
2086 call->count++;
2087 if (call->count < call->count2)
2088 goto more_counts;
2089
2090 call->count = 0;
2091 call->unmarshall++;
2092 call->offset = 0;
2093
2094 /* Extract the callback count and array in two steps */
2095 case 3:
2096 _debug("extract CB count");
2097 ret = afs_extract_data(call, &call->tmp, 4, true);
2098 if (ret < 0)
2099 return ret;
2100
2101 tmp = ntohl(call->tmp);
2102 _debug("CB count: %u", tmp);
2103 if (tmp != call->count2)
2104 return -EBADMSG;
2105 call->count = 0;
2106 call->unmarshall++;
2107 more_cbs:
2108 call->offset = 0;
2109
2110 case 4:
2111 _debug("extract CB array");
2112 ret = afs_extract_data(call, call->buffer, 3 * 4, true);
2113 if (ret < 0)
2114 return ret;
2115
2116 _debug("unmarshall CB array");
2117 bp = call->buffer;
2118 callbacks = call->reply[2];
2119 callbacks[call->count].version = ntohl(bp[0]);
2120 callbacks[call->count].expiry = ntohl(bp[1]);
2121 callbacks[call->count].type = ntohl(bp[2]);
2122 statuses = call->reply[1];
2123 if (call->count == 0 && vnode && statuses[0].abort_code == 0)
2124 xdr_decode_AFSCallBack(call, vnode, &bp);
2125 call->count++;
2126 if (call->count < call->count2)
2127 goto more_cbs;
2128
2129 call->offset = 0;
2130 call->unmarshall++;
2131
2132 case 5:
2133 ret = afs_extract_data(call, call->buffer, 6 * 4, false);
2134 if (ret < 0)
2135 return ret;
2136
2137 bp = call->buffer;
2138 if (call->reply[3])
2139 xdr_decode_AFSVolSync(&bp, call->reply[3]);
2140
2141 call->offset = 0;
2142 call->unmarshall++;
2143
2144 case 6:
2145 break;
2146 }
2147
2148 _leave(" = 0 [done]");
2149 return 0;
2150}
2151
2152/*
2153 * FS.InlineBulkStatus operation type
2154 */
2155static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2156 .name = "FS.InlineBulkStatus",
2157 .op = afs_FS_InlineBulkStatus,
2158 .deliver = afs_deliver_fs_inline_bulk_status,
2159 .destructor = afs_flat_call_destructor,
2160};
2161
2162/*
2163 * Fetch the status information for up to 50 files
2164 */
2165int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2166 struct afs_net *net,
2167 struct afs_fid *fids,
2168 struct afs_file_status *statuses,
2169 struct afs_callback *callbacks,
2170 unsigned int nr_fids,
2171 struct afs_volsync *volsync)
2172{
2173 struct afs_call *call;
2174 __be32 *bp;
2175 int i;
2176
2177 _enter(",%x,{%x:%u},%u",
2178 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2179
2180 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2181 (2 + nr_fids * 3) * 4,
2182 21 * 4);
2183 if (!call) {
2184 fc->ac.error = -ENOMEM;
2185 return -ENOMEM;
2186 }
2187
2188 call->key = fc->key;
2189 call->reply[0] = NULL; /* vnode for fid[0] */
2190 call->reply[1] = statuses;
2191 call->reply[2] = callbacks;
2192 call->reply[3] = volsync;
2193 call->count2 = nr_fids;
2194
2195 /* marshall the parameters */
2196 bp = call->request;
2197 *bp++ = htonl(FSINLINEBULKSTATUS);
2198 *bp++ = htonl(nr_fids);
2199 for (i = 0; i < nr_fids; i++) {
2200 *bp++ = htonl(fids[i].vid);
2201 *bp++ = htonl(fids[i].vnode);
2202 *bp++ = htonl(fids[i].unique);
2203 }
2204
2205 call->cb_break = fc->cb_break;
2206 afs_use_fs_server(call, fc->cbi);
2207 trace_afs_make_fs_call(call, &fids[0]);
2208 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2209}