blob: b90ef39ae914aa688580887a28d4aa433591da2c [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070017#include "afs_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
David Howells025db802017-11-02 15:27:51 +000019static const struct afs_fid afs_zero_fid;
20
Linus Torvalds1da177e2005-04-16 15:20:36 -070021/*
David Howells6db3ac32017-03-16 16:27:44 +000022 * We need somewhere to discard into in case the server helpfully returns more
23 * than we asked for in FS.FetchData{,64}.
24 */
25static u8 afs_discard_buffer[64];
26
David Howellsd2ddc772017-11-02 15:27:50 +000027static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
David Howellsc435ee32017-11-02 15:27:49 +000028{
David Howellsd2ddc772017-11-02 15:27:50 +000029 call->cbi = afs_get_cb_interest(cbi);
David Howellsc435ee32017-11-02 15:27:49 +000030}
31
David Howells6db3ac32017-03-16 16:27:44 +000032/*
David Howells260a9802007-04-26 15:59:35 -070033 * decode an AFSFid block
34 */
35static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
36{
37 const __be32 *bp = *_bp;
38
39 fid->vid = ntohl(*bp++);
40 fid->vnode = ntohl(*bp++);
41 fid->unique = ntohl(*bp++);
42 *_bp = bp;
43}
44
45/*
David Howells08e0e7c2007-04-26 15:55:03 -070046 * decode an AFSFetchStatus block
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 */
David Howells08e0e7c2007-04-26 15:55:03 -070048static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
David Howells260a9802007-04-26 15:59:35 -070049 struct afs_file_status *status,
David Howells31143d52007-05-09 02:33:46 -070050 struct afs_vnode *vnode,
51 afs_dataversion_t *store_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -070052{
David Howells31143d52007-05-09 02:33:46 -070053 afs_dataversion_t expected_version;
David Howells08e0e7c2007-04-26 15:55:03 -070054 const __be32 *bp = *_bp;
55 umode_t mode;
David Howells260a9802007-04-26 15:59:35 -070056 u64 data_version, size;
David Howellsc435ee32017-11-02 15:27:49 +000057 bool changed = false;
Eric W. Biedermana0a53862012-02-07 16:20:48 -080058 kuid_t owner;
59 kgid_t group;
David Howells08e0e7c2007-04-26 15:55:03 -070060
David Howellsd2ddc772017-11-02 15:27:50 +000061 if (vnode)
62 write_seqlock(&vnode->cb_lock);
David Howellsc435ee32017-11-02 15:27:49 +000063
David Howells08e0e7c2007-04-26 15:55:03 -070064#define EXTRACT(DST) \
65 do { \
66 u32 x = ntohl(*bp++); \
David Howellsc435ee32017-11-02 15:27:49 +000067 if (DST != x) \
68 changed |= true; \
David Howells08e0e7c2007-04-26 15:55:03 -070069 DST = x; \
70 } while (0)
71
David Howells260a9802007-04-26 15:59:35 -070072 status->if_version = ntohl(*bp++);
73 EXTRACT(status->type);
74 EXTRACT(status->nlink);
75 size = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -070076 data_version = ntohl(*bp++);
David Howells260a9802007-04-26 15:59:35 -070077 EXTRACT(status->author);
Eric W. Biedermana0a53862012-02-07 16:20:48 -080078 owner = make_kuid(&init_user_ns, ntohl(*bp++));
79 changed |= !uid_eq(owner, status->owner);
80 status->owner = owner;
David Howells260a9802007-04-26 15:59:35 -070081 EXTRACT(status->caller_access); /* call ticket dependent */
82 EXTRACT(status->anon_access);
83 EXTRACT(status->mode);
David Howellsbe080a62017-11-02 15:27:49 +000084 bp++; /* parent.vnode */
85 bp++; /* parent.unique */
David Howells08e0e7c2007-04-26 15:55:03 -070086 bp++; /* seg size */
David Howells260a9802007-04-26 15:59:35 -070087 status->mtime_client = ntohl(*bp++);
88 status->mtime_server = ntohl(*bp++);
Eric W. Biedermana0a53862012-02-07 16:20:48 -080089 group = make_kgid(&init_user_ns, ntohl(*bp++));
90 changed |= !gid_eq(group, status->group);
91 status->group = group;
David Howells08e0e7c2007-04-26 15:55:03 -070092 bp++; /* sync counter */
93 data_version |= (u64) ntohl(*bp++) << 32;
David Howellse8d6c552007-07-15 23:40:12 -070094 EXTRACT(status->lock_count);
David Howells260a9802007-04-26 15:59:35 -070095 size |= (u64) ntohl(*bp++) << 32;
96 bp++; /* spare 4 */
David Howells08e0e7c2007-04-26 15:55:03 -070097 *_bp = bp;
98
David Howells260a9802007-04-26 15:59:35 -070099 if (size != status->size) {
100 status->size = size;
101 changed |= true;
David Howells08e0e7c2007-04-26 15:55:03 -0700102 }
David Howells260a9802007-04-26 15:59:35 -0700103 status->mode &= S_IALLUGO;
David Howells08e0e7c2007-04-26 15:55:03 -0700104
105 _debug("vnode time %lx, %lx",
David Howells260a9802007-04-26 15:59:35 -0700106 status->mtime_client, status->mtime_server);
David Howells08e0e7c2007-04-26 15:55:03 -0700107
David Howells260a9802007-04-26 15:59:35 -0700108 if (vnode) {
David Howells260a9802007-04-26 15:59:35 -0700109 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
110 _debug("vnode changed");
111 i_size_write(&vnode->vfs_inode, size);
112 vnode->vfs_inode.i_uid = status->owner;
113 vnode->vfs_inode.i_gid = status->group;
David Howellsd6e43f72011-06-14 00:45:44 +0100114 vnode->vfs_inode.i_generation = vnode->fid.unique;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200115 set_nlink(&vnode->vfs_inode, status->nlink);
David Howells260a9802007-04-26 15:59:35 -0700116
117 mode = vnode->vfs_inode.i_mode;
118 mode &= ~S_IALLUGO;
119 mode |= status->mode;
120 barrier();
121 vnode->vfs_inode.i_mode = mode;
122 }
123
Marc Dionneab94f5d2017-03-16 16:27:47 +0000124 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
David Howells260a9802007-04-26 15:59:35 -0700125 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
126 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
David Howellsd6e43f72011-06-14 00:45:44 +0100127 vnode->vfs_inode.i_version = data_version;
David Howells260a9802007-04-26 15:59:35 -0700128 }
129
David Howells31143d52007-05-09 02:33:46 -0700130 expected_version = status->data_version;
131 if (store_version)
132 expected_version = *store_version;
133
134 if (expected_version != data_version) {
David Howells260a9802007-04-26 15:59:35 -0700135 status->data_version = data_version;
136 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
137 _debug("vnode modified %llx on {%x:%u}",
David S. Millerba3e0e12007-04-26 16:06:22 -0700138 (unsigned long long) data_version,
139 vnode->fid.vid, vnode->fid.vnode);
David Howellsc435ee32017-11-02 15:27:49 +0000140 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
David Howells260a9802007-04-26 15:59:35 -0700141 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
142 }
David Howells31143d52007-05-09 02:33:46 -0700143 } else if (store_version) {
144 status->data_version = data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 }
David Howellsc435ee32017-11-02 15:27:49 +0000146
David Howellsd2ddc772017-11-02 15:27:50 +0000147 if (vnode)
148 write_sequnlock(&vnode->cb_lock);
David Howellsec268152007-04-26 15:49:28 -0700149}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151/*
David Howells08e0e7c2007-04-26 15:55:03 -0700152 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 */
David Howellsc435ee32017-11-02 15:27:49 +0000154static void xdr_decode_AFSCallBack(struct afs_call *call,
155 struct afs_vnode *vnode,
156 const __be32 **_bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157{
David Howellsd2ddc772017-11-02 15:27:50 +0000158 struct afs_cb_interest *old, *cbi = call->cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700159 const __be32 *bp = *_bp;
David Howellsc435ee32017-11-02 15:27:49 +0000160 u32 cb_expiry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
David Howellsc435ee32017-11-02 15:27:49 +0000162 write_seqlock(&vnode->cb_lock);
163
David Howellsd2ddc772017-11-02 15:27:50 +0000164 if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) {
David Howellsc435ee32017-11-02 15:27:49 +0000165 vnode->cb_version = ntohl(*bp++);
166 cb_expiry = ntohl(*bp++);
167 vnode->cb_type = ntohl(*bp++);
168 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
David Howellsd2ddc772017-11-02 15:27:50 +0000169 old = vnode->cb_interest;
170 if (old != call->cbi) {
171 vnode->cb_interest = cbi;
172 cbi = old;
173 }
David Howellsc435ee32017-11-02 15:27:49 +0000174 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
175 } else {
176 bp += 3;
177 }
178
179 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +0000180 call->cbi = cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700181 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700182}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
David Howells260a9802007-04-26 15:59:35 -0700184static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
185 struct afs_callback *cb)
186{
187 const __be32 *bp = *_bp;
188
189 cb->version = ntohl(*bp++);
190 cb->expiry = ntohl(*bp++);
191 cb->type = ntohl(*bp++);
192 *_bp = bp;
193}
194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195/*
David Howells08e0e7c2007-04-26 15:55:03 -0700196 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 */
David Howells08e0e7c2007-04-26 15:55:03 -0700198static void xdr_decode_AFSVolSync(const __be32 **_bp,
199 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
David Howells08e0e7c2007-04-26 15:55:03 -0700201 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
David Howells08e0e7c2007-04-26 15:55:03 -0700203 volsync->creation = ntohl(*bp++);
204 bp++; /* spare2 */
205 bp++; /* spare3 */
206 bp++; /* spare4 */
207 bp++; /* spare5 */
208 bp++; /* spare6 */
209 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700210}
David Howells08e0e7c2007-04-26 15:55:03 -0700211
212/*
David Howells31143d52007-05-09 02:33:46 -0700213 * encode the requested attributes into an AFSStoreStatus block
214 */
215static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
216{
217 __be32 *bp = *_bp;
218 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
219
220 mask = 0;
221 if (attr->ia_valid & ATTR_MTIME) {
222 mask |= AFS_SET_MTIME;
223 mtime = attr->ia_mtime.tv_sec;
224 }
225
226 if (attr->ia_valid & ATTR_UID) {
227 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800228 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700229 }
230
231 if (attr->ia_valid & ATTR_GID) {
232 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800233 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700234 }
235
236 if (attr->ia_valid & ATTR_MODE) {
237 mask |= AFS_SET_MODE;
238 mode = attr->ia_mode & S_IALLUGO;
239 }
240
241 *bp++ = htonl(mask);
242 *bp++ = htonl(mtime);
243 *bp++ = htonl(owner);
244 *bp++ = htonl(group);
245 *bp++ = htonl(mode);
246 *bp++ = 0; /* segment size */
247 *_bp = bp;
248}
249
250/*
David Howells45222b92007-05-10 22:22:20 -0700251 * decode an AFSFetchVolumeStatus block
252 */
253static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
254 struct afs_volume_status *vs)
255{
256 const __be32 *bp = *_bp;
257
258 vs->vid = ntohl(*bp++);
259 vs->parent_id = ntohl(*bp++);
260 vs->online = ntohl(*bp++);
261 vs->in_service = ntohl(*bp++);
262 vs->blessed = ntohl(*bp++);
263 vs->needs_salvage = ntohl(*bp++);
264 vs->type = ntohl(*bp++);
265 vs->min_quota = ntohl(*bp++);
266 vs->max_quota = ntohl(*bp++);
267 vs->blocks_in_use = ntohl(*bp++);
268 vs->part_blocks_avail = ntohl(*bp++);
269 vs->part_max_blocks = ntohl(*bp++);
270 *_bp = bp;
271}
272
273/*
David Howells08e0e7c2007-04-26 15:55:03 -0700274 * deliver reply data to an FS.FetchStatus
275 */
David Howellsd0016482016-08-30 20:42:14 +0100276static int afs_deliver_fs_fetch_status(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700277{
David Howells97e30432017-11-02 15:27:48 +0000278 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700279 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100280 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700281
David Howellsd0016482016-08-30 20:42:14 +0100282 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100283 if (ret < 0)
284 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700285
David Howellsc435ee32017-11-02 15:27:49 +0000286 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
287
David Howells08e0e7c2007-04-26 15:55:03 -0700288 /* unmarshall the reply once we've received all of it */
289 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700290 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howellsc435ee32017-11-02 15:27:49 +0000291 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000292 if (call->reply[1])
293 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700294
295 _leave(" = 0 [done]");
296 return 0;
297}
298
299/*
300 * FS.FetchStatus operation type
301 */
302static const struct afs_call_type afs_RXFSFetchStatus = {
David Howells00d3b7a2007-04-26 15:57:07 -0700303 .name = "FS.FetchStatus",
David Howells025db802017-11-02 15:27:51 +0000304 .op = afs_FS_FetchStatus,
David Howells08e0e7c2007-04-26 15:55:03 -0700305 .deliver = afs_deliver_fs_fetch_status,
David Howells08e0e7c2007-04-26 15:55:03 -0700306 .destructor = afs_flat_call_destructor,
307};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309/*
310 * fetch the status information for a file
311 */
David Howellsd2ddc772017-11-02 15:27:50 +0000312int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313{
David Howellsd2ddc772017-11-02 15:27:50 +0000314 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700315 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000316 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 __be32 *bp;
318
David Howells416351f2007-05-09 02:33:45 -0700319 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000320 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
David Howellsf044c882017-11-02 15:27:45 +0000322 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000323 if (!call) {
324 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700325 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
David Howellsd2ddc772017-11-02 15:27:50 +0000328 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000329 call->reply[0] = vnode;
330 call->reply[1] = volsync;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
332 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700333 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 bp[0] = htonl(FSFETCHSTATUS);
335 bp[1] = htonl(vnode->fid.vid);
336 bp[2] = htonl(vnode->fid.vnode);
337 bp[3] = htonl(vnode->fid.unique);
338
David Howellsd2ddc772017-11-02 15:27:50 +0000339 call->cb_break = fc->cb_break;
340 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000341 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000342 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700343}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345/*
David Howells08e0e7c2007-04-26 15:55:03 -0700346 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 */
David Howellsd0016482016-08-30 20:42:14 +0100348static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349{
David Howells97e30432017-11-02 15:27:48 +0000350 struct afs_vnode *vnode = call->reply[0];
351 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700352 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000353 unsigned int size;
David Howells08e0e7c2007-04-26 15:55:03 -0700354 void *buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700356
David Howells6a0e3992017-03-16 16:27:46 +0000357 _enter("{%u,%zu/%u;%llu/%llu}",
David Howells196ee9c2017-01-05 10:38:34 +0000358 call->unmarshall, call->offset, call->count,
359 req->remain, req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700360
361 switch (call->unmarshall) {
362 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000363 req->actual_len = 0;
David Howells08e0e7c2007-04-26 15:55:03 -0700364 call->offset = 0;
365 call->unmarshall++;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700366 if (call->operation_ID != FSFETCHDATA64) {
367 call->unmarshall++;
368 goto no_msw;
369 }
David Howells08e0e7c2007-04-26 15:55:03 -0700370
David Howellsb9b1f8d2007-05-10 03:15:21 -0700371 /* extract the upper part of the returned data length of an
372 * FSFETCHDATA64 op (which should always be 0 using this
373 * client) */
David Howells08e0e7c2007-04-26 15:55:03 -0700374 case 1:
David Howellsb9b1f8d2007-05-10 03:15:21 -0700375 _debug("extract data length (MSW)");
David Howellsd0016482016-08-30 20:42:14 +0100376 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100377 if (ret < 0)
378 return ret;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700379
David Howells196ee9c2017-01-05 10:38:34 +0000380 req->actual_len = ntohl(call->tmp);
381 req->actual_len <<= 32;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700382 call->offset = 0;
383 call->unmarshall++;
384
385 no_msw:
386 /* extract the returned data length */
387 case 2:
David Howells08e0e7c2007-04-26 15:55:03 -0700388 _debug("extract data length");
David Howellsd0016482016-08-30 20:42:14 +0100389 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100390 if (ret < 0)
391 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700392
David Howells196ee9c2017-01-05 10:38:34 +0000393 req->actual_len |= ntohl(call->tmp);
394 _debug("DATA length: %llu", req->actual_len);
David Howells196ee9c2017-01-05 10:38:34 +0000395
396 req->remain = req->actual_len;
397 call->offset = req->pos & (PAGE_SIZE - 1);
398 req->index = 0;
399 if (req->actual_len == 0)
400 goto no_more_data;
David Howells08e0e7c2007-04-26 15:55:03 -0700401 call->unmarshall++;
402
David Howells196ee9c2017-01-05 10:38:34 +0000403 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000404 ASSERTCMP(req->index, <, req->nr_pages);
David Howells196ee9c2017-01-05 10:38:34 +0000405 if (req->remain > PAGE_SIZE - call->offset)
406 size = PAGE_SIZE - call->offset;
407 else
408 size = req->remain;
409 call->count = call->offset + size;
410 ASSERTCMP(call->count, <=, PAGE_SIZE);
411 req->remain -= size;
412
David Howells08e0e7c2007-04-26 15:55:03 -0700413 /* extract the returned data */
David Howellsb9b1f8d2007-05-10 03:15:21 -0700414 case 3:
David Howells6a0e3992017-03-16 16:27:46 +0000415 _debug("extract data %llu/%llu %zu/%u",
David Howells196ee9c2017-01-05 10:38:34 +0000416 req->remain, req->actual_len, call->offset, call->count);
417
418 buffer = kmap(req->pages[req->index]);
419 ret = afs_extract_data(call, buffer, call->count, true);
420 kunmap(req->pages[req->index]);
421 if (ret < 0)
422 return ret;
423 if (call->offset == PAGE_SIZE) {
424 if (req->page_done)
425 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000426 req->index++;
David Howells196ee9c2017-01-05 10:38:34 +0000427 if (req->remain > 0) {
David Howells196ee9c2017-01-05 10:38:34 +0000428 call->offset = 0;
David Howellse8e581a2017-03-16 16:27:44 +0000429 if (req->index >= req->nr_pages) {
430 call->unmarshall = 4;
David Howells6db3ac32017-03-16 16:27:44 +0000431 goto begin_discard;
David Howellse8e581a2017-03-16 16:27:44 +0000432 }
David Howells196ee9c2017-01-05 10:38:34 +0000433 goto begin_page;
434 }
David Howells08e0e7c2007-04-26 15:55:03 -0700435 }
David Howells6db3ac32017-03-16 16:27:44 +0000436 goto no_more_data;
437
438 /* Discard any excess data the server gave us */
439 begin_discard:
440 case 4:
David Howells6a0e3992017-03-16 16:27:46 +0000441 size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
David Howells6db3ac32017-03-16 16:27:44 +0000442 call->count = size;
David Howells6a0e3992017-03-16 16:27:46 +0000443 _debug("extract discard %llu/%llu %zu/%u",
David Howells6db3ac32017-03-16 16:27:44 +0000444 req->remain, req->actual_len, call->offset, call->count);
445
446 call->offset = 0;
447 ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
448 req->remain -= call->offset;
449 if (ret < 0)
450 return ret;
451 if (req->remain > 0)
452 goto begin_discard;
David Howells08e0e7c2007-04-26 15:55:03 -0700453
David Howells196ee9c2017-01-05 10:38:34 +0000454 no_more_data:
David Howells08e0e7c2007-04-26 15:55:03 -0700455 call->offset = 0;
David Howells6db3ac32017-03-16 16:27:44 +0000456 call->unmarshall = 5;
David Howells08e0e7c2007-04-26 15:55:03 -0700457
458 /* extract the metadata */
David Howells6db3ac32017-03-16 16:27:44 +0000459 case 5:
David Howellsd0016482016-08-30 20:42:14 +0100460 ret = afs_extract_data(call, call->buffer,
461 (21 + 3 + 6) * 4, false);
David Howells372ee162016-08-03 14:11:40 +0100462 if (ret < 0)
463 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700464
465 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700466 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howellsc435ee32017-11-02 15:27:49 +0000467 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000468 if (call->reply[1])
469 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700470
471 call->offset = 0;
472 call->unmarshall++;
473
David Howells6db3ac32017-03-16 16:27:44 +0000474 case 6:
David Howells08e0e7c2007-04-26 15:55:03 -0700475 break;
476 }
477
David Howells6db3ac32017-03-16 16:27:44 +0000478 for (; req->index < req->nr_pages; req->index++) {
479 if (call->count < PAGE_SIZE)
480 zero_user_segment(req->pages[req->index],
481 call->count, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000482 if (req->page_done)
483 req->page_done(call, req);
David Howells6db3ac32017-03-16 16:27:44 +0000484 call->count = 0;
David Howells416351f2007-05-09 02:33:45 -0700485 }
486
David Howells08e0e7c2007-04-26 15:55:03 -0700487 _leave(" = 0 [done]");
488 return 0;
489}
490
David Howells196ee9c2017-01-05 10:38:34 +0000491static void afs_fetch_data_destructor(struct afs_call *call)
492{
David Howells97e30432017-11-02 15:27:48 +0000493 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000494
495 afs_put_read(req);
496 afs_flat_call_destructor(call);
497}
498
David Howells08e0e7c2007-04-26 15:55:03 -0700499/*
500 * FS.FetchData operation type
501 */
502static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700503 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000504 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700505 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000506 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700507};
508
David Howellsb9b1f8d2007-05-10 03:15:21 -0700509static const struct afs_call_type afs_RXFSFetchData64 = {
510 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000511 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700512 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000513 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700514};
515
516/*
517 * fetch data from a very large file
518 */
David Howellsd2ddc772017-11-02 15:27:50 +0000519static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700520{
David Howellsd2ddc772017-11-02 15:27:50 +0000521 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700522 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000523 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700524 __be32 *bp;
525
526 _enter("");
527
David Howellsf044c882017-11-02 15:27:45 +0000528 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700529 if (!call)
530 return -ENOMEM;
531
David Howellsd2ddc772017-11-02 15:27:50 +0000532 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000533 call->reply[0] = vnode;
534 call->reply[1] = NULL; /* volsync */
535 call->reply[2] = req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700536
537 /* marshall the parameters */
538 bp = call->request;
539 bp[0] = htonl(FSFETCHDATA64);
540 bp[1] = htonl(vnode->fid.vid);
541 bp[2] = htonl(vnode->fid.vnode);
542 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000543 bp[4] = htonl(upper_32_bits(req->pos));
544 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700545 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000546 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700547
David Howells196ee9c2017-01-05 10:38:34 +0000548 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000549 call->cb_break = fc->cb_break;
550 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000551 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000552 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700553}
554
David Howells08e0e7c2007-04-26 15:55:03 -0700555/*
556 * fetch data from a file
557 */
David Howellsd2ddc772017-11-02 15:27:50 +0000558int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700559{
David Howellsd2ddc772017-11-02 15:27:50 +0000560 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700561 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000562 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 __be32 *bp;
564
David Howells196ee9c2017-01-05 10:38:34 +0000565 if (upper_32_bits(req->pos) ||
566 upper_32_bits(req->len) ||
567 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000568 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700569
David Howells08e0e7c2007-04-26 15:55:03 -0700570 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
David Howellsf044c882017-11-02 15:27:45 +0000572 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700573 if (!call)
574 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
David Howellsd2ddc772017-11-02 15:27:50 +0000576 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000577 call->reply[0] = vnode;
578 call->reply[1] = NULL; /* volsync */
579 call->reply[2] = req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
581 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700582 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700584 bp[1] = htonl(vnode->fid.vid);
585 bp[2] = htonl(vnode->fid.vnode);
586 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000587 bp[4] = htonl(lower_32_bits(req->pos));
588 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
David Howells196ee9c2017-01-05 10:38:34 +0000590 atomic_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000591 call->cb_break = fc->cb_break;
592 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000593 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000594 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700595}
David Howells260a9802007-04-26 15:59:35 -0700596
597/*
598 * deliver reply data to an FS.CreateFile or an FS.MakeDir
599 */
David Howellsd0016482016-08-30 20:42:14 +0100600static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700601{
David Howells97e30432017-11-02 15:27:48 +0000602 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700603 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100604 int ret;
David Howells260a9802007-04-26 15:59:35 -0700605
David Howellsd0016482016-08-30 20:42:14 +0100606 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700607
David Howellsd0016482016-08-30 20:42:14 +0100608 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100609 if (ret < 0)
610 return ret;
David Howells260a9802007-04-26 15:59:35 -0700611
612 /* unmarshall the reply once we've received all of it */
613 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000614 xdr_decode_AFSFid(&bp, call->reply[1]);
615 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700616 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000617 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
618 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700619
620 _leave(" = 0 [done]");
621 return 0;
622}
623
624/*
625 * FS.CreateFile and FS.MakeDir operation type
626 */
David Howells025db802017-11-02 15:27:51 +0000627static const struct afs_call_type afs_RXFSCreateFile = {
628 .name = "FS.CreateFile",
629 .op = afs_FS_CreateFile,
630 .deliver = afs_deliver_fs_create_vnode,
631 .destructor = afs_flat_call_destructor,
632};
633
634static const struct afs_call_type afs_RXFSMakeDir = {
635 .name = "FS.MakeDir",
636 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700637 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700638 .destructor = afs_flat_call_destructor,
639};
640
641/*
642 * create a file or make a directory
643 */
David Howells8b2a4642017-11-02 15:27:50 +0000644int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700645 const char *name,
646 umode_t mode,
647 struct afs_fid *newfid,
648 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000649 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700650{
David Howellsd2ddc772017-11-02 15:27:50 +0000651 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700652 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000653 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700654 size_t namesz, reqsz, padsz;
655 __be32 *bp;
656
657 _enter("");
658
659 namesz = strlen(name);
660 padsz = (4 - (namesz & 3)) & 3;
661 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
662
David Howells025db802017-11-02 15:27:51 +0000663 call = afs_alloc_flat_call(
664 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
665 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700666 if (!call)
667 return -ENOMEM;
668
David Howellsd2ddc772017-11-02 15:27:50 +0000669 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000670 call->reply[0] = vnode;
671 call->reply[1] = newfid;
672 call->reply[2] = newstatus;
673 call->reply[3] = newcb;
David Howells260a9802007-04-26 15:59:35 -0700674
675 /* marshall the parameters */
676 bp = call->request;
677 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
678 *bp++ = htonl(vnode->fid.vid);
679 *bp++ = htonl(vnode->fid.vnode);
680 *bp++ = htonl(vnode->fid.unique);
681 *bp++ = htonl(namesz);
682 memcpy(bp, name, namesz);
683 bp = (void *) bp + namesz;
684 if (padsz > 0) {
685 memset(bp, 0, padsz);
686 bp = (void *) bp + padsz;
687 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000688 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
689 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700690 *bp++ = 0; /* owner */
691 *bp++ = 0; /* group */
692 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
693 *bp++ = 0; /* segment size */
694
David Howellsd2ddc772017-11-02 15:27:50 +0000695 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000696 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000697 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700698}
699
700/*
701 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
702 */
David Howellsd0016482016-08-30 20:42:14 +0100703static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700704{
David Howells97e30432017-11-02 15:27:48 +0000705 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700706 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100707 int ret;
David Howells260a9802007-04-26 15:59:35 -0700708
David Howellsd0016482016-08-30 20:42:14 +0100709 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700710
David Howellsd0016482016-08-30 20:42:14 +0100711 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100712 if (ret < 0)
713 return ret;
David Howells260a9802007-04-26 15:59:35 -0700714
715 /* unmarshall the reply once we've received all of it */
716 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700717 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000718 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700719
720 _leave(" = 0 [done]");
721 return 0;
722}
723
724/*
725 * FS.RemoveDir/FS.RemoveFile operation type
726 */
David Howells025db802017-11-02 15:27:51 +0000727static const struct afs_call_type afs_RXFSRemoveFile = {
728 .name = "FS.RemoveFile",
729 .op = afs_FS_RemoveFile,
730 .deliver = afs_deliver_fs_remove,
731 .destructor = afs_flat_call_destructor,
732};
733
734static const struct afs_call_type afs_RXFSRemoveDir = {
735 .name = "FS.RemoveDir",
736 .op = afs_FS_RemoveDir,
David Howells260a9802007-04-26 15:59:35 -0700737 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700738 .destructor = afs_flat_call_destructor,
739};
740
741/*
742 * remove a file or directory
743 */
David Howellsd2ddc772017-11-02 15:27:50 +0000744int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir)
David Howells260a9802007-04-26 15:59:35 -0700745{
David Howellsd2ddc772017-11-02 15:27:50 +0000746 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700747 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000748 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700749 size_t namesz, reqsz, padsz;
750 __be32 *bp;
751
752 _enter("");
753
754 namesz = strlen(name);
755 padsz = (4 - (namesz & 3)) & 3;
756 reqsz = (5 * 4) + namesz + padsz;
757
David Howells025db802017-11-02 15:27:51 +0000758 call = afs_alloc_flat_call(
759 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
760 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700761 if (!call)
762 return -ENOMEM;
763
David Howellsd2ddc772017-11-02 15:27:50 +0000764 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000765 call->reply[0] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700766
767 /* marshall the parameters */
768 bp = call->request;
769 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
770 *bp++ = htonl(vnode->fid.vid);
771 *bp++ = htonl(vnode->fid.vnode);
772 *bp++ = htonl(vnode->fid.unique);
773 *bp++ = htonl(namesz);
774 memcpy(bp, name, namesz);
775 bp = (void *) bp + namesz;
776 if (padsz > 0) {
777 memset(bp, 0, padsz);
778 bp = (void *) bp + padsz;
779 }
780
David Howellsd2ddc772017-11-02 15:27:50 +0000781 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000782 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000783 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700784}
785
786/*
787 * deliver reply data to an FS.Link
788 */
David Howellsd0016482016-08-30 20:42:14 +0100789static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700790{
David Howells97e30432017-11-02 15:27:48 +0000791 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700792 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100793 int ret;
David Howells260a9802007-04-26 15:59:35 -0700794
David Howellsd0016482016-08-30 20:42:14 +0100795 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700796
David Howellsd0016482016-08-30 20:42:14 +0100797 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100798 if (ret < 0)
799 return ret;
David Howells260a9802007-04-26 15:59:35 -0700800
801 /* unmarshall the reply once we've received all of it */
802 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700803 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
804 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000805 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700806
807 _leave(" = 0 [done]");
808 return 0;
809}
810
811/*
812 * FS.Link operation type
813 */
814static const struct afs_call_type afs_RXFSLink = {
815 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000816 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700817 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700818 .destructor = afs_flat_call_destructor,
819};
820
821/*
822 * make a hard link
823 */
David Howellsd2ddc772017-11-02 15:27:50 +0000824int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
825 const char *name)
David Howells260a9802007-04-26 15:59:35 -0700826{
David Howellsd2ddc772017-11-02 15:27:50 +0000827 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700828 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000829 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700830 size_t namesz, reqsz, padsz;
831 __be32 *bp;
832
833 _enter("");
834
835 namesz = strlen(name);
836 padsz = (4 - (namesz & 3)) & 3;
837 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
838
David Howellsf044c882017-11-02 15:27:45 +0000839 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700840 if (!call)
841 return -ENOMEM;
842
David Howellsd2ddc772017-11-02 15:27:50 +0000843 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000844 call->reply[0] = dvnode;
845 call->reply[1] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700846
847 /* marshall the parameters */
848 bp = call->request;
849 *bp++ = htonl(FSLINK);
850 *bp++ = htonl(dvnode->fid.vid);
851 *bp++ = htonl(dvnode->fid.vnode);
852 *bp++ = htonl(dvnode->fid.unique);
853 *bp++ = htonl(namesz);
854 memcpy(bp, name, namesz);
855 bp = (void *) bp + namesz;
856 if (padsz > 0) {
857 memset(bp, 0, padsz);
858 bp = (void *) bp + padsz;
859 }
860 *bp++ = htonl(vnode->fid.vid);
861 *bp++ = htonl(vnode->fid.vnode);
862 *bp++ = htonl(vnode->fid.unique);
863
David Howellsd2ddc772017-11-02 15:27:50 +0000864 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000865 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000866 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700867}
868
869/*
870 * deliver reply data to an FS.Symlink
871 */
David Howellsd0016482016-08-30 20:42:14 +0100872static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700873{
David Howells97e30432017-11-02 15:27:48 +0000874 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700875 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100876 int ret;
David Howells260a9802007-04-26 15:59:35 -0700877
David Howellsd0016482016-08-30 20:42:14 +0100878 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700879
David Howellsd0016482016-08-30 20:42:14 +0100880 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100881 if (ret < 0)
882 return ret;
David Howells260a9802007-04-26 15:59:35 -0700883
884 /* unmarshall the reply once we've received all of it */
885 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000886 xdr_decode_AFSFid(&bp, call->reply[1]);
887 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700888 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000889 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700890
891 _leave(" = 0 [done]");
892 return 0;
893}
894
895/*
896 * FS.Symlink operation type
897 */
898static const struct afs_call_type afs_RXFSSymlink = {
899 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +0000900 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -0700901 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700902 .destructor = afs_flat_call_destructor,
903};
904
905/*
906 * create a symbolic link
907 */
David Howells8b2a4642017-11-02 15:27:50 +0000908int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700909 const char *name,
910 const char *contents,
911 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +0000912 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -0700913{
David Howellsd2ddc772017-11-02 15:27:50 +0000914 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700915 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000916 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700917 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
918 __be32 *bp;
919
920 _enter("");
921
922 namesz = strlen(name);
923 padsz = (4 - (namesz & 3)) & 3;
924
925 c_namesz = strlen(contents);
926 c_padsz = (4 - (c_namesz & 3)) & 3;
927
928 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
929
David Howellsf044c882017-11-02 15:27:45 +0000930 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700931 (3 + 21 + 21 + 6) * 4);
932 if (!call)
933 return -ENOMEM;
934
David Howellsd2ddc772017-11-02 15:27:50 +0000935 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000936 call->reply[0] = vnode;
937 call->reply[1] = newfid;
938 call->reply[2] = newstatus;
David Howells260a9802007-04-26 15:59:35 -0700939
940 /* marshall the parameters */
941 bp = call->request;
942 *bp++ = htonl(FSSYMLINK);
943 *bp++ = htonl(vnode->fid.vid);
944 *bp++ = htonl(vnode->fid.vnode);
945 *bp++ = htonl(vnode->fid.unique);
946 *bp++ = htonl(namesz);
947 memcpy(bp, name, namesz);
948 bp = (void *) bp + namesz;
949 if (padsz > 0) {
950 memset(bp, 0, padsz);
951 bp = (void *) bp + padsz;
952 }
953 *bp++ = htonl(c_namesz);
954 memcpy(bp, contents, c_namesz);
955 bp = (void *) bp + c_namesz;
956 if (c_padsz > 0) {
957 memset(bp, 0, c_padsz);
958 bp = (void *) bp + c_padsz;
959 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000960 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
961 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700962 *bp++ = 0; /* owner */
963 *bp++ = 0; /* group */
964 *bp++ = htonl(S_IRWXUGO); /* unix mode */
965 *bp++ = 0; /* segment size */
966
David Howellsd2ddc772017-11-02 15:27:50 +0000967 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000968 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000969 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700970}
971
972/*
973 * deliver reply data to an FS.Rename
974 */
David Howellsd0016482016-08-30 20:42:14 +0100975static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700976{
David Howells97e30432017-11-02 15:27:48 +0000977 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700978 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100979 int ret;
David Howells260a9802007-04-26 15:59:35 -0700980
David Howellsd0016482016-08-30 20:42:14 +0100981 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700982
David Howellsd0016482016-08-30 20:42:14 +0100983 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100984 if (ret < 0)
985 return ret;
David Howells260a9802007-04-26 15:59:35 -0700986
987 /* unmarshall the reply once we've received all of it */
988 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700989 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700990 if (new_dvnode != orig_dvnode)
David Howells31143d52007-05-09 02:33:46 -0700991 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
992 NULL);
David Howells97e30432017-11-02 15:27:48 +0000993 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700994
995 _leave(" = 0 [done]");
996 return 0;
997}
998
999/*
1000 * FS.Rename operation type
1001 */
1002static const struct afs_call_type afs_RXFSRename = {
1003 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001004 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001005 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001006 .destructor = afs_flat_call_destructor,
1007};
1008
1009/*
1010 * create a symbolic link
1011 */
David Howells8b2a4642017-11-02 15:27:50 +00001012int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001013 const char *orig_name,
1014 struct afs_vnode *new_dvnode,
David Howellsd2ddc772017-11-02 15:27:50 +00001015 const char *new_name)
David Howells260a9802007-04-26 15:59:35 -07001016{
David Howellsd2ddc772017-11-02 15:27:50 +00001017 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001018 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001019 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001020 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1021 __be32 *bp;
1022
1023 _enter("");
1024
1025 o_namesz = strlen(orig_name);
1026 o_padsz = (4 - (o_namesz & 3)) & 3;
1027
1028 n_namesz = strlen(new_name);
1029 n_padsz = (4 - (n_namesz & 3)) & 3;
1030
1031 reqsz = (4 * 4) +
1032 4 + o_namesz + o_padsz +
1033 (3 * 4) +
1034 4 + n_namesz + n_padsz;
1035
David Howellsf044c882017-11-02 15:27:45 +00001036 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001037 if (!call)
1038 return -ENOMEM;
1039
David Howellsd2ddc772017-11-02 15:27:50 +00001040 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001041 call->reply[0] = orig_dvnode;
1042 call->reply[1] = new_dvnode;
David Howells260a9802007-04-26 15:59:35 -07001043
1044 /* marshall the parameters */
1045 bp = call->request;
1046 *bp++ = htonl(FSRENAME);
1047 *bp++ = htonl(orig_dvnode->fid.vid);
1048 *bp++ = htonl(orig_dvnode->fid.vnode);
1049 *bp++ = htonl(orig_dvnode->fid.unique);
1050 *bp++ = htonl(o_namesz);
1051 memcpy(bp, orig_name, o_namesz);
1052 bp = (void *) bp + o_namesz;
1053 if (o_padsz > 0) {
1054 memset(bp, 0, o_padsz);
1055 bp = (void *) bp + o_padsz;
1056 }
1057
1058 *bp++ = htonl(new_dvnode->fid.vid);
1059 *bp++ = htonl(new_dvnode->fid.vnode);
1060 *bp++ = htonl(new_dvnode->fid.unique);
1061 *bp++ = htonl(n_namesz);
1062 memcpy(bp, new_name, n_namesz);
1063 bp = (void *) bp + n_namesz;
1064 if (n_padsz > 0) {
1065 memset(bp, 0, n_padsz);
1066 bp = (void *) bp + n_padsz;
1067 }
1068
David Howellsd2ddc772017-11-02 15:27:50 +00001069 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001070 trace_afs_make_fs_call(call, &orig_dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001071 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001072}
David Howells31143d52007-05-09 02:33:46 -07001073
1074/*
1075 * deliver reply data to an FS.StoreData
1076 */
David Howellsd0016482016-08-30 20:42:14 +01001077static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001078{
David Howells97e30432017-11-02 15:27:48 +00001079 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001080 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001081 int ret;
David Howells31143d52007-05-09 02:33:46 -07001082
David Howellsd0016482016-08-30 20:42:14 +01001083 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001084
David Howellsd0016482016-08-30 20:42:14 +01001085 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001086 if (ret < 0)
1087 return ret;
David Howells31143d52007-05-09 02:33:46 -07001088
1089 /* unmarshall the reply once we've received all of it */
1090 bp = call->buffer;
1091 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1092 &call->store_version);
David Howells97e30432017-11-02 15:27:48 +00001093 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001094
1095 afs_pages_written_back(vnode, call);
1096
1097 _leave(" = 0 [done]");
1098 return 0;
1099}
1100
1101/*
1102 * FS.StoreData operation type
1103 */
1104static const struct afs_call_type afs_RXFSStoreData = {
1105 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001106 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001107 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001108 .destructor = afs_flat_call_destructor,
1109};
1110
David Howellsb9b1f8d2007-05-10 03:15:21 -07001111static const struct afs_call_type afs_RXFSStoreData64 = {
1112 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001113 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001114 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001115 .destructor = afs_flat_call_destructor,
1116};
1117
1118/*
1119 * store a set of pages to a very large file
1120 */
David Howells8b2a4642017-11-02 15:27:50 +00001121static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001122 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001123 pgoff_t first, pgoff_t last,
1124 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001125 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001126{
David Howells4343d002017-11-02 15:27:52 +00001127 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001128 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001129 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001130 __be32 *bp;
1131
1132 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001133 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001134
David Howellsf044c882017-11-02 15:27:45 +00001135 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001136 (4 + 6 + 3 * 2) * 4,
1137 (21 + 6) * 4);
1138 if (!call)
1139 return -ENOMEM;
1140
David Howells4343d002017-11-02 15:27:52 +00001141 call->key = fc->key;
1142 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001143 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001144 call->first = first;
1145 call->last = last;
1146 call->first_offset = offset;
1147 call->last_to = to;
1148 call->send_pages = true;
1149 call->store_version = vnode->status.data_version + 1;
1150
1151 /* marshall the parameters */
1152 bp = call->request;
1153 *bp++ = htonl(FSSTOREDATA64);
1154 *bp++ = htonl(vnode->fid.vid);
1155 *bp++ = htonl(vnode->fid.vnode);
1156 *bp++ = htonl(vnode->fid.unique);
1157
Marc Dionneab94f5d2017-03-16 16:27:47 +00001158 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1159 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001160 *bp++ = 0; /* owner */
1161 *bp++ = 0; /* group */
1162 *bp++ = 0; /* unix mode */
1163 *bp++ = 0; /* segment size */
1164
1165 *bp++ = htonl(pos >> 32);
1166 *bp++ = htonl((u32) pos);
1167 *bp++ = htonl(size >> 32);
1168 *bp++ = htonl((u32) size);
1169 *bp++ = htonl(i_size >> 32);
1170 *bp++ = htonl((u32) i_size);
1171
David Howells025db802017-11-02 15:27:51 +00001172 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001173 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001174}
1175
David Howells31143d52007-05-09 02:33:46 -07001176/*
1177 * store a set of pages
1178 */
David Howells4343d002017-11-02 15:27:52 +00001179int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001180 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001181 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001182{
David Howells4343d002017-11-02 15:27:52 +00001183 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001184 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001185 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001186 loff_t size, pos, i_size;
1187 __be32 *bp;
1188
1189 _enter(",%x,{%x:%u},,",
David Howells4343d002017-11-02 15:27:52 +00001190 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001191
David Howells146a1192017-03-16 16:27:47 +00001192 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001193 if (first != last)
1194 size += (loff_t)(last - first) << PAGE_SHIFT;
1195 pos = (loff_t)first << PAGE_SHIFT;
1196 pos += offset;
1197
1198 i_size = i_size_read(&vnode->vfs_inode);
1199 if (pos + size > i_size)
1200 i_size = size + pos;
1201
1202 _debug("size %llx, at %llx, i_size %llx",
1203 (unsigned long long) size, (unsigned long long) pos,
1204 (unsigned long long) i_size);
1205
David Howellsb9b1f8d2007-05-10 03:15:21 -07001206 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001207 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001208 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001209
David Howellsf044c882017-11-02 15:27:45 +00001210 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001211 (4 + 6 + 3) * 4,
1212 (21 + 6) * 4);
1213 if (!call)
1214 return -ENOMEM;
1215
David Howells4343d002017-11-02 15:27:52 +00001216 call->key = fc->key;
1217 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001218 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001219 call->first = first;
1220 call->last = last;
1221 call->first_offset = offset;
1222 call->last_to = to;
1223 call->send_pages = true;
1224 call->store_version = vnode->status.data_version + 1;
1225
1226 /* marshall the parameters */
1227 bp = call->request;
1228 *bp++ = htonl(FSSTOREDATA);
1229 *bp++ = htonl(vnode->fid.vid);
1230 *bp++ = htonl(vnode->fid.vnode);
1231 *bp++ = htonl(vnode->fid.unique);
1232
Marc Dionneab94f5d2017-03-16 16:27:47 +00001233 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1234 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001235 *bp++ = 0; /* owner */
1236 *bp++ = 0; /* group */
1237 *bp++ = 0; /* unix mode */
1238 *bp++ = 0; /* segment size */
1239
1240 *bp++ = htonl(pos);
1241 *bp++ = htonl(size);
1242 *bp++ = htonl(i_size);
1243
David Howellsd2ddc772017-11-02 15:27:50 +00001244 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001245 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001246 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001247}
1248
1249/*
1250 * deliver reply data to an FS.StoreStatus
1251 */
David Howellsd0016482016-08-30 20:42:14 +01001252static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001253{
1254 afs_dataversion_t *store_version;
David Howells97e30432017-11-02 15:27:48 +00001255 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001256 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001257 int ret;
David Howells31143d52007-05-09 02:33:46 -07001258
David Howellsd0016482016-08-30 20:42:14 +01001259 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001260
David Howellsd0016482016-08-30 20:42:14 +01001261 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001262 if (ret < 0)
1263 return ret;
David Howells31143d52007-05-09 02:33:46 -07001264
1265 /* unmarshall the reply once we've received all of it */
1266 store_version = NULL;
1267 if (call->operation_ID == FSSTOREDATA)
1268 store_version = &call->store_version;
1269
1270 bp = call->buffer;
1271 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
David Howells97e30432017-11-02 15:27:48 +00001272 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001273
1274 _leave(" = 0 [done]");
1275 return 0;
1276}
1277
1278/*
1279 * FS.StoreStatus operation type
1280 */
1281static const struct afs_call_type afs_RXFSStoreStatus = {
1282 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001283 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001284 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001285 .destructor = afs_flat_call_destructor,
1286};
1287
1288static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1289 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001290 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001291 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001292 .destructor = afs_flat_call_destructor,
1293};
1294
David Howellsb9b1f8d2007-05-10 03:15:21 -07001295static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1296 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001297 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001298 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001299 .destructor = afs_flat_call_destructor,
1300};
1301
1302/*
1303 * set the attributes on a very large file, using FS.StoreData rather than
1304 * FS.StoreStatus so as to alter the file size also
1305 */
David Howellsd2ddc772017-11-02 15:27:50 +00001306static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001307{
David Howellsd2ddc772017-11-02 15:27:50 +00001308 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001309 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001310 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001311 __be32 *bp;
1312
1313 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001314 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001315
1316 ASSERT(attr->ia_valid & ATTR_SIZE);
1317
David Howellsf044c882017-11-02 15:27:45 +00001318 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001319 (4 + 6 + 3 * 2) * 4,
1320 (21 + 6) * 4);
1321 if (!call)
1322 return -ENOMEM;
1323
David Howellsd2ddc772017-11-02 15:27:50 +00001324 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001325 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001326 call->store_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001327
1328 /* marshall the parameters */
1329 bp = call->request;
1330 *bp++ = htonl(FSSTOREDATA64);
1331 *bp++ = htonl(vnode->fid.vid);
1332 *bp++ = htonl(vnode->fid.vnode);
1333 *bp++ = htonl(vnode->fid.unique);
1334
1335 xdr_encode_AFS_StoreStatus(&bp, attr);
1336
1337 *bp++ = 0; /* position of start of write */
1338 *bp++ = 0;
1339 *bp++ = 0; /* size of write */
1340 *bp++ = 0;
1341 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1342 *bp++ = htonl((u32) attr->ia_size);
1343
David Howellsd2ddc772017-11-02 15:27:50 +00001344 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001345 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001346 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001347}
1348
David Howells31143d52007-05-09 02:33:46 -07001349/*
1350 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1351 * so as to alter the file size also
1352 */
David Howellsd2ddc772017-11-02 15:27:50 +00001353static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001354{
David Howellsd2ddc772017-11-02 15:27:50 +00001355 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001356 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001357 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001358 __be32 *bp;
1359
1360 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001361 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001362
1363 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001364 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001365 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001366
David Howellsf044c882017-11-02 15:27:45 +00001367 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001368 (4 + 6 + 3) * 4,
1369 (21 + 6) * 4);
1370 if (!call)
1371 return -ENOMEM;
1372
David Howellsd2ddc772017-11-02 15:27:50 +00001373 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001374 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001375 call->store_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001376
1377 /* marshall the parameters */
1378 bp = call->request;
1379 *bp++ = htonl(FSSTOREDATA);
1380 *bp++ = htonl(vnode->fid.vid);
1381 *bp++ = htonl(vnode->fid.vnode);
1382 *bp++ = htonl(vnode->fid.unique);
1383
1384 xdr_encode_AFS_StoreStatus(&bp, attr);
1385
1386 *bp++ = 0; /* position of start of write */
1387 *bp++ = 0; /* size of write */
1388 *bp++ = htonl(attr->ia_size); /* new file length */
1389
David Howellsd2ddc772017-11-02 15:27:50 +00001390 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001391 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001392 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001393}
1394
1395/*
1396 * set the attributes on a file, using FS.StoreData if there's a change in file
1397 * size, and FS.StoreStatus otherwise
1398 */
David Howellsd2ddc772017-11-02 15:27:50 +00001399int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001400{
David Howellsd2ddc772017-11-02 15:27:50 +00001401 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001402 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001403 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001404 __be32 *bp;
1405
1406 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001407 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001408
1409 _enter(",%x,{%x:%u},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001410 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001411
David Howellsf044c882017-11-02 15:27:45 +00001412 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001413 (4 + 6) * 4,
1414 (21 + 6) * 4);
1415 if (!call)
1416 return -ENOMEM;
1417
David Howellsd2ddc772017-11-02 15:27:50 +00001418 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001419 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001420
1421 /* marshall the parameters */
1422 bp = call->request;
1423 *bp++ = htonl(FSSTORESTATUS);
1424 *bp++ = htonl(vnode->fid.vid);
1425 *bp++ = htonl(vnode->fid.vnode);
1426 *bp++ = htonl(vnode->fid.unique);
1427
1428 xdr_encode_AFS_StoreStatus(&bp, attr);
1429
David Howellsd2ddc772017-11-02 15:27:50 +00001430 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001431 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001432 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001433}
David Howells45222b92007-05-10 22:22:20 -07001434
1435/*
1436 * deliver reply data to an FS.GetVolumeStatus
1437 */
David Howellsd0016482016-08-30 20:42:14 +01001438static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001439{
1440 const __be32 *bp;
1441 char *p;
1442 int ret;
1443
David Howellsd0016482016-08-30 20:42:14 +01001444 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001445
1446 switch (call->unmarshall) {
1447 case 0:
1448 call->offset = 0;
1449 call->unmarshall++;
1450
1451 /* extract the returned status record */
1452 case 1:
1453 _debug("extract status");
David Howellsd0016482016-08-30 20:42:14 +01001454 ret = afs_extract_data(call, call->buffer,
1455 12 * 4, true);
David Howells372ee162016-08-03 14:11:40 +01001456 if (ret < 0)
1457 return ret;
David Howells45222b92007-05-10 22:22:20 -07001458
1459 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001460 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001461 call->offset = 0;
1462 call->unmarshall++;
1463
1464 /* extract the volume name length */
1465 case 2:
David Howellsd0016482016-08-30 20:42:14 +01001466 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001467 if (ret < 0)
1468 return ret;
David Howells45222b92007-05-10 22:22:20 -07001469
1470 call->count = ntohl(call->tmp);
1471 _debug("volname length: %u", call->count);
1472 if (call->count >= AFSNAMEMAX)
1473 return -EBADMSG;
1474 call->offset = 0;
1475 call->unmarshall++;
1476
1477 /* extract the volume name */
1478 case 3:
1479 _debug("extract volname");
1480 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001481 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001482 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001483 if (ret < 0)
1484 return ret;
David Howells45222b92007-05-10 22:22:20 -07001485 }
1486
David Howells97e30432017-11-02 15:27:48 +00001487 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001488 p[call->count] = 0;
1489 _debug("volname '%s'", p);
1490
1491 call->offset = 0;
1492 call->unmarshall++;
1493
1494 /* extract the volume name padding */
1495 if ((call->count & 3) == 0) {
1496 call->unmarshall++;
1497 goto no_volname_padding;
1498 }
1499 call->count = 4 - (call->count & 3);
1500
1501 case 4:
David Howellsd0016482016-08-30 20:42:14 +01001502 ret = afs_extract_data(call, call->buffer,
1503 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001504 if (ret < 0)
1505 return ret;
David Howells45222b92007-05-10 22:22:20 -07001506
1507 call->offset = 0;
1508 call->unmarshall++;
1509 no_volname_padding:
1510
1511 /* extract the offline message length */
1512 case 5:
David Howellsd0016482016-08-30 20:42:14 +01001513 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001514 if (ret < 0)
1515 return ret;
David Howells45222b92007-05-10 22:22:20 -07001516
1517 call->count = ntohl(call->tmp);
1518 _debug("offline msg length: %u", call->count);
1519 if (call->count >= AFSNAMEMAX)
1520 return -EBADMSG;
1521 call->offset = 0;
1522 call->unmarshall++;
1523
1524 /* extract the offline message */
1525 case 6:
1526 _debug("extract offline");
1527 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001528 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001529 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001530 if (ret < 0)
1531 return ret;
David Howells45222b92007-05-10 22:22:20 -07001532 }
1533
David Howells97e30432017-11-02 15:27:48 +00001534 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001535 p[call->count] = 0;
1536 _debug("offline '%s'", p);
1537
1538 call->offset = 0;
1539 call->unmarshall++;
1540
1541 /* extract the offline message padding */
1542 if ((call->count & 3) == 0) {
1543 call->unmarshall++;
1544 goto no_offline_padding;
1545 }
1546 call->count = 4 - (call->count & 3);
1547
1548 case 7:
David Howellsd0016482016-08-30 20:42:14 +01001549 ret = afs_extract_data(call, call->buffer,
1550 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001551 if (ret < 0)
1552 return ret;
David Howells45222b92007-05-10 22:22:20 -07001553
1554 call->offset = 0;
1555 call->unmarshall++;
1556 no_offline_padding:
1557
1558 /* extract the message of the day length */
1559 case 8:
David Howellsd0016482016-08-30 20:42:14 +01001560 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001561 if (ret < 0)
1562 return ret;
David Howells45222b92007-05-10 22:22:20 -07001563
1564 call->count = ntohl(call->tmp);
1565 _debug("motd length: %u", call->count);
1566 if (call->count >= AFSNAMEMAX)
1567 return -EBADMSG;
1568 call->offset = 0;
1569 call->unmarshall++;
1570
1571 /* extract the message of the day */
1572 case 9:
1573 _debug("extract motd");
1574 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001575 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001576 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001577 if (ret < 0)
1578 return ret;
David Howells45222b92007-05-10 22:22:20 -07001579 }
1580
David Howells97e30432017-11-02 15:27:48 +00001581 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001582 p[call->count] = 0;
1583 _debug("motd '%s'", p);
1584
1585 call->offset = 0;
1586 call->unmarshall++;
1587
1588 /* extract the message of the day padding */
David Howellsd0016482016-08-30 20:42:14 +01001589 call->count = (4 - (call->count & 3)) & 3;
David Howells45222b92007-05-10 22:22:20 -07001590
1591 case 10:
David Howellsd0016482016-08-30 20:42:14 +01001592 ret = afs_extract_data(call, call->buffer,
1593 call->count, false);
David Howells372ee162016-08-03 14:11:40 +01001594 if (ret < 0)
1595 return ret;
David Howells45222b92007-05-10 22:22:20 -07001596
1597 call->offset = 0;
1598 call->unmarshall++;
David Howells45222b92007-05-10 22:22:20 -07001599 case 11:
David Howells45222b92007-05-10 22:22:20 -07001600 break;
1601 }
1602
David Howells45222b92007-05-10 22:22:20 -07001603 _leave(" = 0 [done]");
1604 return 0;
1605}
1606
1607/*
1608 * destroy an FS.GetVolumeStatus call
1609 */
1610static void afs_get_volume_status_call_destructor(struct afs_call *call)
1611{
David Howells97e30432017-11-02 15:27:48 +00001612 kfree(call->reply[2]);
1613 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001614 afs_flat_call_destructor(call);
1615}
1616
1617/*
1618 * FS.GetVolumeStatus operation type
1619 */
1620static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1621 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001622 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001623 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001624 .destructor = afs_get_volume_status_call_destructor,
1625};
1626
1627/*
1628 * fetch the status of a volume
1629 */
David Howells8b2a4642017-11-02 15:27:50 +00001630int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001631 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001632{
David Howellsd2ddc772017-11-02 15:27:50 +00001633 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001634 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001635 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001636 __be32 *bp;
1637 void *tmpbuf;
1638
1639 _enter("");
1640
1641 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1642 if (!tmpbuf)
1643 return -ENOMEM;
1644
David Howellsf044c882017-11-02 15:27:45 +00001645 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001646 if (!call) {
1647 kfree(tmpbuf);
1648 return -ENOMEM;
1649 }
1650
David Howellsd2ddc772017-11-02 15:27:50 +00001651 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001652 call->reply[0] = vnode;
1653 call->reply[1] = vs;
1654 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001655
1656 /* marshall the parameters */
1657 bp = call->request;
1658 bp[0] = htonl(FSGETVOLUMESTATUS);
1659 bp[1] = htonl(vnode->fid.vid);
1660
David Howellsd2ddc772017-11-02 15:27:50 +00001661 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001662 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001663 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells45222b92007-05-10 22:22:20 -07001664}
David Howellse8d6c552007-07-15 23:40:12 -07001665
1666/*
1667 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1668 */
David Howellsd0016482016-08-30 20:42:14 +01001669static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001670{
1671 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001672 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001673
David Howellsd0016482016-08-30 20:42:14 +01001674 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001675
David Howellsd0016482016-08-30 20:42:14 +01001676 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001677 if (ret < 0)
1678 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001679
1680 /* unmarshall the reply once we've received all of it */
1681 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001682 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001683
1684 _leave(" = 0 [done]");
1685 return 0;
1686}
1687
1688/*
1689 * FS.SetLock operation type
1690 */
1691static const struct afs_call_type afs_RXFSSetLock = {
1692 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001693 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001694 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001695 .destructor = afs_flat_call_destructor,
1696};
1697
1698/*
1699 * FS.ExtendLock operation type
1700 */
1701static const struct afs_call_type afs_RXFSExtendLock = {
1702 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001703 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001704 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001705 .destructor = afs_flat_call_destructor,
1706};
1707
1708/*
1709 * FS.ReleaseLock operation type
1710 */
1711static const struct afs_call_type afs_RXFSReleaseLock = {
1712 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001713 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001714 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001715 .destructor = afs_flat_call_destructor,
1716};
1717
1718/*
David Howellsd2ddc772017-11-02 15:27:50 +00001719 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001720 */
David Howellsd2ddc772017-11-02 15:27:50 +00001721int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001722{
David Howellsd2ddc772017-11-02 15:27:50 +00001723 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001724 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001725 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001726 __be32 *bp;
1727
1728 _enter("");
1729
David Howellsf044c882017-11-02 15:27:45 +00001730 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001731 if (!call)
1732 return -ENOMEM;
1733
David Howellsd2ddc772017-11-02 15:27:50 +00001734 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001735 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001736
1737 /* marshall the parameters */
1738 bp = call->request;
1739 *bp++ = htonl(FSSETLOCK);
1740 *bp++ = htonl(vnode->fid.vid);
1741 *bp++ = htonl(vnode->fid.vnode);
1742 *bp++ = htonl(vnode->fid.unique);
1743 *bp++ = htonl(type);
1744
David Howellsd2ddc772017-11-02 15:27:50 +00001745 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001746 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001747 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001748}
1749
1750/*
1751 * extend a lock on a file
1752 */
David Howellsd2ddc772017-11-02 15:27:50 +00001753int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001754{
David Howellsd2ddc772017-11-02 15:27:50 +00001755 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001756 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001757 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001758 __be32 *bp;
1759
1760 _enter("");
1761
David Howellsf044c882017-11-02 15:27:45 +00001762 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001763 if (!call)
1764 return -ENOMEM;
1765
David Howellsd2ddc772017-11-02 15:27:50 +00001766 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001767 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001768
1769 /* marshall the parameters */
1770 bp = call->request;
1771 *bp++ = htonl(FSEXTENDLOCK);
1772 *bp++ = htonl(vnode->fid.vid);
1773 *bp++ = htonl(vnode->fid.vnode);
1774 *bp++ = htonl(vnode->fid.unique);
1775
David Howellsd2ddc772017-11-02 15:27:50 +00001776 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001777 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001778 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001779}
1780
1781/*
1782 * release a lock on a file
1783 */
David Howellsd2ddc772017-11-02 15:27:50 +00001784int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001785{
David Howellsd2ddc772017-11-02 15:27:50 +00001786 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001787 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001788 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001789 __be32 *bp;
1790
1791 _enter("");
1792
David Howellsf044c882017-11-02 15:27:45 +00001793 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001794 if (!call)
1795 return -ENOMEM;
1796
David Howellsd2ddc772017-11-02 15:27:50 +00001797 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001798 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001799
1800 /* marshall the parameters */
1801 bp = call->request;
1802 *bp++ = htonl(FSRELEASELOCK);
1803 *bp++ = htonl(vnode->fid.vid);
1804 *bp++ = htonl(vnode->fid.vnode);
1805 *bp++ = htonl(vnode->fid.unique);
1806
David Howellsd2ddc772017-11-02 15:27:50 +00001807 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001808 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001809 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsc435ee32017-11-02 15:27:49 +00001810}
1811
1812/*
1813 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1814 */
1815static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1816{
1817 return afs_transfer_reply(call);
1818}
1819
1820/*
1821 * FS.GiveUpAllCallBacks operation type
1822 */
1823static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1824 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001825 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001826 .deliver = afs_deliver_fs_give_up_all_callbacks,
1827 .destructor = afs_flat_call_destructor,
1828};
1829
1830/*
1831 * Flush all the callbacks we have on a server.
1832 */
David Howellsd2ddc772017-11-02 15:27:50 +00001833int afs_fs_give_up_all_callbacks(struct afs_net *net,
1834 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001835 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001836 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001837{
1838 struct afs_call *call;
1839 __be32 *bp;
1840
1841 _enter("");
1842
David Howellsd2ddc772017-11-02 15:27:50 +00001843 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001844 if (!call)
1845 return -ENOMEM;
1846
1847 call->key = key;
1848
1849 /* marshall the parameters */
1850 bp = call->request;
1851 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1852
1853 /* Can't take a ref on server */
David Howellsd2ddc772017-11-02 15:27:50 +00001854 return afs_make_call(ac, call, GFP_NOFS, false);
1855}
1856
1857/*
1858 * Deliver reply data to an FS.GetCapabilities operation.
1859 */
1860static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1861{
1862 u32 count;
1863 int ret;
1864
1865 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count);
1866
1867again:
1868 switch (call->unmarshall) {
1869 case 0:
1870 call->offset = 0;
1871 call->unmarshall++;
1872
1873 /* Extract the capabilities word count */
1874 case 1:
1875 ret = afs_extract_data(call, &call->tmp,
1876 1 * sizeof(__be32),
1877 true);
1878 if (ret < 0)
1879 return ret;
1880
1881 count = ntohl(call->tmp);
1882
1883 call->count = count;
1884 call->count2 = count;
1885 call->offset = 0;
1886 call->unmarshall++;
1887
1888 /* Extract capabilities words */
1889 case 2:
1890 count = min(call->count, 16U);
1891 ret = afs_extract_data(call, call->buffer,
1892 count * sizeof(__be32),
1893 call->count > 16);
1894 if (ret < 0)
1895 return ret;
1896
1897 /* TODO: Examine capabilities */
1898
1899 call->count -= count;
1900 if (call->count > 0)
1901 goto again;
1902 call->offset = 0;
1903 call->unmarshall++;
1904 break;
1905 }
1906
1907 _leave(" = 0 [done]");
1908 return 0;
1909}
1910
1911/*
1912 * FS.GetCapabilities operation type
1913 */
1914static const struct afs_call_type afs_RXFSGetCapabilities = {
1915 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001916 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001917 .deliver = afs_deliver_fs_get_capabilities,
1918 .destructor = afs_flat_call_destructor,
1919};
1920
1921/*
1922 * Probe a fileserver for the capabilities that it supports. This can
1923 * return up to 196 words.
1924 */
1925int afs_fs_get_capabilities(struct afs_net *net,
1926 struct afs_server *server,
1927 struct afs_addr_cursor *ac,
1928 struct key *key)
1929{
1930 struct afs_call *call;
1931 __be32 *bp;
1932
1933 _enter("");
1934
1935 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1936 if (!call)
1937 return -ENOMEM;
1938
1939 call->key = key;
1940
1941 /* marshall the parameters */
1942 bp = call->request;
1943 *bp++ = htonl(FSGETCAPABILITIES);
1944
1945 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00001946 trace_afs_make_fs_call(call, NULL);
David Howellsd2ddc772017-11-02 15:27:50 +00001947 return afs_make_call(ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001948}