blob: 36f58adde030dbf091843cc28a2395ba25bb8674 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070019/*
David Howells6db3ac32017-03-16 16:27:44 +000020 * We need somewhere to discard into in case the server helpfully returns more
21 * than we asked for in FS.FetchData{,64}.
22 */
23static u8 afs_discard_buffer[64];
24
25/*
David Howells260a9802007-04-26 15:59:35 -070026 * decode an AFSFid block
27 */
28static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
29{
30 const __be32 *bp = *_bp;
31
32 fid->vid = ntohl(*bp++);
33 fid->vnode = ntohl(*bp++);
34 fid->unique = ntohl(*bp++);
35 *_bp = bp;
36}
37
38/*
David Howells08e0e7c2007-04-26 15:55:03 -070039 * decode an AFSFetchStatus block
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 */
David Howells08e0e7c2007-04-26 15:55:03 -070041static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
David Howells260a9802007-04-26 15:59:35 -070042 struct afs_file_status *status,
David Howells31143d52007-05-09 02:33:46 -070043 struct afs_vnode *vnode,
44 afs_dataversion_t *store_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045{
David Howells31143d52007-05-09 02:33:46 -070046 afs_dataversion_t expected_version;
David Howells08e0e7c2007-04-26 15:55:03 -070047 const __be32 *bp = *_bp;
48 umode_t mode;
David Howells260a9802007-04-26 15:59:35 -070049 u64 data_version, size;
David Howells08e0e7c2007-04-26 15:55:03 -070050 u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
Eric W. Biedermana0a53862012-02-07 16:20:48 -080051 kuid_t owner;
52 kgid_t group;
David Howells08e0e7c2007-04-26 15:55:03 -070053
54#define EXTRACT(DST) \
55 do { \
56 u32 x = ntohl(*bp++); \
57 changed |= DST - x; \
58 DST = x; \
59 } while (0)
60
David Howells260a9802007-04-26 15:59:35 -070061 status->if_version = ntohl(*bp++);
62 EXTRACT(status->type);
63 EXTRACT(status->nlink);
64 size = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -070065 data_version = ntohl(*bp++);
David Howells260a9802007-04-26 15:59:35 -070066 EXTRACT(status->author);
Eric W. Biedermana0a53862012-02-07 16:20:48 -080067 owner = make_kuid(&init_user_ns, ntohl(*bp++));
68 changed |= !uid_eq(owner, status->owner);
69 status->owner = owner;
David Howells260a9802007-04-26 15:59:35 -070070 EXTRACT(status->caller_access); /* call ticket dependent */
71 EXTRACT(status->anon_access);
72 EXTRACT(status->mode);
73 EXTRACT(status->parent.vnode);
74 EXTRACT(status->parent.unique);
David Howells08e0e7c2007-04-26 15:55:03 -070075 bp++; /* seg size */
David Howells260a9802007-04-26 15:59:35 -070076 status->mtime_client = ntohl(*bp++);
77 status->mtime_server = ntohl(*bp++);
Eric W. Biedermana0a53862012-02-07 16:20:48 -080078 group = make_kgid(&init_user_ns, ntohl(*bp++));
79 changed |= !gid_eq(group, status->group);
80 status->group = group;
David Howells08e0e7c2007-04-26 15:55:03 -070081 bp++; /* sync counter */
82 data_version |= (u64) ntohl(*bp++) << 32;
David Howellse8d6c552007-07-15 23:40:12 -070083 EXTRACT(status->lock_count);
David Howells260a9802007-04-26 15:59:35 -070084 size |= (u64) ntohl(*bp++) << 32;
85 bp++; /* spare 4 */
David Howells08e0e7c2007-04-26 15:55:03 -070086 *_bp = bp;
87
David Howells260a9802007-04-26 15:59:35 -070088 if (size != status->size) {
89 status->size = size;
90 changed |= true;
David Howells08e0e7c2007-04-26 15:55:03 -070091 }
David Howells260a9802007-04-26 15:59:35 -070092 status->mode &= S_IALLUGO;
David Howells08e0e7c2007-04-26 15:55:03 -070093
94 _debug("vnode time %lx, %lx",
David Howells260a9802007-04-26 15:59:35 -070095 status->mtime_client, status->mtime_server);
David Howells08e0e7c2007-04-26 15:55:03 -070096
David Howells260a9802007-04-26 15:59:35 -070097 if (vnode) {
98 status->parent.vid = vnode->fid.vid;
99 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
100 _debug("vnode changed");
101 i_size_write(&vnode->vfs_inode, size);
102 vnode->vfs_inode.i_uid = status->owner;
103 vnode->vfs_inode.i_gid = status->group;
David Howellsd6e43f72011-06-14 00:45:44 +0100104 vnode->vfs_inode.i_generation = vnode->fid.unique;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200105 set_nlink(&vnode->vfs_inode, status->nlink);
David Howells260a9802007-04-26 15:59:35 -0700106
107 mode = vnode->vfs_inode.i_mode;
108 mode &= ~S_IALLUGO;
109 mode |= status->mode;
110 barrier();
111 vnode->vfs_inode.i_mode = mode;
112 }
113
Marc Dionneab94f5d2017-03-16 16:27:47 +0000114 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
David Howells260a9802007-04-26 15:59:35 -0700115 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
116 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
David Howellsd6e43f72011-06-14 00:45:44 +0100117 vnode->vfs_inode.i_version = data_version;
David Howells260a9802007-04-26 15:59:35 -0700118 }
119
David Howells31143d52007-05-09 02:33:46 -0700120 expected_version = status->data_version;
121 if (store_version)
122 expected_version = *store_version;
123
124 if (expected_version != data_version) {
David Howells260a9802007-04-26 15:59:35 -0700125 status->data_version = data_version;
126 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
127 _debug("vnode modified %llx on {%x:%u}",
David S. Millerba3e0e12007-04-26 16:06:22 -0700128 (unsigned long long) data_version,
129 vnode->fid.vid, vnode->fid.vnode);
David Howells260a9802007-04-26 15:59:35 -0700130 set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
131 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
132 }
David Howells31143d52007-05-09 02:33:46 -0700133 } else if (store_version) {
134 status->data_version = data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 }
David Howellsec268152007-04-26 15:49:28 -0700136}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138/*
David Howells08e0e7c2007-04-26 15:55:03 -0700139 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 */
David Howells08e0e7c2007-04-26 15:55:03 -0700141static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142{
David Howells08e0e7c2007-04-26 15:55:03 -0700143 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
David Howells08e0e7c2007-04-26 15:55:03 -0700145 vnode->cb_version = ntohl(*bp++);
146 vnode->cb_expiry = ntohl(*bp++);
147 vnode->cb_type = ntohl(*bp++);
Tina Ruchandani56e71432017-03-16 16:27:46 +0000148 vnode->cb_expires = vnode->cb_expiry + ktime_get_real_seconds();
David Howells08e0e7c2007-04-26 15:55:03 -0700149 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700150}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
David Howells260a9802007-04-26 15:59:35 -0700152static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
153 struct afs_callback *cb)
154{
155 const __be32 *bp = *_bp;
156
157 cb->version = ntohl(*bp++);
158 cb->expiry = ntohl(*bp++);
159 cb->type = ntohl(*bp++);
160 *_bp = bp;
161}
162
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163/*
David Howells08e0e7c2007-04-26 15:55:03 -0700164 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 */
David Howells08e0e7c2007-04-26 15:55:03 -0700166static void xdr_decode_AFSVolSync(const __be32 **_bp,
167 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168{
David Howells08e0e7c2007-04-26 15:55:03 -0700169 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
David Howells08e0e7c2007-04-26 15:55:03 -0700171 volsync->creation = ntohl(*bp++);
172 bp++; /* spare2 */
173 bp++; /* spare3 */
174 bp++; /* spare4 */
175 bp++; /* spare5 */
176 bp++; /* spare6 */
177 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700178}
David Howells08e0e7c2007-04-26 15:55:03 -0700179
180/*
David Howells31143d52007-05-09 02:33:46 -0700181 * encode the requested attributes into an AFSStoreStatus block
182 */
183static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
184{
185 __be32 *bp = *_bp;
186 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
187
188 mask = 0;
189 if (attr->ia_valid & ATTR_MTIME) {
190 mask |= AFS_SET_MTIME;
191 mtime = attr->ia_mtime.tv_sec;
192 }
193
194 if (attr->ia_valid & ATTR_UID) {
195 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800196 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700197 }
198
199 if (attr->ia_valid & ATTR_GID) {
200 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800201 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700202 }
203
204 if (attr->ia_valid & ATTR_MODE) {
205 mask |= AFS_SET_MODE;
206 mode = attr->ia_mode & S_IALLUGO;
207 }
208
209 *bp++ = htonl(mask);
210 *bp++ = htonl(mtime);
211 *bp++ = htonl(owner);
212 *bp++ = htonl(group);
213 *bp++ = htonl(mode);
214 *bp++ = 0; /* segment size */
215 *_bp = bp;
216}
217
218/*
David Howells45222b92007-05-10 22:22:20 -0700219 * decode an AFSFetchVolumeStatus block
220 */
221static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
222 struct afs_volume_status *vs)
223{
224 const __be32 *bp = *_bp;
225
226 vs->vid = ntohl(*bp++);
227 vs->parent_id = ntohl(*bp++);
228 vs->online = ntohl(*bp++);
229 vs->in_service = ntohl(*bp++);
230 vs->blessed = ntohl(*bp++);
231 vs->needs_salvage = ntohl(*bp++);
232 vs->type = ntohl(*bp++);
233 vs->min_quota = ntohl(*bp++);
234 vs->max_quota = ntohl(*bp++);
235 vs->blocks_in_use = ntohl(*bp++);
236 vs->part_blocks_avail = ntohl(*bp++);
237 vs->part_max_blocks = ntohl(*bp++);
238 *_bp = bp;
239}
240
241/*
David Howells08e0e7c2007-04-26 15:55:03 -0700242 * deliver reply data to an FS.FetchStatus
243 */
David Howellsd0016482016-08-30 20:42:14 +0100244static int afs_deliver_fs_fetch_status(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700245{
David Howells97e30432017-11-02 15:27:48 +0000246 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700247 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100248 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700249
David Howellsd0016482016-08-30 20:42:14 +0100250 _enter("");
David Howells08e0e7c2007-04-26 15:55:03 -0700251
David Howellsd0016482016-08-30 20:42:14 +0100252 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100253 if (ret < 0)
254 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700255
256 /* unmarshall the reply once we've received all of it */
257 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700258 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700259 xdr_decode_AFSCallBack(&bp, vnode);
David Howells97e30432017-11-02 15:27:48 +0000260 if (call->reply[1])
261 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700262
263 _leave(" = 0 [done]");
264 return 0;
265}
266
267/*
268 * FS.FetchStatus operation type
269 */
270static const struct afs_call_type afs_RXFSFetchStatus = {
David Howells00d3b7a2007-04-26 15:57:07 -0700271 .name = "FS.FetchStatus",
David Howells08e0e7c2007-04-26 15:55:03 -0700272 .deliver = afs_deliver_fs_fetch_status,
David Howells08e0e7c2007-04-26 15:55:03 -0700273 .destructor = afs_flat_call_destructor,
274};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276/*
277 * fetch the status information for a file
278 */
David Howells08e0e7c2007-04-26 15:55:03 -0700279int afs_fs_fetch_file_status(struct afs_server *server,
David Howells00d3b7a2007-04-26 15:57:07 -0700280 struct key *key,
David Howells08e0e7c2007-04-26 15:55:03 -0700281 struct afs_vnode *vnode,
282 struct afs_volsync *volsync,
David Howells56ff9c82017-01-05 10:38:36 +0000283 bool async)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284{
David Howells08e0e7c2007-04-26 15:55:03 -0700285 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000286 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 __be32 *bp;
288
David Howells416351f2007-05-09 02:33:45 -0700289 _enter(",%x,{%x:%u},,",
David Howells260a9802007-04-26 15:59:35 -0700290 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
David Howellsf044c882017-11-02 15:27:45 +0000292 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700293 if (!call)
294 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
David Howells00d3b7a2007-04-26 15:57:07 -0700296 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000297 call->reply[0] = vnode;
298 call->reply[1] = volsync;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700301 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 bp[0] = htonl(FSFETCHSTATUS);
303 bp[1] = htonl(vnode->fid.vid);
304 bp[2] = htonl(vnode->fid.vnode);
305 bp[3] = htonl(vnode->fid.unique);
306
David Howells56ff9c82017-01-05 10:38:36 +0000307 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellsec268152007-04-26 15:49:28 -0700308}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310/*
David Howells08e0e7c2007-04-26 15:55:03 -0700311 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 */
David Howellsd0016482016-08-30 20:42:14 +0100313static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314{
David Howells97e30432017-11-02 15:27:48 +0000315 struct afs_vnode *vnode = call->reply[0];
316 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700317 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000318 unsigned int size;
David Howells08e0e7c2007-04-26 15:55:03 -0700319 void *buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700321
David Howells6a0e3992017-03-16 16:27:46 +0000322 _enter("{%u,%zu/%u;%llu/%llu}",
David Howells196ee9c2017-01-05 10:38:34 +0000323 call->unmarshall, call->offset, call->count,
324 req->remain, req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700325
326 switch (call->unmarshall) {
327 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000328 req->actual_len = 0;
David Howells08e0e7c2007-04-26 15:55:03 -0700329 call->offset = 0;
330 call->unmarshall++;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700331 if (call->operation_ID != FSFETCHDATA64) {
332 call->unmarshall++;
333 goto no_msw;
334 }
David Howells08e0e7c2007-04-26 15:55:03 -0700335
David Howellsb9b1f8d2007-05-10 03:15:21 -0700336 /* extract the upper part of the returned data length of an
337 * FSFETCHDATA64 op (which should always be 0 using this
338 * client) */
David Howells08e0e7c2007-04-26 15:55:03 -0700339 case 1:
David Howellsb9b1f8d2007-05-10 03:15:21 -0700340 _debug("extract data length (MSW)");
David Howellsd0016482016-08-30 20:42:14 +0100341 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100342 if (ret < 0)
343 return ret;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700344
David Howells196ee9c2017-01-05 10:38:34 +0000345 req->actual_len = ntohl(call->tmp);
346 req->actual_len <<= 32;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700347 call->offset = 0;
348 call->unmarshall++;
349
350 no_msw:
351 /* extract the returned data length */
352 case 2:
David Howells08e0e7c2007-04-26 15:55:03 -0700353 _debug("extract data length");
David Howellsd0016482016-08-30 20:42:14 +0100354 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +0100355 if (ret < 0)
356 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700357
David Howells196ee9c2017-01-05 10:38:34 +0000358 req->actual_len |= ntohl(call->tmp);
359 _debug("DATA length: %llu", req->actual_len);
David Howells196ee9c2017-01-05 10:38:34 +0000360
361 req->remain = req->actual_len;
362 call->offset = req->pos & (PAGE_SIZE - 1);
363 req->index = 0;
364 if (req->actual_len == 0)
365 goto no_more_data;
David Howells08e0e7c2007-04-26 15:55:03 -0700366 call->unmarshall++;
367
David Howells196ee9c2017-01-05 10:38:34 +0000368 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000369 ASSERTCMP(req->index, <, req->nr_pages);
David Howells196ee9c2017-01-05 10:38:34 +0000370 if (req->remain > PAGE_SIZE - call->offset)
371 size = PAGE_SIZE - call->offset;
372 else
373 size = req->remain;
374 call->count = call->offset + size;
375 ASSERTCMP(call->count, <=, PAGE_SIZE);
376 req->remain -= size;
377
David Howells08e0e7c2007-04-26 15:55:03 -0700378 /* extract the returned data */
David Howellsb9b1f8d2007-05-10 03:15:21 -0700379 case 3:
David Howells6a0e3992017-03-16 16:27:46 +0000380 _debug("extract data %llu/%llu %zu/%u",
David Howells196ee9c2017-01-05 10:38:34 +0000381 req->remain, req->actual_len, call->offset, call->count);
382
383 buffer = kmap(req->pages[req->index]);
384 ret = afs_extract_data(call, buffer, call->count, true);
385 kunmap(req->pages[req->index]);
386 if (ret < 0)
387 return ret;
388 if (call->offset == PAGE_SIZE) {
389 if (req->page_done)
390 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000391 req->index++;
David Howells196ee9c2017-01-05 10:38:34 +0000392 if (req->remain > 0) {
David Howells196ee9c2017-01-05 10:38:34 +0000393 call->offset = 0;
David Howellse8e581a2017-03-16 16:27:44 +0000394 if (req->index >= req->nr_pages) {
395 call->unmarshall = 4;
David Howells6db3ac32017-03-16 16:27:44 +0000396 goto begin_discard;
David Howellse8e581a2017-03-16 16:27:44 +0000397 }
David Howells196ee9c2017-01-05 10:38:34 +0000398 goto begin_page;
399 }
David Howells08e0e7c2007-04-26 15:55:03 -0700400 }
David Howells6db3ac32017-03-16 16:27:44 +0000401 goto no_more_data;
402
403 /* Discard any excess data the server gave us */
404 begin_discard:
405 case 4:
David Howells6a0e3992017-03-16 16:27:46 +0000406 size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
David Howells6db3ac32017-03-16 16:27:44 +0000407 call->count = size;
David Howells6a0e3992017-03-16 16:27:46 +0000408 _debug("extract discard %llu/%llu %zu/%u",
David Howells6db3ac32017-03-16 16:27:44 +0000409 req->remain, req->actual_len, call->offset, call->count);
410
411 call->offset = 0;
412 ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
413 req->remain -= call->offset;
414 if (ret < 0)
415 return ret;
416 if (req->remain > 0)
417 goto begin_discard;
David Howells08e0e7c2007-04-26 15:55:03 -0700418
David Howells196ee9c2017-01-05 10:38:34 +0000419 no_more_data:
David Howells08e0e7c2007-04-26 15:55:03 -0700420 call->offset = 0;
David Howells6db3ac32017-03-16 16:27:44 +0000421 call->unmarshall = 5;
David Howells08e0e7c2007-04-26 15:55:03 -0700422
423 /* extract the metadata */
David Howells6db3ac32017-03-16 16:27:44 +0000424 case 5:
David Howellsd0016482016-08-30 20:42:14 +0100425 ret = afs_extract_data(call, call->buffer,
426 (21 + 3 + 6) * 4, false);
David Howells372ee162016-08-03 14:11:40 +0100427 if (ret < 0)
428 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700429
430 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700431 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700432 xdr_decode_AFSCallBack(&bp, vnode);
David Howells97e30432017-11-02 15:27:48 +0000433 if (call->reply[1])
434 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700435
436 call->offset = 0;
437 call->unmarshall++;
438
David Howells6db3ac32017-03-16 16:27:44 +0000439 case 6:
David Howells08e0e7c2007-04-26 15:55:03 -0700440 break;
441 }
442
David Howells6db3ac32017-03-16 16:27:44 +0000443 for (; req->index < req->nr_pages; req->index++) {
444 if (call->count < PAGE_SIZE)
445 zero_user_segment(req->pages[req->index],
446 call->count, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000447 if (req->page_done)
448 req->page_done(call, req);
David Howells6db3ac32017-03-16 16:27:44 +0000449 call->count = 0;
David Howells416351f2007-05-09 02:33:45 -0700450 }
451
David Howells08e0e7c2007-04-26 15:55:03 -0700452 _leave(" = 0 [done]");
453 return 0;
454}
455
David Howells196ee9c2017-01-05 10:38:34 +0000456static void afs_fetch_data_destructor(struct afs_call *call)
457{
David Howells97e30432017-11-02 15:27:48 +0000458 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000459
460 afs_put_read(req);
461 afs_flat_call_destructor(call);
462}
463
David Howells08e0e7c2007-04-26 15:55:03 -0700464/*
465 * FS.FetchData operation type
466 */
467static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700468 .name = "FS.FetchData",
David Howells08e0e7c2007-04-26 15:55:03 -0700469 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000470 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700471};
472
David Howellsb9b1f8d2007-05-10 03:15:21 -0700473static const struct afs_call_type afs_RXFSFetchData64 = {
474 .name = "FS.FetchData64",
475 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000476 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700477};
478
479/*
480 * fetch data from a very large file
481 */
482static int afs_fs_fetch_data64(struct afs_server *server,
483 struct key *key,
484 struct afs_vnode *vnode,
David Howells196ee9c2017-01-05 10:38:34 +0000485 struct afs_read *req,
David Howells56ff9c82017-01-05 10:38:36 +0000486 bool async)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700487{
488 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000489 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700490 __be32 *bp;
491
492 _enter("");
493
David Howellsf044c882017-11-02 15:27:45 +0000494 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700495 if (!call)
496 return -ENOMEM;
497
498 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000499 call->reply[0] = vnode;
500 call->reply[1] = NULL; /* volsync */
501 call->reply[2] = req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700502 call->operation_ID = FSFETCHDATA64;
503
504 /* marshall the parameters */
505 bp = call->request;
506 bp[0] = htonl(FSFETCHDATA64);
507 bp[1] = htonl(vnode->fid.vid);
508 bp[2] = htonl(vnode->fid.vnode);
509 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000510 bp[4] = htonl(upper_32_bits(req->pos));
511 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700512 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000513 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700514
David Howells196ee9c2017-01-05 10:38:34 +0000515 atomic_inc(&req->usage);
David Howells56ff9c82017-01-05 10:38:36 +0000516 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700517}
518
David Howells08e0e7c2007-04-26 15:55:03 -0700519/*
520 * fetch data from a file
521 */
522int afs_fs_fetch_data(struct afs_server *server,
David Howells00d3b7a2007-04-26 15:57:07 -0700523 struct key *key,
David Howells08e0e7c2007-04-26 15:55:03 -0700524 struct afs_vnode *vnode,
David Howells196ee9c2017-01-05 10:38:34 +0000525 struct afs_read *req,
David Howells56ff9c82017-01-05 10:38:36 +0000526 bool async)
David Howells08e0e7c2007-04-26 15:55:03 -0700527{
528 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000529 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 __be32 *bp;
531
David Howells196ee9c2017-01-05 10:38:34 +0000532 if (upper_32_bits(req->pos) ||
533 upper_32_bits(req->len) ||
534 upper_32_bits(req->pos + req->len))
David Howells56ff9c82017-01-05 10:38:36 +0000535 return afs_fs_fetch_data64(server, key, vnode, req, async);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700536
David Howells08e0e7c2007-04-26 15:55:03 -0700537 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
David Howellsf044c882017-11-02 15:27:45 +0000539 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700540 if (!call)
541 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
David Howells00d3b7a2007-04-26 15:57:07 -0700543 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000544 call->reply[0] = vnode;
545 call->reply[1] = NULL; /* volsync */
546 call->reply[2] = req;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700547 call->operation_ID = FSFETCHDATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
549 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700550 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700552 bp[1] = htonl(vnode->fid.vid);
553 bp[2] = htonl(vnode->fid.vnode);
554 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000555 bp[4] = htonl(lower_32_bits(req->pos));
556 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
David Howells196ee9c2017-01-05 10:38:34 +0000558 atomic_inc(&req->usage);
David Howells56ff9c82017-01-05 10:38:36 +0000559 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellsec268152007-04-26 15:49:28 -0700560}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562/*
David Howells08e0e7c2007-04-26 15:55:03 -0700563 * deliver reply data to an FS.GiveUpCallBacks
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 */
David Howellsd0016482016-08-30 20:42:14 +0100565static int afs_deliver_fs_give_up_callbacks(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566{
David Howellsd0016482016-08-30 20:42:14 +0100567 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
David Howells372ee162016-08-03 14:11:40 +0100569 /* shouldn't be any reply data */
David Howellsd0016482016-08-30 20:42:14 +0100570 return afs_extract_data(call, NULL, 0, false);
David Howells08e0e7c2007-04-26 15:55:03 -0700571}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
David Howells08e0e7c2007-04-26 15:55:03 -0700573/*
574 * FS.GiveUpCallBacks operation type
575 */
576static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
David Howells00d3b7a2007-04-26 15:57:07 -0700577 .name = "FS.GiveUpCallBacks",
David Howells08e0e7c2007-04-26 15:55:03 -0700578 .deliver = afs_deliver_fs_give_up_callbacks,
David Howells08e0e7c2007-04-26 15:55:03 -0700579 .destructor = afs_flat_call_destructor,
580};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
David Howells08e0e7c2007-04-26 15:55:03 -0700582/*
583 * give up a set of callbacks
584 * - the callbacks are held in the server->cb_break ring
585 */
David Howellsf044c882017-11-02 15:27:45 +0000586int afs_fs_give_up_callbacks(struct afs_net *net,
587 struct afs_server *server,
David Howells56ff9c82017-01-05 10:38:36 +0000588 bool async)
David Howells08e0e7c2007-04-26 15:55:03 -0700589{
590 struct afs_call *call;
591 size_t ncallbacks;
592 __be32 *bp, *tp;
593 int loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
David Howells08e0e7c2007-04-26 15:55:03 -0700595 ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail,
596 ARRAY_SIZE(server->cb_break));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
David Howells08e0e7c2007-04-26 15:55:03 -0700598 _enter("{%zu},", ncallbacks);
599
600 if (ncallbacks == 0)
601 return 0;
602 if (ncallbacks > AFSCBMAX)
603 ncallbacks = AFSCBMAX;
604
605 _debug("break %zu callbacks", ncallbacks);
606
David Howellsf044c882017-11-02 15:27:45 +0000607 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpCallBacks,
David Howells08e0e7c2007-04-26 15:55:03 -0700608 12 + ncallbacks * 6 * 4, 0);
609 if (!call)
610 return -ENOMEM;
611
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
613 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700614 bp = call->request;
615 tp = bp + 2 + ncallbacks * 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 *bp++ = htonl(FSGIVEUPCALLBACKS);
David Howells08e0e7c2007-04-26 15:55:03 -0700617 *bp++ = htonl(ncallbacks);
618 *tp++ = htonl(ncallbacks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
David Howells08e0e7c2007-04-26 15:55:03 -0700620 atomic_sub(ncallbacks, &server->cb_break_n);
621 for (loop = ncallbacks; loop > 0; loop--) {
622 struct afs_callback *cb =
623 &server->cb_break[server->cb_break_tail];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
David Howells08e0e7c2007-04-26 15:55:03 -0700625 *bp++ = htonl(cb->fid.vid);
626 *bp++ = htonl(cb->fid.vnode);
627 *bp++ = htonl(cb->fid.unique);
628 *tp++ = htonl(cb->version);
629 *tp++ = htonl(cb->expiry);
630 *tp++ = htonl(cb->type);
631 smp_mb();
632 server->cb_break_tail =
633 (server->cb_break_tail + 1) &
634 (ARRAY_SIZE(server->cb_break) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
636
David Howells08e0e7c2007-04-26 15:55:03 -0700637 ASSERT(ncallbacks > 0);
638 wake_up_nr(&server->cb_break_waitq, ncallbacks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
David Howells56ff9c82017-01-05 10:38:36 +0000640 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellsec268152007-04-26 15:49:28 -0700641}
David Howells260a9802007-04-26 15:59:35 -0700642
643/*
644 * deliver reply data to an FS.CreateFile or an FS.MakeDir
645 */
David Howellsd0016482016-08-30 20:42:14 +0100646static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700647{
David Howells97e30432017-11-02 15:27:48 +0000648 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700649 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100650 int ret;
David Howells260a9802007-04-26 15:59:35 -0700651
David Howellsd0016482016-08-30 20:42:14 +0100652 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700653
David Howellsd0016482016-08-30 20:42:14 +0100654 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100655 if (ret < 0)
656 return ret;
David Howells260a9802007-04-26 15:59:35 -0700657
658 /* unmarshall the reply once we've received all of it */
659 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000660 xdr_decode_AFSFid(&bp, call->reply[1]);
661 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700662 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000663 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
664 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700665
666 _leave(" = 0 [done]");
667 return 0;
668}
669
670/*
671 * FS.CreateFile and FS.MakeDir operation type
672 */
673static const struct afs_call_type afs_RXFSCreateXXXX = {
674 .name = "FS.CreateXXXX",
675 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700676 .destructor = afs_flat_call_destructor,
677};
678
679/*
680 * create a file or make a directory
681 */
682int afs_fs_create(struct afs_server *server,
683 struct key *key,
684 struct afs_vnode *vnode,
685 const char *name,
686 umode_t mode,
687 struct afs_fid *newfid,
688 struct afs_file_status *newstatus,
689 struct afs_callback *newcb,
David Howells56ff9c82017-01-05 10:38:36 +0000690 bool async)
David Howells260a9802007-04-26 15:59:35 -0700691{
692 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000693 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700694 size_t namesz, reqsz, padsz;
695 __be32 *bp;
696
697 _enter("");
698
699 namesz = strlen(name);
700 padsz = (4 - (namesz & 3)) & 3;
701 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
702
David Howellsf044c882017-11-02 15:27:45 +0000703 call = afs_alloc_flat_call(net, &afs_RXFSCreateXXXX, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700704 (3 + 21 + 21 + 3 + 6) * 4);
705 if (!call)
706 return -ENOMEM;
707
708 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000709 call->reply[0] = vnode;
710 call->reply[1] = newfid;
711 call->reply[2] = newstatus;
712 call->reply[3] = newcb;
David Howells260a9802007-04-26 15:59:35 -0700713
714 /* marshall the parameters */
715 bp = call->request;
716 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
717 *bp++ = htonl(vnode->fid.vid);
718 *bp++ = htonl(vnode->fid.vnode);
719 *bp++ = htonl(vnode->fid.unique);
720 *bp++ = htonl(namesz);
721 memcpy(bp, name, namesz);
722 bp = (void *) bp + namesz;
723 if (padsz > 0) {
724 memset(bp, 0, padsz);
725 bp = (void *) bp + padsz;
726 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000727 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
728 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700729 *bp++ = 0; /* owner */
730 *bp++ = 0; /* group */
731 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
732 *bp++ = 0; /* segment size */
733
David Howells56ff9c82017-01-05 10:38:36 +0000734 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells260a9802007-04-26 15:59:35 -0700735}
736
737/*
738 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
739 */
David Howellsd0016482016-08-30 20:42:14 +0100740static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700741{
David Howells97e30432017-11-02 15:27:48 +0000742 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700743 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100744 int ret;
David Howells260a9802007-04-26 15:59:35 -0700745
David Howellsd0016482016-08-30 20:42:14 +0100746 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700747
David Howellsd0016482016-08-30 20:42:14 +0100748 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100749 if (ret < 0)
750 return ret;
David Howells260a9802007-04-26 15:59:35 -0700751
752 /* unmarshall the reply once we've received all of it */
753 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700754 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000755 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700756
757 _leave(" = 0 [done]");
758 return 0;
759}
760
761/*
762 * FS.RemoveDir/FS.RemoveFile operation type
763 */
764static const struct afs_call_type afs_RXFSRemoveXXXX = {
765 .name = "FS.RemoveXXXX",
766 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700767 .destructor = afs_flat_call_destructor,
768};
769
770/*
771 * remove a file or directory
772 */
773int afs_fs_remove(struct afs_server *server,
774 struct key *key,
775 struct afs_vnode *vnode,
776 const char *name,
777 bool isdir,
David Howells56ff9c82017-01-05 10:38:36 +0000778 bool async)
David Howells260a9802007-04-26 15:59:35 -0700779{
780 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000781 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700782 size_t namesz, reqsz, padsz;
783 __be32 *bp;
784
785 _enter("");
786
787 namesz = strlen(name);
788 padsz = (4 - (namesz & 3)) & 3;
789 reqsz = (5 * 4) + namesz + padsz;
790
David Howellsf044c882017-11-02 15:27:45 +0000791 call = afs_alloc_flat_call(net, &afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700792 if (!call)
793 return -ENOMEM;
794
795 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000796 call->reply[0] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700797
798 /* marshall the parameters */
799 bp = call->request;
800 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
801 *bp++ = htonl(vnode->fid.vid);
802 *bp++ = htonl(vnode->fid.vnode);
803 *bp++ = htonl(vnode->fid.unique);
804 *bp++ = htonl(namesz);
805 memcpy(bp, name, namesz);
806 bp = (void *) bp + namesz;
807 if (padsz > 0) {
808 memset(bp, 0, padsz);
809 bp = (void *) bp + padsz;
810 }
811
David Howells56ff9c82017-01-05 10:38:36 +0000812 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells260a9802007-04-26 15:59:35 -0700813}
814
815/*
816 * deliver reply data to an FS.Link
817 */
David Howellsd0016482016-08-30 20:42:14 +0100818static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700819{
David Howells97e30432017-11-02 15:27:48 +0000820 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700821 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100822 int ret;
David Howells260a9802007-04-26 15:59:35 -0700823
David Howellsd0016482016-08-30 20:42:14 +0100824 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700825
David Howellsd0016482016-08-30 20:42:14 +0100826 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100827 if (ret < 0)
828 return ret;
David Howells260a9802007-04-26 15:59:35 -0700829
830 /* unmarshall the reply once we've received all of it */
831 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700832 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
833 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000834 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700835
836 _leave(" = 0 [done]");
837 return 0;
838}
839
840/*
841 * FS.Link operation type
842 */
843static const struct afs_call_type afs_RXFSLink = {
844 .name = "FS.Link",
845 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700846 .destructor = afs_flat_call_destructor,
847};
848
849/*
850 * make a hard link
851 */
852int afs_fs_link(struct afs_server *server,
853 struct key *key,
854 struct afs_vnode *dvnode,
855 struct afs_vnode *vnode,
856 const char *name,
David Howells56ff9c82017-01-05 10:38:36 +0000857 bool async)
David Howells260a9802007-04-26 15:59:35 -0700858{
859 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000860 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700861 size_t namesz, reqsz, padsz;
862 __be32 *bp;
863
864 _enter("");
865
866 namesz = strlen(name);
867 padsz = (4 - (namesz & 3)) & 3;
868 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
869
David Howellsf044c882017-11-02 15:27:45 +0000870 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700871 if (!call)
872 return -ENOMEM;
873
874 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000875 call->reply[0] = dvnode;
876 call->reply[1] = vnode;
David Howells260a9802007-04-26 15:59:35 -0700877
878 /* marshall the parameters */
879 bp = call->request;
880 *bp++ = htonl(FSLINK);
881 *bp++ = htonl(dvnode->fid.vid);
882 *bp++ = htonl(dvnode->fid.vnode);
883 *bp++ = htonl(dvnode->fid.unique);
884 *bp++ = htonl(namesz);
885 memcpy(bp, name, namesz);
886 bp = (void *) bp + namesz;
887 if (padsz > 0) {
888 memset(bp, 0, padsz);
889 bp = (void *) bp + padsz;
890 }
891 *bp++ = htonl(vnode->fid.vid);
892 *bp++ = htonl(vnode->fid.vnode);
893 *bp++ = htonl(vnode->fid.unique);
894
David Howells56ff9c82017-01-05 10:38:36 +0000895 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells260a9802007-04-26 15:59:35 -0700896}
897
898/*
899 * deliver reply data to an FS.Symlink
900 */
David Howellsd0016482016-08-30 20:42:14 +0100901static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700902{
David Howells97e30432017-11-02 15:27:48 +0000903 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700904 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100905 int ret;
David Howells260a9802007-04-26 15:59:35 -0700906
David Howellsd0016482016-08-30 20:42:14 +0100907 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700908
David Howellsd0016482016-08-30 20:42:14 +0100909 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100910 if (ret < 0)
911 return ret;
David Howells260a9802007-04-26 15:59:35 -0700912
913 /* unmarshall the reply once we've received all of it */
914 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000915 xdr_decode_AFSFid(&bp, call->reply[1]);
916 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
David Howells31143d52007-05-09 02:33:46 -0700917 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells97e30432017-11-02 15:27:48 +0000918 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700919
920 _leave(" = 0 [done]");
921 return 0;
922}
923
924/*
925 * FS.Symlink operation type
926 */
927static const struct afs_call_type afs_RXFSSymlink = {
928 .name = "FS.Symlink",
929 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -0700930 .destructor = afs_flat_call_destructor,
931};
932
933/*
934 * create a symbolic link
935 */
936int afs_fs_symlink(struct afs_server *server,
937 struct key *key,
938 struct afs_vnode *vnode,
939 const char *name,
940 const char *contents,
941 struct afs_fid *newfid,
942 struct afs_file_status *newstatus,
David Howells56ff9c82017-01-05 10:38:36 +0000943 bool async)
David Howells260a9802007-04-26 15:59:35 -0700944{
945 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000946 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700947 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
948 __be32 *bp;
949
950 _enter("");
951
952 namesz = strlen(name);
953 padsz = (4 - (namesz & 3)) & 3;
954
955 c_namesz = strlen(contents);
956 c_padsz = (4 - (c_namesz & 3)) & 3;
957
958 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
959
David Howellsf044c882017-11-02 15:27:45 +0000960 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -0700961 (3 + 21 + 21 + 6) * 4);
962 if (!call)
963 return -ENOMEM;
964
965 call->key = key;
David Howells97e30432017-11-02 15:27:48 +0000966 call->reply[0] = vnode;
967 call->reply[1] = newfid;
968 call->reply[2] = newstatus;
David Howells260a9802007-04-26 15:59:35 -0700969
970 /* marshall the parameters */
971 bp = call->request;
972 *bp++ = htonl(FSSYMLINK);
973 *bp++ = htonl(vnode->fid.vid);
974 *bp++ = htonl(vnode->fid.vnode);
975 *bp++ = htonl(vnode->fid.unique);
976 *bp++ = htonl(namesz);
977 memcpy(bp, name, namesz);
978 bp = (void *) bp + namesz;
979 if (padsz > 0) {
980 memset(bp, 0, padsz);
981 bp = (void *) bp + padsz;
982 }
983 *bp++ = htonl(c_namesz);
984 memcpy(bp, contents, c_namesz);
985 bp = (void *) bp + c_namesz;
986 if (c_padsz > 0) {
987 memset(bp, 0, c_padsz);
988 bp = (void *) bp + c_padsz;
989 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000990 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
991 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700992 *bp++ = 0; /* owner */
993 *bp++ = 0; /* group */
994 *bp++ = htonl(S_IRWXUGO); /* unix mode */
995 *bp++ = 0; /* segment size */
996
David Howells56ff9c82017-01-05 10:38:36 +0000997 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells260a9802007-04-26 15:59:35 -0700998}
999
1000/*
1001 * deliver reply data to an FS.Rename
1002 */
David Howellsd0016482016-08-30 20:42:14 +01001003static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001004{
David Howells97e30432017-11-02 15:27:48 +00001005 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -07001006 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001007 int ret;
David Howells260a9802007-04-26 15:59:35 -07001008
David Howellsd0016482016-08-30 20:42:14 +01001009 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001010
David Howellsd0016482016-08-30 20:42:14 +01001011 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001012 if (ret < 0)
1013 return ret;
David Howells260a9802007-04-26 15:59:35 -07001014
1015 /* unmarshall the reply once we've received all of it */
1016 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -07001017 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
David Howells260a9802007-04-26 15:59:35 -07001018 if (new_dvnode != orig_dvnode)
David Howells31143d52007-05-09 02:33:46 -07001019 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
1020 NULL);
David Howells97e30432017-11-02 15:27:48 +00001021 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001022
1023 _leave(" = 0 [done]");
1024 return 0;
1025}
1026
1027/*
1028 * FS.Rename operation type
1029 */
1030static const struct afs_call_type afs_RXFSRename = {
1031 .name = "FS.Rename",
1032 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001033 .destructor = afs_flat_call_destructor,
1034};
1035
1036/*
1037 * create a symbolic link
1038 */
1039int afs_fs_rename(struct afs_server *server,
1040 struct key *key,
1041 struct afs_vnode *orig_dvnode,
1042 const char *orig_name,
1043 struct afs_vnode *new_dvnode,
1044 const char *new_name,
David Howells56ff9c82017-01-05 10:38:36 +00001045 bool async)
David Howells260a9802007-04-26 15:59:35 -07001046{
1047 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001048 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001049 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1050 __be32 *bp;
1051
1052 _enter("");
1053
1054 o_namesz = strlen(orig_name);
1055 o_padsz = (4 - (o_namesz & 3)) & 3;
1056
1057 n_namesz = strlen(new_name);
1058 n_padsz = (4 - (n_namesz & 3)) & 3;
1059
1060 reqsz = (4 * 4) +
1061 4 + o_namesz + o_padsz +
1062 (3 * 4) +
1063 4 + n_namesz + n_padsz;
1064
David Howellsf044c882017-11-02 15:27:45 +00001065 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001066 if (!call)
1067 return -ENOMEM;
1068
1069 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001070 call->reply[0] = orig_dvnode;
1071 call->reply[1] = new_dvnode;
David Howells260a9802007-04-26 15:59:35 -07001072
1073 /* marshall the parameters */
1074 bp = call->request;
1075 *bp++ = htonl(FSRENAME);
1076 *bp++ = htonl(orig_dvnode->fid.vid);
1077 *bp++ = htonl(orig_dvnode->fid.vnode);
1078 *bp++ = htonl(orig_dvnode->fid.unique);
1079 *bp++ = htonl(o_namesz);
1080 memcpy(bp, orig_name, o_namesz);
1081 bp = (void *) bp + o_namesz;
1082 if (o_padsz > 0) {
1083 memset(bp, 0, o_padsz);
1084 bp = (void *) bp + o_padsz;
1085 }
1086
1087 *bp++ = htonl(new_dvnode->fid.vid);
1088 *bp++ = htonl(new_dvnode->fid.vnode);
1089 *bp++ = htonl(new_dvnode->fid.unique);
1090 *bp++ = htonl(n_namesz);
1091 memcpy(bp, new_name, n_namesz);
1092 bp = (void *) bp + n_namesz;
1093 if (n_padsz > 0) {
1094 memset(bp, 0, n_padsz);
1095 bp = (void *) bp + n_padsz;
1096 }
1097
David Howells56ff9c82017-01-05 10:38:36 +00001098 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells260a9802007-04-26 15:59:35 -07001099}
David Howells31143d52007-05-09 02:33:46 -07001100
1101/*
1102 * deliver reply data to an FS.StoreData
1103 */
David Howellsd0016482016-08-30 20:42:14 +01001104static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001105{
David Howells97e30432017-11-02 15:27:48 +00001106 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001107 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001108 int ret;
David Howells31143d52007-05-09 02:33:46 -07001109
David Howellsd0016482016-08-30 20:42:14 +01001110 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001111
David Howellsd0016482016-08-30 20:42:14 +01001112 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001113 if (ret < 0)
1114 return ret;
David Howells31143d52007-05-09 02:33:46 -07001115
1116 /* unmarshall the reply once we've received all of it */
1117 bp = call->buffer;
1118 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1119 &call->store_version);
David Howells97e30432017-11-02 15:27:48 +00001120 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001121
1122 afs_pages_written_back(vnode, call);
1123
1124 _leave(" = 0 [done]");
1125 return 0;
1126}
1127
1128/*
1129 * FS.StoreData operation type
1130 */
1131static const struct afs_call_type afs_RXFSStoreData = {
1132 .name = "FS.StoreData",
1133 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001134 .destructor = afs_flat_call_destructor,
1135};
1136
David Howellsb9b1f8d2007-05-10 03:15:21 -07001137static const struct afs_call_type afs_RXFSStoreData64 = {
1138 .name = "FS.StoreData64",
1139 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001140 .destructor = afs_flat_call_destructor,
1141};
1142
1143/*
1144 * store a set of pages to a very large file
1145 */
1146static int afs_fs_store_data64(struct afs_server *server,
1147 struct afs_writeback *wb,
1148 pgoff_t first, pgoff_t last,
1149 unsigned offset, unsigned to,
1150 loff_t size, loff_t pos, loff_t i_size,
David Howells56ff9c82017-01-05 10:38:36 +00001151 bool async)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001152{
1153 struct afs_vnode *vnode = wb->vnode;
1154 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001155 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001156 __be32 *bp;
1157
1158 _enter(",%x,{%x:%u},,",
1159 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1160
David Howellsf044c882017-11-02 15:27:45 +00001161 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001162 (4 + 6 + 3 * 2) * 4,
1163 (21 + 6) * 4);
1164 if (!call)
1165 return -ENOMEM;
1166
1167 call->wb = wb;
1168 call->key = wb->key;
David Howells97e30432017-11-02 15:27:48 +00001169 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001170 call->mapping = vnode->vfs_inode.i_mapping;
1171 call->first = first;
1172 call->last = last;
1173 call->first_offset = offset;
1174 call->last_to = to;
1175 call->send_pages = true;
1176 call->store_version = vnode->status.data_version + 1;
1177
1178 /* marshall the parameters */
1179 bp = call->request;
1180 *bp++ = htonl(FSSTOREDATA64);
1181 *bp++ = htonl(vnode->fid.vid);
1182 *bp++ = htonl(vnode->fid.vnode);
1183 *bp++ = htonl(vnode->fid.unique);
1184
Marc Dionneab94f5d2017-03-16 16:27:47 +00001185 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1186 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001187 *bp++ = 0; /* owner */
1188 *bp++ = 0; /* group */
1189 *bp++ = 0; /* unix mode */
1190 *bp++ = 0; /* segment size */
1191
1192 *bp++ = htonl(pos >> 32);
1193 *bp++ = htonl((u32) pos);
1194 *bp++ = htonl(size >> 32);
1195 *bp++ = htonl((u32) size);
1196 *bp++ = htonl(i_size >> 32);
1197 *bp++ = htonl((u32) i_size);
1198
David Howells56ff9c82017-01-05 10:38:36 +00001199 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001200}
1201
David Howells31143d52007-05-09 02:33:46 -07001202/*
1203 * store a set of pages
1204 */
1205int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
1206 pgoff_t first, pgoff_t last,
1207 unsigned offset, unsigned to,
David Howells56ff9c82017-01-05 10:38:36 +00001208 bool async)
David Howells31143d52007-05-09 02:33:46 -07001209{
1210 struct afs_vnode *vnode = wb->vnode;
1211 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001212 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001213 loff_t size, pos, i_size;
1214 __be32 *bp;
1215
1216 _enter(",%x,{%x:%u},,",
1217 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1218
David Howells146a1192017-03-16 16:27:47 +00001219 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001220 if (first != last)
1221 size += (loff_t)(last - first) << PAGE_SHIFT;
1222 pos = (loff_t)first << PAGE_SHIFT;
1223 pos += offset;
1224
1225 i_size = i_size_read(&vnode->vfs_inode);
1226 if (pos + size > i_size)
1227 i_size = size + pos;
1228
1229 _debug("size %llx, at %llx, i_size %llx",
1230 (unsigned long long) size, (unsigned long long) pos,
1231 (unsigned long long) i_size);
1232
David Howellsb9b1f8d2007-05-10 03:15:21 -07001233 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
1234 return afs_fs_store_data64(server, wb, first, last, offset, to,
David Howells56ff9c82017-01-05 10:38:36 +00001235 size, pos, i_size, async);
David Howells31143d52007-05-09 02:33:46 -07001236
David Howellsf044c882017-11-02 15:27:45 +00001237 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001238 (4 + 6 + 3) * 4,
1239 (21 + 6) * 4);
1240 if (!call)
1241 return -ENOMEM;
1242
1243 call->wb = wb;
1244 call->key = wb->key;
David Howells97e30432017-11-02 15:27:48 +00001245 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001246 call->mapping = vnode->vfs_inode.i_mapping;
1247 call->first = first;
1248 call->last = last;
1249 call->first_offset = offset;
1250 call->last_to = to;
1251 call->send_pages = true;
1252 call->store_version = vnode->status.data_version + 1;
1253
1254 /* marshall the parameters */
1255 bp = call->request;
1256 *bp++ = htonl(FSSTOREDATA);
1257 *bp++ = htonl(vnode->fid.vid);
1258 *bp++ = htonl(vnode->fid.vnode);
1259 *bp++ = htonl(vnode->fid.unique);
1260
Marc Dionneab94f5d2017-03-16 16:27:47 +00001261 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1262 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001263 *bp++ = 0; /* owner */
1264 *bp++ = 0; /* group */
1265 *bp++ = 0; /* unix mode */
1266 *bp++ = 0; /* segment size */
1267
1268 *bp++ = htonl(pos);
1269 *bp++ = htonl(size);
1270 *bp++ = htonl(i_size);
1271
David Howells56ff9c82017-01-05 10:38:36 +00001272 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells31143d52007-05-09 02:33:46 -07001273}
1274
1275/*
1276 * deliver reply data to an FS.StoreStatus
1277 */
David Howellsd0016482016-08-30 20:42:14 +01001278static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001279{
1280 afs_dataversion_t *store_version;
David Howells97e30432017-11-02 15:27:48 +00001281 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001282 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001283 int ret;
David Howells31143d52007-05-09 02:33:46 -07001284
David Howellsd0016482016-08-30 20:42:14 +01001285 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001286
David Howellsd0016482016-08-30 20:42:14 +01001287 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001288 if (ret < 0)
1289 return ret;
David Howells31143d52007-05-09 02:33:46 -07001290
1291 /* unmarshall the reply once we've received all of it */
1292 store_version = NULL;
1293 if (call->operation_ID == FSSTOREDATA)
1294 store_version = &call->store_version;
1295
1296 bp = call->buffer;
1297 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
David Howells97e30432017-11-02 15:27:48 +00001298 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001299
1300 _leave(" = 0 [done]");
1301 return 0;
1302}
1303
1304/*
1305 * FS.StoreStatus operation type
1306 */
1307static const struct afs_call_type afs_RXFSStoreStatus = {
1308 .name = "FS.StoreStatus",
1309 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001310 .destructor = afs_flat_call_destructor,
1311};
1312
1313static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1314 .name = "FS.StoreData",
1315 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001316 .destructor = afs_flat_call_destructor,
1317};
1318
David Howellsb9b1f8d2007-05-10 03:15:21 -07001319static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1320 .name = "FS.StoreData64",
1321 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001322 .destructor = afs_flat_call_destructor,
1323};
1324
1325/*
1326 * set the attributes on a very large file, using FS.StoreData rather than
1327 * FS.StoreStatus so as to alter the file size also
1328 */
1329static int afs_fs_setattr_size64(struct afs_server *server, struct key *key,
1330 struct afs_vnode *vnode, struct iattr *attr,
David Howells56ff9c82017-01-05 10:38:36 +00001331 bool async)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001332{
1333 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001334 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001335 __be32 *bp;
1336
1337 _enter(",%x,{%x:%u},,",
1338 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1339
1340 ASSERT(attr->ia_valid & ATTR_SIZE);
1341
David Howellsf044c882017-11-02 15:27:45 +00001342 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001343 (4 + 6 + 3 * 2) * 4,
1344 (21 + 6) * 4);
1345 if (!call)
1346 return -ENOMEM;
1347
1348 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001349 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001350 call->store_version = vnode->status.data_version + 1;
1351 call->operation_ID = FSSTOREDATA;
1352
1353 /* marshall the parameters */
1354 bp = call->request;
1355 *bp++ = htonl(FSSTOREDATA64);
1356 *bp++ = htonl(vnode->fid.vid);
1357 *bp++ = htonl(vnode->fid.vnode);
1358 *bp++ = htonl(vnode->fid.unique);
1359
1360 xdr_encode_AFS_StoreStatus(&bp, attr);
1361
1362 *bp++ = 0; /* position of start of write */
1363 *bp++ = 0;
1364 *bp++ = 0; /* size of write */
1365 *bp++ = 0;
1366 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1367 *bp++ = htonl((u32) attr->ia_size);
1368
David Howells56ff9c82017-01-05 10:38:36 +00001369 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001370}
1371
David Howells31143d52007-05-09 02:33:46 -07001372/*
1373 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1374 * so as to alter the file size also
1375 */
1376static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
1377 struct afs_vnode *vnode, struct iattr *attr,
David Howells56ff9c82017-01-05 10:38:36 +00001378 bool async)
David Howells31143d52007-05-09 02:33:46 -07001379{
1380 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001381 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001382 __be32 *bp;
1383
1384 _enter(",%x,{%x:%u},,",
1385 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1386
1387 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001388 if (attr->ia_size >> 32)
1389 return afs_fs_setattr_size64(server, key, vnode, attr,
David Howells56ff9c82017-01-05 10:38:36 +00001390 async);
David Howells31143d52007-05-09 02:33:46 -07001391
David Howellsf044c882017-11-02 15:27:45 +00001392 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001393 (4 + 6 + 3) * 4,
1394 (21 + 6) * 4);
1395 if (!call)
1396 return -ENOMEM;
1397
1398 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001399 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001400 call->store_version = vnode->status.data_version + 1;
1401 call->operation_ID = FSSTOREDATA;
1402
1403 /* marshall the parameters */
1404 bp = call->request;
1405 *bp++ = htonl(FSSTOREDATA);
1406 *bp++ = htonl(vnode->fid.vid);
1407 *bp++ = htonl(vnode->fid.vnode);
1408 *bp++ = htonl(vnode->fid.unique);
1409
1410 xdr_encode_AFS_StoreStatus(&bp, attr);
1411
1412 *bp++ = 0; /* position of start of write */
1413 *bp++ = 0; /* size of write */
1414 *bp++ = htonl(attr->ia_size); /* new file length */
1415
David Howells56ff9c82017-01-05 10:38:36 +00001416 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells31143d52007-05-09 02:33:46 -07001417}
1418
1419/*
1420 * set the attributes on a file, using FS.StoreData if there's a change in file
1421 * size, and FS.StoreStatus otherwise
1422 */
1423int afs_fs_setattr(struct afs_server *server, struct key *key,
1424 struct afs_vnode *vnode, struct iattr *attr,
David Howells56ff9c82017-01-05 10:38:36 +00001425 bool async)
David Howells31143d52007-05-09 02:33:46 -07001426{
1427 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001428 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001429 __be32 *bp;
1430
1431 if (attr->ia_valid & ATTR_SIZE)
1432 return afs_fs_setattr_size(server, key, vnode, attr,
David Howells56ff9c82017-01-05 10:38:36 +00001433 async);
David Howells31143d52007-05-09 02:33:46 -07001434
1435 _enter(",%x,{%x:%u},,",
1436 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1437
David Howellsf044c882017-11-02 15:27:45 +00001438 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001439 (4 + 6) * 4,
1440 (21 + 6) * 4);
1441 if (!call)
1442 return -ENOMEM;
1443
1444 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001445 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001446 call->operation_ID = FSSTORESTATUS;
1447
1448 /* marshall the parameters */
1449 bp = call->request;
1450 *bp++ = htonl(FSSTORESTATUS);
1451 *bp++ = htonl(vnode->fid.vid);
1452 *bp++ = htonl(vnode->fid.vnode);
1453 *bp++ = htonl(vnode->fid.unique);
1454
1455 xdr_encode_AFS_StoreStatus(&bp, attr);
1456
David Howells56ff9c82017-01-05 10:38:36 +00001457 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells31143d52007-05-09 02:33:46 -07001458}
David Howells45222b92007-05-10 22:22:20 -07001459
1460/*
1461 * deliver reply data to an FS.GetVolumeStatus
1462 */
David Howellsd0016482016-08-30 20:42:14 +01001463static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001464{
1465 const __be32 *bp;
1466 char *p;
1467 int ret;
1468
David Howellsd0016482016-08-30 20:42:14 +01001469 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001470
1471 switch (call->unmarshall) {
1472 case 0:
1473 call->offset = 0;
1474 call->unmarshall++;
1475
1476 /* extract the returned status record */
1477 case 1:
1478 _debug("extract status");
David Howellsd0016482016-08-30 20:42:14 +01001479 ret = afs_extract_data(call, call->buffer,
1480 12 * 4, true);
David Howells372ee162016-08-03 14:11:40 +01001481 if (ret < 0)
1482 return ret;
David Howells45222b92007-05-10 22:22:20 -07001483
1484 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001485 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001486 call->offset = 0;
1487 call->unmarshall++;
1488
1489 /* extract the volume name length */
1490 case 2:
David Howellsd0016482016-08-30 20:42:14 +01001491 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001492 if (ret < 0)
1493 return ret;
David Howells45222b92007-05-10 22:22:20 -07001494
1495 call->count = ntohl(call->tmp);
1496 _debug("volname length: %u", call->count);
1497 if (call->count >= AFSNAMEMAX)
1498 return -EBADMSG;
1499 call->offset = 0;
1500 call->unmarshall++;
1501
1502 /* extract the volume name */
1503 case 3:
1504 _debug("extract volname");
1505 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001506 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001507 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001508 if (ret < 0)
1509 return ret;
David Howells45222b92007-05-10 22:22:20 -07001510 }
1511
David Howells97e30432017-11-02 15:27:48 +00001512 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001513 p[call->count] = 0;
1514 _debug("volname '%s'", p);
1515
1516 call->offset = 0;
1517 call->unmarshall++;
1518
1519 /* extract the volume name padding */
1520 if ((call->count & 3) == 0) {
1521 call->unmarshall++;
1522 goto no_volname_padding;
1523 }
1524 call->count = 4 - (call->count & 3);
1525
1526 case 4:
David Howellsd0016482016-08-30 20:42:14 +01001527 ret = afs_extract_data(call, call->buffer,
1528 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001529 if (ret < 0)
1530 return ret;
David Howells45222b92007-05-10 22:22:20 -07001531
1532 call->offset = 0;
1533 call->unmarshall++;
1534 no_volname_padding:
1535
1536 /* extract the offline message length */
1537 case 5:
David Howellsd0016482016-08-30 20:42:14 +01001538 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001539 if (ret < 0)
1540 return ret;
David Howells45222b92007-05-10 22:22:20 -07001541
1542 call->count = ntohl(call->tmp);
1543 _debug("offline msg length: %u", call->count);
1544 if (call->count >= AFSNAMEMAX)
1545 return -EBADMSG;
1546 call->offset = 0;
1547 call->unmarshall++;
1548
1549 /* extract the offline message */
1550 case 6:
1551 _debug("extract offline");
1552 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001553 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001554 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001555 if (ret < 0)
1556 return ret;
David Howells45222b92007-05-10 22:22:20 -07001557 }
1558
David Howells97e30432017-11-02 15:27:48 +00001559 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001560 p[call->count] = 0;
1561 _debug("offline '%s'", p);
1562
1563 call->offset = 0;
1564 call->unmarshall++;
1565
1566 /* extract the offline message padding */
1567 if ((call->count & 3) == 0) {
1568 call->unmarshall++;
1569 goto no_offline_padding;
1570 }
1571 call->count = 4 - (call->count & 3);
1572
1573 case 7:
David Howellsd0016482016-08-30 20:42:14 +01001574 ret = afs_extract_data(call, call->buffer,
1575 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001576 if (ret < 0)
1577 return ret;
David Howells45222b92007-05-10 22:22:20 -07001578
1579 call->offset = 0;
1580 call->unmarshall++;
1581 no_offline_padding:
1582
1583 /* extract the message of the day length */
1584 case 8:
David Howellsd0016482016-08-30 20:42:14 +01001585 ret = afs_extract_data(call, &call->tmp, 4, true);
David Howells372ee162016-08-03 14:11:40 +01001586 if (ret < 0)
1587 return ret;
David Howells45222b92007-05-10 22:22:20 -07001588
1589 call->count = ntohl(call->tmp);
1590 _debug("motd length: %u", call->count);
1591 if (call->count >= AFSNAMEMAX)
1592 return -EBADMSG;
1593 call->offset = 0;
1594 call->unmarshall++;
1595
1596 /* extract the message of the day */
1597 case 9:
1598 _debug("extract motd");
1599 if (call->count > 0) {
David Howells97e30432017-11-02 15:27:48 +00001600 ret = afs_extract_data(call, call->reply[2],
David Howellsd0016482016-08-30 20:42:14 +01001601 call->count, true);
David Howells372ee162016-08-03 14:11:40 +01001602 if (ret < 0)
1603 return ret;
David Howells45222b92007-05-10 22:22:20 -07001604 }
1605
David Howells97e30432017-11-02 15:27:48 +00001606 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001607 p[call->count] = 0;
1608 _debug("motd '%s'", p);
1609
1610 call->offset = 0;
1611 call->unmarshall++;
1612
1613 /* extract the message of the day padding */
David Howellsd0016482016-08-30 20:42:14 +01001614 call->count = (4 - (call->count & 3)) & 3;
David Howells45222b92007-05-10 22:22:20 -07001615
1616 case 10:
David Howellsd0016482016-08-30 20:42:14 +01001617 ret = afs_extract_data(call, call->buffer,
1618 call->count, false);
David Howells372ee162016-08-03 14:11:40 +01001619 if (ret < 0)
1620 return ret;
David Howells45222b92007-05-10 22:22:20 -07001621
1622 call->offset = 0;
1623 call->unmarshall++;
David Howells45222b92007-05-10 22:22:20 -07001624 case 11:
David Howells45222b92007-05-10 22:22:20 -07001625 break;
1626 }
1627
David Howells45222b92007-05-10 22:22:20 -07001628 _leave(" = 0 [done]");
1629 return 0;
1630}
1631
1632/*
1633 * destroy an FS.GetVolumeStatus call
1634 */
1635static void afs_get_volume_status_call_destructor(struct afs_call *call)
1636{
David Howells97e30432017-11-02 15:27:48 +00001637 kfree(call->reply[2]);
1638 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001639 afs_flat_call_destructor(call);
1640}
1641
1642/*
1643 * FS.GetVolumeStatus operation type
1644 */
1645static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1646 .name = "FS.GetVolumeStatus",
1647 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001648 .destructor = afs_get_volume_status_call_destructor,
1649};
1650
1651/*
1652 * fetch the status of a volume
1653 */
1654int afs_fs_get_volume_status(struct afs_server *server,
1655 struct key *key,
1656 struct afs_vnode *vnode,
1657 struct afs_volume_status *vs,
David Howells56ff9c82017-01-05 10:38:36 +00001658 bool async)
David Howells45222b92007-05-10 22:22:20 -07001659{
1660 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001661 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001662 __be32 *bp;
1663 void *tmpbuf;
1664
1665 _enter("");
1666
1667 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1668 if (!tmpbuf)
1669 return -ENOMEM;
1670
David Howellsf044c882017-11-02 15:27:45 +00001671 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001672 if (!call) {
1673 kfree(tmpbuf);
1674 return -ENOMEM;
1675 }
1676
1677 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001678 call->reply[0] = vnode;
1679 call->reply[1] = vs;
1680 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001681
1682 /* marshall the parameters */
1683 bp = call->request;
1684 bp[0] = htonl(FSGETVOLUMESTATUS);
1685 bp[1] = htonl(vnode->fid.vid);
1686
David Howells56ff9c82017-01-05 10:38:36 +00001687 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howells45222b92007-05-10 22:22:20 -07001688}
David Howellse8d6c552007-07-15 23:40:12 -07001689
1690/*
1691 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1692 */
David Howellsd0016482016-08-30 20:42:14 +01001693static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001694{
1695 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001696 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001697
David Howellsd0016482016-08-30 20:42:14 +01001698 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001699
David Howellsd0016482016-08-30 20:42:14 +01001700 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001701 if (ret < 0)
1702 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001703
1704 /* unmarshall the reply once we've received all of it */
1705 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001706 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001707
1708 _leave(" = 0 [done]");
1709 return 0;
1710}
1711
1712/*
1713 * FS.SetLock operation type
1714 */
1715static const struct afs_call_type afs_RXFSSetLock = {
1716 .name = "FS.SetLock",
1717 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001718 .destructor = afs_flat_call_destructor,
1719};
1720
1721/*
1722 * FS.ExtendLock operation type
1723 */
1724static const struct afs_call_type afs_RXFSExtendLock = {
1725 .name = "FS.ExtendLock",
1726 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001727 .destructor = afs_flat_call_destructor,
1728};
1729
1730/*
1731 * FS.ReleaseLock operation type
1732 */
1733static const struct afs_call_type afs_RXFSReleaseLock = {
1734 .name = "FS.ReleaseLock",
1735 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001736 .destructor = afs_flat_call_destructor,
1737};
1738
1739/*
1740 * get a lock on a file
1741 */
1742int afs_fs_set_lock(struct afs_server *server,
1743 struct key *key,
1744 struct afs_vnode *vnode,
1745 afs_lock_type_t type,
David Howells56ff9c82017-01-05 10:38:36 +00001746 bool async)
David Howellse8d6c552007-07-15 23:40:12 -07001747{
1748 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001749 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001750 __be32 *bp;
1751
1752 _enter("");
1753
David Howellsf044c882017-11-02 15:27:45 +00001754 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001755 if (!call)
1756 return -ENOMEM;
1757
1758 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001759 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001760
1761 /* marshall the parameters */
1762 bp = call->request;
1763 *bp++ = htonl(FSSETLOCK);
1764 *bp++ = htonl(vnode->fid.vid);
1765 *bp++ = htonl(vnode->fid.vnode);
1766 *bp++ = htonl(vnode->fid.unique);
1767 *bp++ = htonl(type);
1768
David Howells56ff9c82017-01-05 10:38:36 +00001769 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellse8d6c552007-07-15 23:40:12 -07001770}
1771
1772/*
1773 * extend a lock on a file
1774 */
1775int afs_fs_extend_lock(struct afs_server *server,
1776 struct key *key,
1777 struct afs_vnode *vnode,
David Howells56ff9c82017-01-05 10:38:36 +00001778 bool async)
David Howellse8d6c552007-07-15 23:40:12 -07001779{
1780 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001781 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001782 __be32 *bp;
1783
1784 _enter("");
1785
David Howellsf044c882017-11-02 15:27:45 +00001786 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001787 if (!call)
1788 return -ENOMEM;
1789
1790 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001791 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001792
1793 /* marshall the parameters */
1794 bp = call->request;
1795 *bp++ = htonl(FSEXTENDLOCK);
1796 *bp++ = htonl(vnode->fid.vid);
1797 *bp++ = htonl(vnode->fid.vnode);
1798 *bp++ = htonl(vnode->fid.unique);
1799
David Howells56ff9c82017-01-05 10:38:36 +00001800 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellse8d6c552007-07-15 23:40:12 -07001801}
1802
1803/*
1804 * release a lock on a file
1805 */
1806int afs_fs_release_lock(struct afs_server *server,
1807 struct key *key,
1808 struct afs_vnode *vnode,
David Howells56ff9c82017-01-05 10:38:36 +00001809 bool async)
David Howellse8d6c552007-07-15 23:40:12 -07001810{
1811 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001812 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001813 __be32 *bp;
1814
1815 _enter("");
1816
David Howellsf044c882017-11-02 15:27:45 +00001817 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001818 if (!call)
1819 return -ENOMEM;
1820
1821 call->key = key;
David Howells97e30432017-11-02 15:27:48 +00001822 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001823
1824 /* marshall the parameters */
1825 bp = call->request;
1826 *bp++ = htonl(FSRELEASELOCK);
1827 *bp++ = htonl(vnode->fid.vid);
1828 *bp++ = htonl(vnode->fid.vnode);
1829 *bp++ = htonl(vnode->fid.unique);
1830
David Howells56ff9c82017-01-05 10:38:36 +00001831 return afs_make_call(&server->addr, call, GFP_NOFS, async);
David Howellse8d6c552007-07-15 23:40:12 -07001832}