blob: 6105cdb1716326a2a5a5907e1dc85530a6b7a66e [file] [log] [blame]
David Howells08e0e7c2007-04-26 15:55:03 -07001/* AFS File Server client stubs
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
David Howells08e0e7c2007-04-26 15:55:03 -07003 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/sched.h>
David Howells08e0e7c2007-04-26 15:55:03 -070015#include <linux/circ_buf.h>
Jeff Laytona01179e2017-12-11 06:35:11 -050016#include <linux/iversion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070018#include "afs_fs.h"
David Howellsdd9fbcb2018-04-06 14:17:24 +010019#include "xdr_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
David Howells025db802017-11-02 15:27:51 +000021static const struct afs_fid afs_zero_fid;
22
David Howellsd2ddc772017-11-02 15:27:50 +000023static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
David Howellsc435ee32017-11-02 15:27:49 +000024{
David Howellsd2ddc772017-11-02 15:27:50 +000025 call->cbi = afs_get_cb_interest(cbi);
David Howellsc435ee32017-11-02 15:27:49 +000026}
27
David Howells6db3ac32017-03-16 16:27:44 +000028/*
David Howells260a9802007-04-26 15:59:35 -070029 * decode an AFSFid block
30 */
31static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
32{
33 const __be32 *bp = *_bp;
34
35 fid->vid = ntohl(*bp++);
36 fid->vnode = ntohl(*bp++);
37 fid->unique = ntohl(*bp++);
38 *_bp = bp;
39}
40
41/*
David Howells888b3382018-04-06 14:17:24 +010042 * Dump a bad file status record.
43 */
44static void xdr_dump_bad(const __be32 *bp)
45{
46 __be32 x[4];
47 int i;
48
49 pr_notice("AFS XDR: Bad status record\n");
50 for (i = 0; i < 5 * 4 * 4; i += 16) {
51 memcpy(x, bp, 16);
52 bp += 4;
53 pr_notice("%03x: %08x %08x %08x %08x\n",
54 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
55 }
56
57 memcpy(x, bp, 4);
58 pr_notice("0x50: %08x\n", ntohl(x[0]));
59}
60
61/*
David Howellsdd9fbcb2018-04-06 14:17:24 +010062 * Update the core inode struct from a returned status record.
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 */
David Howellsdd9fbcb2018-04-06 14:17:24 +010064void afs_update_inode_from_status(struct afs_vnode *vnode,
65 struct afs_file_status *status,
66 const afs_dataversion_t *expected_version,
67 u8 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -070068{
Deepa Dinamani95582b02018-05-08 19:36:02 -070069 struct timespec64 t;
David Howells08e0e7c2007-04-26 15:55:03 -070070 umode_t mode;
David Howells08e0e7c2007-04-26 15:55:03 -070071
David Howellsdd9fbcb2018-04-06 14:17:24 +010072 t.tv_sec = status->mtime_client;
73 t.tv_nsec = 0;
74 vnode->vfs_inode.i_ctime = t;
75 vnode->vfs_inode.i_mtime = t;
76 vnode->vfs_inode.i_atime = t;
David Howellsc435ee32017-11-02 15:27:49 +000077
David Howellsdd9fbcb2018-04-06 14:17:24 +010078 if (flags & (AFS_VNODE_META_CHANGED | AFS_VNODE_NOT_YET_SET)) {
79 vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner);
80 vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group);
81 set_nlink(&vnode->vfs_inode, status->nlink);
David Howells08e0e7c2007-04-26 15:55:03 -070082
David Howellsdd9fbcb2018-04-06 14:17:24 +010083 mode = vnode->vfs_inode.i_mode;
84 mode &= ~S_IALLUGO;
85 mode |= status->mode;
86 barrier();
87 vnode->vfs_inode.i_mode = mode;
David Howells888b3382018-04-06 14:17:24 +010088 }
89
David Howellsdd9fbcb2018-04-06 14:17:24 +010090 if (!(flags & AFS_VNODE_NOT_YET_SET)) {
91 if (expected_version &&
92 *expected_version != status->data_version) {
David Howells3b6492d2018-10-20 00:57:57 +010093 _debug("vnode modified %llx on {%llx:%llu} [exp %llx]",
David Howellsdd9fbcb2018-04-06 14:17:24 +010094 (unsigned long long) status->data_version,
95 vnode->fid.vid, vnode->fid.vnode,
96 (unsigned long long) *expected_version);
David Howellsa4ff7402018-04-06 14:17:24 +010097 vnode->invalid_before = status->data_version;
David Howellsf3ddee82018-04-06 14:17:25 +010098 if (vnode->status.type == AFS_FTYPE_DIR) {
99 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
100 afs_stat_v(vnode, n_inval);
101 } else {
102 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
103 }
David Howells63a46812018-04-06 14:17:25 +0100104 } else if (vnode->status.type == AFS_FTYPE_DIR) {
105 /* Expected directory change is handled elsewhere so
106 * that we can locally edit the directory and save on a
107 * download.
108 */
109 if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
110 flags &= ~AFS_VNODE_DATA_CHANGED;
David Howells260a9802007-04-26 15:59:35 -0700111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 }
David Howellsc435ee32017-11-02 15:27:49 +0000113
David Howellsdd9fbcb2018-04-06 14:17:24 +0100114 if (flags & (AFS_VNODE_DATA_CHANGED | AFS_VNODE_NOT_YET_SET)) {
115 inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
116 i_size_write(&vnode->vfs_inode, status->size);
117 }
118}
119
120/*
121 * decode an AFSFetchStatus block
122 */
David Howells5f702c82018-04-06 14:17:25 +0100123static int xdr_decode_AFSFetchStatus(struct afs_call *call,
124 const __be32 **_bp,
David Howellsdd9fbcb2018-04-06 14:17:24 +0100125 struct afs_file_status *status,
126 struct afs_vnode *vnode,
127 const afs_dataversion_t *expected_version,
David Howellsf3ddee82018-04-06 14:17:25 +0100128 struct afs_read *read_req)
David Howellsdd9fbcb2018-04-06 14:17:24 +0100129{
130 const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
David Howells684b0f62018-05-10 21:51:47 +0100131 bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
David Howellsdd9fbcb2018-04-06 14:17:24 +0100132 u64 data_version, size;
133 u32 type, abort_code;
134 u8 flags = 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100135
David Howells684b0f62018-05-10 21:51:47 +0100136 abort_code = ntohl(xdr->abort_code);
137
David Howellsdd9fbcb2018-04-06 14:17:24 +0100138 if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
David Howells684b0f62018-05-10 21:51:47 +0100139 if (xdr->if_version == htonl(0) &&
140 abort_code != 0 &&
141 inline_error) {
142 /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
143 * whereby it doesn't set the interface version in the error
144 * case.
145 */
146 status->abort_code = abort_code;
Al Virode52cf92018-06-02 18:08:11 -0400147 return 0;
David Howells684b0f62018-05-10 21:51:47 +0100148 }
149
David Howellsdd9fbcb2018-04-06 14:17:24 +0100150 pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
151 goto bad;
152 }
153
David Howells684b0f62018-05-10 21:51:47 +0100154 if (abort_code != 0 && inline_error) {
155 status->abort_code = abort_code;
Al Virode52cf92018-06-02 18:08:11 -0400156 return 0;
David Howells684b0f62018-05-10 21:51:47 +0100157 }
158
David Howellsdd9fbcb2018-04-06 14:17:24 +0100159 type = ntohl(xdr->type);
David Howellsdd9fbcb2018-04-06 14:17:24 +0100160 switch (type) {
161 case AFS_FTYPE_FILE:
162 case AFS_FTYPE_DIR:
163 case AFS_FTYPE_SYMLINK:
164 if (type != status->type &&
165 vnode &&
166 !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
David Howells3b6492d2018-10-20 00:57:57 +0100167 pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n",
David Howellsdd9fbcb2018-04-06 14:17:24 +0100168 vnode->fid.vid,
169 vnode->fid.vnode,
170 vnode->fid.unique,
171 status->type, type);
172 goto bad;
173 }
174 status->type = type;
175 break;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100176 default:
177 goto bad;
178 }
179
180#define EXTRACT_M(FIELD) \
181 do { \
182 u32 x = ntohl(xdr->FIELD); \
183 if (status->FIELD != x) { \
184 flags |= AFS_VNODE_META_CHANGED; \
185 status->FIELD = x; \
186 } \
187 } while (0)
188
189 EXTRACT_M(nlink);
190 EXTRACT_M(author);
191 EXTRACT_M(owner);
192 EXTRACT_M(caller_access); /* call ticket dependent */
193 EXTRACT_M(anon_access);
194 EXTRACT_M(mode);
195 EXTRACT_M(group);
196
197 status->mtime_client = ntohl(xdr->mtime_client);
198 status->mtime_server = ntohl(xdr->mtime_server);
199 status->lock_count = ntohl(xdr->lock_count);
200
201 size = (u64)ntohl(xdr->size_lo);
202 size |= (u64)ntohl(xdr->size_hi) << 32;
David Howells63a46812018-04-06 14:17:25 +0100203 status->size = size;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100204
205 data_version = (u64)ntohl(xdr->data_version_lo);
206 data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
207 if (data_version != status->data_version) {
208 status->data_version = data_version;
209 flags |= AFS_VNODE_DATA_CHANGED;
210 }
David Howellsf3ddee82018-04-06 14:17:25 +0100211
212 if (read_req) {
213 read_req->data_version = data_version;
214 read_req->file_size = size;
215 }
David Howellsdd9fbcb2018-04-06 14:17:24 +0100216
217 *_bp = (const void *)*_bp + sizeof(*xdr);
218
219 if (vnode) {
220 if (test_bit(AFS_VNODE_UNSET, &vnode->flags))
221 flags |= AFS_VNODE_NOT_YET_SET;
222 afs_update_inode_from_status(vnode, status, expected_version,
223 flags);
224 }
225
David Howellsc875c762018-05-23 11:32:06 +0100226 return 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100227
228bad:
229 xdr_dump_bad(*_bp);
David Howells160cb952018-10-20 00:57:56 +0100230 return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
David Howellsc875c762018-05-23 11:32:06 +0100231}
232
233/*
234 * Decode the file status. We need to lock the target vnode if we're going to
235 * update its status so that stat() sees the attributes update atomically.
236 */
237static int afs_decode_status(struct afs_call *call,
238 const __be32 **_bp,
239 struct afs_file_status *status,
240 struct afs_vnode *vnode,
241 const afs_dataversion_t *expected_version,
242 struct afs_read *read_req)
243{
244 int ret;
245
246 if (!vnode)
247 return xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
248 expected_version, read_req);
249
250 write_seqlock(&vnode->cb_lock);
251 ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
252 expected_version, read_req);
253 write_sequnlock(&vnode->cb_lock);
254 return ret;
David Howellsec268152007-04-26 15:49:28 -0700255}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257/*
David Howells08e0e7c2007-04-26 15:55:03 -0700258 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 */
David Howellsc435ee32017-11-02 15:27:49 +0000260static void xdr_decode_AFSCallBack(struct afs_call *call,
261 struct afs_vnode *vnode,
262 const __be32 **_bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263{
David Howellsd2ddc772017-11-02 15:27:50 +0000264 struct afs_cb_interest *old, *cbi = call->cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700265 const __be32 *bp = *_bp;
David Howellsc435ee32017-11-02 15:27:49 +0000266 u32 cb_expiry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
David Howellsc435ee32017-11-02 15:27:49 +0000268 write_seqlock(&vnode->cb_lock);
269
David Howells68251f02018-05-12 22:31:33 +0100270 if (call->cb_break == afs_cb_break_sum(vnode, cbi)) {
David Howellsc435ee32017-11-02 15:27:49 +0000271 vnode->cb_version = ntohl(*bp++);
272 cb_expiry = ntohl(*bp++);
273 vnode->cb_type = ntohl(*bp++);
274 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
David Howellsd2ddc772017-11-02 15:27:50 +0000275 old = vnode->cb_interest;
276 if (old != call->cbi) {
277 vnode->cb_interest = cbi;
278 cbi = old;
279 }
David Howellsc435ee32017-11-02 15:27:49 +0000280 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
281 } else {
282 bp += 3;
283 }
284
285 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +0000286 call->cbi = cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700287 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700288}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
David Howells12d8e952018-10-20 00:57:58 +0100290static ktime_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
291{
292 return ktime_add_ns(call->reply_time, expiry * NSEC_PER_SEC);
293}
294
295static void xdr_decode_AFSCallBack_raw(struct afs_call *call,
296 const __be32 **_bp,
David Howells260a9802007-04-26 15:59:35 -0700297 struct afs_callback *cb)
298{
299 const __be32 *bp = *_bp;
300
301 cb->version = ntohl(*bp++);
David Howells12d8e952018-10-20 00:57:58 +0100302 cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++));
David Howells260a9802007-04-26 15:59:35 -0700303 cb->type = ntohl(*bp++);
304 *_bp = bp;
305}
306
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307/*
David Howells08e0e7c2007-04-26 15:55:03 -0700308 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 */
David Howells08e0e7c2007-04-26 15:55:03 -0700310static void xdr_decode_AFSVolSync(const __be32 **_bp,
311 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312{
David Howells08e0e7c2007-04-26 15:55:03 -0700313 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
David Howells08e0e7c2007-04-26 15:55:03 -0700315 volsync->creation = ntohl(*bp++);
316 bp++; /* spare2 */
317 bp++; /* spare3 */
318 bp++; /* spare4 */
319 bp++; /* spare5 */
320 bp++; /* spare6 */
321 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700322}
David Howells08e0e7c2007-04-26 15:55:03 -0700323
324/*
David Howells31143d52007-05-09 02:33:46 -0700325 * encode the requested attributes into an AFSStoreStatus block
326 */
327static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
328{
329 __be32 *bp = *_bp;
330 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
331
332 mask = 0;
333 if (attr->ia_valid & ATTR_MTIME) {
334 mask |= AFS_SET_MTIME;
335 mtime = attr->ia_mtime.tv_sec;
336 }
337
338 if (attr->ia_valid & ATTR_UID) {
339 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800340 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700341 }
342
343 if (attr->ia_valid & ATTR_GID) {
344 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800345 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700346 }
347
348 if (attr->ia_valid & ATTR_MODE) {
349 mask |= AFS_SET_MODE;
350 mode = attr->ia_mode & S_IALLUGO;
351 }
352
353 *bp++ = htonl(mask);
354 *bp++ = htonl(mtime);
355 *bp++ = htonl(owner);
356 *bp++ = htonl(group);
357 *bp++ = htonl(mode);
358 *bp++ = 0; /* segment size */
359 *_bp = bp;
360}
361
362/*
David Howells45222b92007-05-10 22:22:20 -0700363 * decode an AFSFetchVolumeStatus block
364 */
365static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
366 struct afs_volume_status *vs)
367{
368 const __be32 *bp = *_bp;
369
370 vs->vid = ntohl(*bp++);
371 vs->parent_id = ntohl(*bp++);
372 vs->online = ntohl(*bp++);
373 vs->in_service = ntohl(*bp++);
374 vs->blessed = ntohl(*bp++);
375 vs->needs_salvage = ntohl(*bp++);
376 vs->type = ntohl(*bp++);
377 vs->min_quota = ntohl(*bp++);
378 vs->max_quota = ntohl(*bp++);
379 vs->blocks_in_use = ntohl(*bp++);
380 vs->part_blocks_avail = ntohl(*bp++);
381 vs->part_max_blocks = ntohl(*bp++);
382 *_bp = bp;
383}
384
385/*
David Howells08e0e7c2007-04-26 15:55:03 -0700386 * deliver reply data to an FS.FetchStatus
387 */
David Howells5cf9dd52018-04-09 21:12:31 +0100388static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700389{
David Howells97e30432017-11-02 15:27:48 +0000390 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700391 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100392 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700393
David Howellsd0016482016-08-30 20:42:14 +0100394 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100395 if (ret < 0)
396 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700397
David Howells3b6492d2018-10-20 00:57:57 +0100398 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
David Howellsc435ee32017-11-02 15:27:49 +0000399
David Howells08e0e7c2007-04-26 15:55:03 -0700400 /* unmarshall the reply once we've received all of it */
401 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100402 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
403 &call->expected_version, NULL);
404 if (ret < 0)
405 return ret;
David Howellsc435ee32017-11-02 15:27:49 +0000406 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000407 if (call->reply[1])
408 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700409
410 _leave(" = 0 [done]");
411 return 0;
412}
413
414/*
415 * FS.FetchStatus operation type
416 */
David Howells5cf9dd52018-04-09 21:12:31 +0100417static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
418 .name = "FS.FetchStatus(vnode)",
David Howells025db802017-11-02 15:27:51 +0000419 .op = afs_FS_FetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100420 .deliver = afs_deliver_fs_fetch_status_vnode,
David Howells08e0e7c2007-04-26 15:55:03 -0700421 .destructor = afs_flat_call_destructor,
422};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424/*
425 * fetch the status information for a file
426 */
David Howells0c3a5ac2018-04-06 14:17:24 +0100427int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync,
428 bool new_inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429{
David Howellsd2ddc772017-11-02 15:27:50 +0000430 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700431 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000432 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 __be32 *bp;
434
David Howells3b6492d2018-10-20 00:57:57 +0100435 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000436 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
David Howells5cf9dd52018-04-09 21:12:31 +0100438 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
439 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000440 if (!call) {
441 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700442 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
David Howellsd2ddc772017-11-02 15:27:50 +0000445 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000446 call->reply[0] = vnode;
447 call->reply[1] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +0100448 call->expected_version = new_inode ? 1 : vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100449 call->want_reply_time = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
451 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700452 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 bp[0] = htonl(FSFETCHSTATUS);
454 bp[1] = htonl(vnode->fid.vid);
455 bp[2] = htonl(vnode->fid.vnode);
456 bp[3] = htonl(vnode->fid.unique);
457
David Howellsd2ddc772017-11-02 15:27:50 +0000458 call->cb_break = fc->cb_break;
459 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000460 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000461 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700462}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464/*
David Howells08e0e7c2007-04-26 15:55:03 -0700465 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 */
David Howellsd0016482016-08-30 20:42:14 +0100467static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
David Howells97e30432017-11-02 15:27:48 +0000469 struct afs_vnode *vnode = call->reply[0];
470 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700471 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000472 unsigned int size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700474
David Howells12bdcf32018-10-20 00:57:56 +0100475 _enter("{%u,%zu/%llu}",
476 call->unmarshall, iov_iter_count(&call->iter), req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700477
478 switch (call->unmarshall) {
479 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000480 req->actual_len = 0;
David Howells12bdcf32018-10-20 00:57:56 +0100481 req->index = 0;
482 req->offset = req->pos & (PAGE_SIZE - 1);
David Howells08e0e7c2007-04-26 15:55:03 -0700483 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +0100484 if (call->operation_ID == FSFETCHDATA64) {
485 afs_extract_to_tmp64(call);
486 } else {
487 call->tmp_u = htonl(0);
488 afs_extract_to_tmp(call);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700489 }
David Howells08e0e7c2007-04-26 15:55:03 -0700490
David Howellsb9b1f8d2007-05-10 03:15:21 -0700491 /* extract the returned data length */
David Howells12bdcf32018-10-20 00:57:56 +0100492 case 1:
David Howells08e0e7c2007-04-26 15:55:03 -0700493 _debug("extract data length");
David Howells12bdcf32018-10-20 00:57:56 +0100494 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +0100495 if (ret < 0)
496 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700497
David Howells12bdcf32018-10-20 00:57:56 +0100498 req->actual_len = be64_to_cpu(call->tmp64);
David Howells196ee9c2017-01-05 10:38:34 +0000499 _debug("DATA length: %llu", req->actual_len);
David Howells12bdcf32018-10-20 00:57:56 +0100500 req->remain = min(req->len, req->actual_len);
501 if (req->remain == 0)
David Howells196ee9c2017-01-05 10:38:34 +0000502 goto no_more_data;
David Howells12bdcf32018-10-20 00:57:56 +0100503
David Howells08e0e7c2007-04-26 15:55:03 -0700504 call->unmarshall++;
505
David Howells196ee9c2017-01-05 10:38:34 +0000506 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000507 ASSERTCMP(req->index, <, req->nr_pages);
David Howells12bdcf32018-10-20 00:57:56 +0100508 if (req->remain > PAGE_SIZE - req->offset)
509 size = PAGE_SIZE - req->offset;
David Howells196ee9c2017-01-05 10:38:34 +0000510 else
511 size = req->remain;
David Howells12bdcf32018-10-20 00:57:56 +0100512 call->bvec[0].bv_len = size;
513 call->bvec[0].bv_offset = req->offset;
514 call->bvec[0].bv_page = req->pages[req->index];
515 iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
516 ASSERTCMP(size, <=, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000517
David Howells08e0e7c2007-04-26 15:55:03 -0700518 /* extract the returned data */
David Howells12bdcf32018-10-20 00:57:56 +0100519 case 2:
520 _debug("extract data %zu/%llu",
521 iov_iter_count(&call->iter), req->remain);
David Howells196ee9c2017-01-05 10:38:34 +0000522
David Howells12bdcf32018-10-20 00:57:56 +0100523 ret = afs_extract_data(call, true);
David Howells196ee9c2017-01-05 10:38:34 +0000524 if (ret < 0)
525 return ret;
David Howells12bdcf32018-10-20 00:57:56 +0100526 req->remain -= call->bvec[0].bv_len;
527 req->offset += call->bvec[0].bv_len;
528 ASSERTCMP(req->offset, <=, PAGE_SIZE);
529 if (req->offset == PAGE_SIZE) {
530 req->offset = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000531 if (req->page_done)
532 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000533 req->index++;
David Howells12bdcf32018-10-20 00:57:56 +0100534 if (req->remain > 0)
David Howells196ee9c2017-01-05 10:38:34 +0000535 goto begin_page;
David Howells08e0e7c2007-04-26 15:55:03 -0700536 }
David Howells12bdcf32018-10-20 00:57:56 +0100537
538 ASSERTCMP(req->remain, ==, 0);
539 if (req->actual_len <= req->len)
540 goto no_more_data;
David Howells6db3ac32017-03-16 16:27:44 +0000541
542 /* Discard any excess data the server gave us */
David Howells12bdcf32018-10-20 00:57:56 +0100543 iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
544 call->unmarshall = 3;
545 case 3:
546 _debug("extract discard %zu/%llu",
547 iov_iter_count(&call->iter), req->actual_len - req->len);
David Howells6db3ac32017-03-16 16:27:44 +0000548
David Howells12bdcf32018-10-20 00:57:56 +0100549 ret = afs_extract_data(call, true);
David Howells6db3ac32017-03-16 16:27:44 +0000550 if (ret < 0)
551 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700552
David Howells196ee9c2017-01-05 10:38:34 +0000553 no_more_data:
David Howells12bdcf32018-10-20 00:57:56 +0100554 call->unmarshall = 4;
555 afs_extract_to_buf(call, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700556
557 /* extract the metadata */
David Howells12bdcf32018-10-20 00:57:56 +0100558 case 4:
559 ret = afs_extract_data(call, false);
David Howells372ee162016-08-03 14:11:40 +0100560 if (ret < 0)
561 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700562
563 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100564 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
565 &vnode->status.data_version, req);
566 if (ret < 0)
567 return ret;
David Howellsc435ee32017-11-02 15:27:49 +0000568 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells97e30432017-11-02 15:27:48 +0000569 if (call->reply[1])
570 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700571
David Howells08e0e7c2007-04-26 15:55:03 -0700572 call->unmarshall++;
573
David Howells12bdcf32018-10-20 00:57:56 +0100574 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700575 break;
576 }
577
David Howells6db3ac32017-03-16 16:27:44 +0000578 for (; req->index < req->nr_pages; req->index++) {
David Howells12bdcf32018-10-20 00:57:56 +0100579 if (req->offset < PAGE_SIZE)
David Howells6db3ac32017-03-16 16:27:44 +0000580 zero_user_segment(req->pages[req->index],
David Howells12bdcf32018-10-20 00:57:56 +0100581 req->offset, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000582 if (req->page_done)
583 req->page_done(call, req);
David Howells12bdcf32018-10-20 00:57:56 +0100584 req->offset = 0;
David Howells416351f2007-05-09 02:33:45 -0700585 }
586
David Howells08e0e7c2007-04-26 15:55:03 -0700587 _leave(" = 0 [done]");
588 return 0;
589}
590
David Howells196ee9c2017-01-05 10:38:34 +0000591static void afs_fetch_data_destructor(struct afs_call *call)
592{
David Howells97e30432017-11-02 15:27:48 +0000593 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000594
595 afs_put_read(req);
596 afs_flat_call_destructor(call);
597}
598
David Howells08e0e7c2007-04-26 15:55:03 -0700599/*
600 * FS.FetchData operation type
601 */
602static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700603 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000604 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700605 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000606 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700607};
608
David Howellsb9b1f8d2007-05-10 03:15:21 -0700609static const struct afs_call_type afs_RXFSFetchData64 = {
610 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000611 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700612 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000613 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700614};
615
616/*
617 * fetch data from a very large file
618 */
David Howellsd2ddc772017-11-02 15:27:50 +0000619static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700620{
David Howellsd2ddc772017-11-02 15:27:50 +0000621 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700622 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000623 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700624 __be32 *bp;
625
626 _enter("");
627
David Howellsf044c882017-11-02 15:27:45 +0000628 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700629 if (!call)
630 return -ENOMEM;
631
David Howellsd2ddc772017-11-02 15:27:50 +0000632 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000633 call->reply[0] = vnode;
634 call->reply[1] = NULL; /* volsync */
635 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100636 call->expected_version = vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100637 call->want_reply_time = true;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700638
639 /* marshall the parameters */
640 bp = call->request;
641 bp[0] = htonl(FSFETCHDATA64);
642 bp[1] = htonl(vnode->fid.vid);
643 bp[2] = htonl(vnode->fid.vnode);
644 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000645 bp[4] = htonl(upper_32_bits(req->pos));
646 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700647 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000648 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700649
David Howellsf3ddee82018-04-06 14:17:25 +0100650 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000651 call->cb_break = fc->cb_break;
652 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000653 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000654 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700655}
656
David Howells08e0e7c2007-04-26 15:55:03 -0700657/*
658 * fetch data from a file
659 */
David Howellsd2ddc772017-11-02 15:27:50 +0000660int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700661{
David Howellsd2ddc772017-11-02 15:27:50 +0000662 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700663 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000664 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 __be32 *bp;
666
David Howells196ee9c2017-01-05 10:38:34 +0000667 if (upper_32_bits(req->pos) ||
668 upper_32_bits(req->len) ||
669 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000670 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700671
David Howells08e0e7c2007-04-26 15:55:03 -0700672 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
David Howellsf044c882017-11-02 15:27:45 +0000674 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700675 if (!call)
676 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
David Howellsd2ddc772017-11-02 15:27:50 +0000678 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000679 call->reply[0] = vnode;
680 call->reply[1] = NULL; /* volsync */
681 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100682 call->expected_version = vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100683 call->want_reply_time = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
685 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700686 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700688 bp[1] = htonl(vnode->fid.vid);
689 bp[2] = htonl(vnode->fid.vnode);
690 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000691 bp[4] = htonl(lower_32_bits(req->pos));
692 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
David Howellsf3ddee82018-04-06 14:17:25 +0100694 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000695 call->cb_break = fc->cb_break;
696 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000697 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000698 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700699}
David Howells260a9802007-04-26 15:59:35 -0700700
701/*
702 * deliver reply data to an FS.CreateFile or an FS.MakeDir
703 */
David Howellsd0016482016-08-30 20:42:14 +0100704static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700705{
David Howells97e30432017-11-02 15:27:48 +0000706 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700707 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100708 int ret;
David Howells260a9802007-04-26 15:59:35 -0700709
David Howellsd0016482016-08-30 20:42:14 +0100710 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700711
David Howellsd0016482016-08-30 20:42:14 +0100712 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100713 if (ret < 0)
714 return ret;
David Howells260a9802007-04-26 15:59:35 -0700715
716 /* unmarshall the reply once we've received all of it */
717 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000718 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +0100719 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
720 if (ret < 0)
721 return ret;
722 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
723 &call->expected_version, NULL);
724 if (ret < 0)
725 return ret;
David Howells12d8e952018-10-20 00:57:58 +0100726 xdr_decode_AFSCallBack_raw(call, &bp, call->reply[3]);
David Howells97e30432017-11-02 15:27:48 +0000727 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700728
729 _leave(" = 0 [done]");
730 return 0;
731}
732
733/*
734 * FS.CreateFile and FS.MakeDir operation type
735 */
David Howells025db802017-11-02 15:27:51 +0000736static const struct afs_call_type afs_RXFSCreateFile = {
737 .name = "FS.CreateFile",
738 .op = afs_FS_CreateFile,
739 .deliver = afs_deliver_fs_create_vnode,
740 .destructor = afs_flat_call_destructor,
741};
742
743static const struct afs_call_type afs_RXFSMakeDir = {
744 .name = "FS.MakeDir",
745 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700746 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700747 .destructor = afs_flat_call_destructor,
748};
749
750/*
751 * create a file or make a directory
752 */
David Howells8b2a4642017-11-02 15:27:50 +0000753int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700754 const char *name,
755 umode_t mode,
David Howells63a46812018-04-06 14:17:25 +0100756 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -0700757 struct afs_fid *newfid,
758 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000759 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700760{
David Howellsd2ddc772017-11-02 15:27:50 +0000761 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700762 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000763 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700764 size_t namesz, reqsz, padsz;
765 __be32 *bp;
766
767 _enter("");
768
769 namesz = strlen(name);
770 padsz = (4 - (namesz & 3)) & 3;
771 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
772
David Howells025db802017-11-02 15:27:51 +0000773 call = afs_alloc_flat_call(
774 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
775 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700776 if (!call)
777 return -ENOMEM;
778
David Howellsd2ddc772017-11-02 15:27:50 +0000779 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000780 call->reply[0] = vnode;
781 call->reply[1] = newfid;
782 call->reply[2] = newstatus;
783 call->reply[3] = newcb;
David Howells63a46812018-04-06 14:17:25 +0100784 call->expected_version = current_data_version + 1;
David Howells12d8e952018-10-20 00:57:58 +0100785 call->want_reply_time = true;
David Howells260a9802007-04-26 15:59:35 -0700786
787 /* marshall the parameters */
788 bp = call->request;
789 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
790 *bp++ = htonl(vnode->fid.vid);
791 *bp++ = htonl(vnode->fid.vnode);
792 *bp++ = htonl(vnode->fid.unique);
793 *bp++ = htonl(namesz);
794 memcpy(bp, name, namesz);
795 bp = (void *) bp + namesz;
796 if (padsz > 0) {
797 memset(bp, 0, padsz);
798 bp = (void *) bp + padsz;
799 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000800 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
801 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700802 *bp++ = 0; /* owner */
803 *bp++ = 0; /* group */
804 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
805 *bp++ = 0; /* segment size */
806
David Howellsd2ddc772017-11-02 15:27:50 +0000807 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000808 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000809 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700810}
811
812/*
813 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
814 */
David Howellsd0016482016-08-30 20:42:14 +0100815static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700816{
David Howells97e30432017-11-02 15:27:48 +0000817 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700818 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100819 int ret;
David Howells260a9802007-04-26 15:59:35 -0700820
David Howellsd0016482016-08-30 20:42:14 +0100821 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700822
David Howellsd0016482016-08-30 20:42:14 +0100823 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100824 if (ret < 0)
825 return ret;
David Howells260a9802007-04-26 15:59:35 -0700826
827 /* unmarshall the reply once we've received all of it */
828 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100829 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
830 &call->expected_version, NULL);
831 if (ret < 0)
832 return ret;
David Howells97e30432017-11-02 15:27:48 +0000833 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700834
835 _leave(" = 0 [done]");
836 return 0;
837}
838
839/*
840 * FS.RemoveDir/FS.RemoveFile operation type
841 */
David Howells025db802017-11-02 15:27:51 +0000842static const struct afs_call_type afs_RXFSRemoveFile = {
843 .name = "FS.RemoveFile",
844 .op = afs_FS_RemoveFile,
845 .deliver = afs_deliver_fs_remove,
846 .destructor = afs_flat_call_destructor,
847};
848
849static const struct afs_call_type afs_RXFSRemoveDir = {
850 .name = "FS.RemoveDir",
851 .op = afs_FS_RemoveDir,
David Howells260a9802007-04-26 15:59:35 -0700852 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700853 .destructor = afs_flat_call_destructor,
854};
855
856/*
857 * remove a file or directory
858 */
David Howells63a46812018-04-06 14:17:25 +0100859int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir,
860 u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700861{
David Howellsd2ddc772017-11-02 15:27:50 +0000862 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700863 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000864 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700865 size_t namesz, reqsz, padsz;
866 __be32 *bp;
867
868 _enter("");
869
870 namesz = strlen(name);
871 padsz = (4 - (namesz & 3)) & 3;
872 reqsz = (5 * 4) + namesz + padsz;
873
David Howells025db802017-11-02 15:27:51 +0000874 call = afs_alloc_flat_call(
875 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
876 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700877 if (!call)
878 return -ENOMEM;
879
David Howellsd2ddc772017-11-02 15:27:50 +0000880 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000881 call->reply[0] = vnode;
David Howells63a46812018-04-06 14:17:25 +0100882 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700883
884 /* marshall the parameters */
885 bp = call->request;
886 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
887 *bp++ = htonl(vnode->fid.vid);
888 *bp++ = htonl(vnode->fid.vnode);
889 *bp++ = htonl(vnode->fid.unique);
890 *bp++ = htonl(namesz);
891 memcpy(bp, name, namesz);
892 bp = (void *) bp + namesz;
893 if (padsz > 0) {
894 memset(bp, 0, padsz);
895 bp = (void *) bp + padsz;
896 }
897
David Howellsd2ddc772017-11-02 15:27:50 +0000898 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000899 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000900 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700901}
902
903/*
904 * deliver reply data to an FS.Link
905 */
David Howellsd0016482016-08-30 20:42:14 +0100906static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700907{
David Howells97e30432017-11-02 15:27:48 +0000908 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700909 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100910 int ret;
David Howells260a9802007-04-26 15:59:35 -0700911
David Howellsd0016482016-08-30 20:42:14 +0100912 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700913
David Howellsd0016482016-08-30 20:42:14 +0100914 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100915 if (ret < 0)
916 return ret;
David Howells260a9802007-04-26 15:59:35 -0700917
918 /* unmarshall the reply once we've received all of it */
919 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100920 ret = afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
921 if (ret < 0)
922 return ret;
923 ret = afs_decode_status(call, &bp, &dvnode->status, dvnode,
924 &call->expected_version, NULL);
925 if (ret < 0)
926 return ret;
David Howells97e30432017-11-02 15:27:48 +0000927 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700928
929 _leave(" = 0 [done]");
930 return 0;
931}
932
933/*
934 * FS.Link operation type
935 */
936static const struct afs_call_type afs_RXFSLink = {
937 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000938 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700939 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700940 .destructor = afs_flat_call_destructor,
941};
942
943/*
944 * make a hard link
945 */
David Howellsd2ddc772017-11-02 15:27:50 +0000946int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
David Howells63a46812018-04-06 14:17:25 +0100947 const char *name, u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700948{
David Howellsd2ddc772017-11-02 15:27:50 +0000949 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700950 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000951 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700952 size_t namesz, reqsz, padsz;
953 __be32 *bp;
954
955 _enter("");
956
957 namesz = strlen(name);
958 padsz = (4 - (namesz & 3)) & 3;
959 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
960
David Howellsf044c882017-11-02 15:27:45 +0000961 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700962 if (!call)
963 return -ENOMEM;
964
David Howellsd2ddc772017-11-02 15:27:50 +0000965 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000966 call->reply[0] = dvnode;
967 call->reply[1] = vnode;
David Howells63a46812018-04-06 14:17:25 +0100968 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700969
970 /* marshall the parameters */
971 bp = call->request;
972 *bp++ = htonl(FSLINK);
973 *bp++ = htonl(dvnode->fid.vid);
974 *bp++ = htonl(dvnode->fid.vnode);
975 *bp++ = htonl(dvnode->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(vnode->fid.vid);
984 *bp++ = htonl(vnode->fid.vnode);
985 *bp++ = htonl(vnode->fid.unique);
986
David Howellsd2ddc772017-11-02 15:27:50 +0000987 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000988 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000989 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700990}
991
992/*
993 * deliver reply data to an FS.Symlink
994 */
David Howellsd0016482016-08-30 20:42:14 +0100995static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700996{
David Howells97e30432017-11-02 15:27:48 +0000997 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700998 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100999 int ret;
David Howells260a9802007-04-26 15:59:35 -07001000
David Howellsd0016482016-08-30 20:42:14 +01001001 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001002
David Howellsd0016482016-08-30 20:42:14 +01001003 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001004 if (ret < 0)
1005 return ret;
David Howells260a9802007-04-26 15:59:35 -07001006
1007 /* unmarshall the reply once we've received all of it */
1008 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001009 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +01001010 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
1011 if (ret < 0)
1012 return ret;
1013 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1014 &call->expected_version, NULL);
1015 if (ret < 0)
1016 return ret;
David Howells97e30432017-11-02 15:27:48 +00001017 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001018
1019 _leave(" = 0 [done]");
1020 return 0;
1021}
1022
1023/*
1024 * FS.Symlink operation type
1025 */
1026static const struct afs_call_type afs_RXFSSymlink = {
1027 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +00001028 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -07001029 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -07001030 .destructor = afs_flat_call_destructor,
1031};
1032
1033/*
1034 * create a symbolic link
1035 */
David Howells8b2a4642017-11-02 15:27:50 +00001036int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001037 const char *name,
1038 const char *contents,
David Howells63a46812018-04-06 14:17:25 +01001039 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -07001040 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +00001041 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -07001042{
David Howellsd2ddc772017-11-02 15:27:50 +00001043 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001044 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001045 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -07001046 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
1047 __be32 *bp;
1048
1049 _enter("");
1050
1051 namesz = strlen(name);
1052 padsz = (4 - (namesz & 3)) & 3;
1053
1054 c_namesz = strlen(contents);
1055 c_padsz = (4 - (c_namesz & 3)) & 3;
1056
1057 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
1058
David Howellsf044c882017-11-02 15:27:45 +00001059 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -07001060 (3 + 21 + 21 + 6) * 4);
1061 if (!call)
1062 return -ENOMEM;
1063
David Howellsd2ddc772017-11-02 15:27:50 +00001064 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001065 call->reply[0] = vnode;
1066 call->reply[1] = newfid;
1067 call->reply[2] = newstatus;
David Howells63a46812018-04-06 14:17:25 +01001068 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001069
1070 /* marshall the parameters */
1071 bp = call->request;
1072 *bp++ = htonl(FSSYMLINK);
1073 *bp++ = htonl(vnode->fid.vid);
1074 *bp++ = htonl(vnode->fid.vnode);
1075 *bp++ = htonl(vnode->fid.unique);
1076 *bp++ = htonl(namesz);
1077 memcpy(bp, name, namesz);
1078 bp = (void *) bp + namesz;
1079 if (padsz > 0) {
1080 memset(bp, 0, padsz);
1081 bp = (void *) bp + padsz;
1082 }
1083 *bp++ = htonl(c_namesz);
1084 memcpy(bp, contents, c_namesz);
1085 bp = (void *) bp + c_namesz;
1086 if (c_padsz > 0) {
1087 memset(bp, 0, c_padsz);
1088 bp = (void *) bp + c_padsz;
1089 }
Marc Dionneab94f5d2017-03-16 16:27:47 +00001090 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
1091 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -07001092 *bp++ = 0; /* owner */
1093 *bp++ = 0; /* group */
1094 *bp++ = htonl(S_IRWXUGO); /* unix mode */
1095 *bp++ = 0; /* segment size */
1096
David Howellsd2ddc772017-11-02 15:27:50 +00001097 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001098 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001099 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001100}
1101
1102/*
1103 * deliver reply data to an FS.Rename
1104 */
David Howellsd0016482016-08-30 20:42:14 +01001105static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001106{
David Howells97e30432017-11-02 15:27:48 +00001107 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -07001108 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001109 int ret;
David Howells260a9802007-04-26 15:59:35 -07001110
David Howellsd0016482016-08-30 20:42:14 +01001111 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001112
David Howellsd0016482016-08-30 20:42:14 +01001113 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001114 if (ret < 0)
1115 return ret;
David Howells260a9802007-04-26 15:59:35 -07001116
1117 /* unmarshall the reply once we've received all of it */
1118 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001119 ret = afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
1120 &call->expected_version, NULL);
1121 if (ret < 0)
1122 return ret;
1123 if (new_dvnode != orig_dvnode) {
1124 ret = afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
1125 &call->expected_version_2, NULL);
1126 if (ret < 0)
1127 return ret;
1128 }
David Howells97e30432017-11-02 15:27:48 +00001129 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001130
1131 _leave(" = 0 [done]");
1132 return 0;
1133}
1134
1135/*
1136 * FS.Rename operation type
1137 */
1138static const struct afs_call_type afs_RXFSRename = {
1139 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001140 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001141 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001142 .destructor = afs_flat_call_destructor,
1143};
1144
1145/*
1146 * create a symbolic link
1147 */
David Howells8b2a4642017-11-02 15:27:50 +00001148int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001149 const char *orig_name,
1150 struct afs_vnode *new_dvnode,
David Howells63a46812018-04-06 14:17:25 +01001151 const char *new_name,
1152 u64 current_orig_data_version,
1153 u64 current_new_data_version)
David Howells260a9802007-04-26 15:59:35 -07001154{
David Howellsd2ddc772017-11-02 15:27:50 +00001155 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001156 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001157 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001158 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1159 __be32 *bp;
1160
1161 _enter("");
1162
1163 o_namesz = strlen(orig_name);
1164 o_padsz = (4 - (o_namesz & 3)) & 3;
1165
1166 n_namesz = strlen(new_name);
1167 n_padsz = (4 - (n_namesz & 3)) & 3;
1168
1169 reqsz = (4 * 4) +
1170 4 + o_namesz + o_padsz +
1171 (3 * 4) +
1172 4 + n_namesz + n_padsz;
1173
David Howellsf044c882017-11-02 15:27:45 +00001174 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001175 if (!call)
1176 return -ENOMEM;
1177
David Howellsd2ddc772017-11-02 15:27:50 +00001178 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001179 call->reply[0] = orig_dvnode;
1180 call->reply[1] = new_dvnode;
David Howells63a46812018-04-06 14:17:25 +01001181 call->expected_version = current_orig_data_version + 1;
1182 call->expected_version_2 = current_new_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001183
1184 /* marshall the parameters */
1185 bp = call->request;
1186 *bp++ = htonl(FSRENAME);
1187 *bp++ = htonl(orig_dvnode->fid.vid);
1188 *bp++ = htonl(orig_dvnode->fid.vnode);
1189 *bp++ = htonl(orig_dvnode->fid.unique);
1190 *bp++ = htonl(o_namesz);
1191 memcpy(bp, orig_name, o_namesz);
1192 bp = (void *) bp + o_namesz;
1193 if (o_padsz > 0) {
1194 memset(bp, 0, o_padsz);
1195 bp = (void *) bp + o_padsz;
1196 }
1197
1198 *bp++ = htonl(new_dvnode->fid.vid);
1199 *bp++ = htonl(new_dvnode->fid.vnode);
1200 *bp++ = htonl(new_dvnode->fid.unique);
1201 *bp++ = htonl(n_namesz);
1202 memcpy(bp, new_name, n_namesz);
1203 bp = (void *) bp + n_namesz;
1204 if (n_padsz > 0) {
1205 memset(bp, 0, n_padsz);
1206 bp = (void *) bp + n_padsz;
1207 }
1208
David Howellsd2ddc772017-11-02 15:27:50 +00001209 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001210 trace_afs_make_fs_call(call, &orig_dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001211 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001212}
David Howells31143d52007-05-09 02:33:46 -07001213
1214/*
1215 * deliver reply data to an FS.StoreData
1216 */
David Howellsd0016482016-08-30 20:42:14 +01001217static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001218{
David Howells97e30432017-11-02 15:27:48 +00001219 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001220 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001221 int ret;
David Howells31143d52007-05-09 02:33:46 -07001222
David Howellsd0016482016-08-30 20:42:14 +01001223 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001224
David Howellsd0016482016-08-30 20:42:14 +01001225 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001226 if (ret < 0)
1227 return ret;
David Howells31143d52007-05-09 02:33:46 -07001228
1229 /* unmarshall the reply once we've received all of it */
1230 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001231 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1232 &call->expected_version, NULL);
1233 if (ret < 0)
1234 return ret;
David Howells97e30432017-11-02 15:27:48 +00001235 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001236
1237 afs_pages_written_back(vnode, call);
1238
1239 _leave(" = 0 [done]");
1240 return 0;
1241}
1242
1243/*
1244 * FS.StoreData operation type
1245 */
1246static const struct afs_call_type afs_RXFSStoreData = {
1247 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001248 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001249 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001250 .destructor = afs_flat_call_destructor,
1251};
1252
David Howellsb9b1f8d2007-05-10 03:15:21 -07001253static const struct afs_call_type afs_RXFSStoreData64 = {
1254 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001255 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001256 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001257 .destructor = afs_flat_call_destructor,
1258};
1259
1260/*
1261 * store a set of pages to a very large file
1262 */
David Howells8b2a4642017-11-02 15:27:50 +00001263static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001264 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001265 pgoff_t first, pgoff_t last,
1266 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001267 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001268{
David Howells4343d002017-11-02 15:27:52 +00001269 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001270 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001271 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001272 __be32 *bp;
1273
David Howells3b6492d2018-10-20 00:57:57 +01001274 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001275 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001276
David Howellsf044c882017-11-02 15:27:45 +00001277 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001278 (4 + 6 + 3 * 2) * 4,
1279 (21 + 6) * 4);
1280 if (!call)
1281 return -ENOMEM;
1282
David Howells4343d002017-11-02 15:27:52 +00001283 call->key = fc->key;
1284 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001285 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001286 call->first = first;
1287 call->last = last;
1288 call->first_offset = offset;
1289 call->last_to = to;
1290 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001291 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001292
1293 /* marshall the parameters */
1294 bp = call->request;
1295 *bp++ = htonl(FSSTOREDATA64);
1296 *bp++ = htonl(vnode->fid.vid);
1297 *bp++ = htonl(vnode->fid.vnode);
1298 *bp++ = htonl(vnode->fid.unique);
1299
Marc Dionneab94f5d2017-03-16 16:27:47 +00001300 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1301 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001302 *bp++ = 0; /* owner */
1303 *bp++ = 0; /* group */
1304 *bp++ = 0; /* unix mode */
1305 *bp++ = 0; /* segment size */
1306
1307 *bp++ = htonl(pos >> 32);
1308 *bp++ = htonl((u32) pos);
1309 *bp++ = htonl(size >> 32);
1310 *bp++ = htonl((u32) size);
1311 *bp++ = htonl(i_size >> 32);
1312 *bp++ = htonl((u32) i_size);
1313
David Howells025db802017-11-02 15:27:51 +00001314 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001315 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001316}
1317
David Howells31143d52007-05-09 02:33:46 -07001318/*
1319 * store a set of pages
1320 */
David Howells4343d002017-11-02 15:27:52 +00001321int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001322 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001323 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001324{
David Howells4343d002017-11-02 15:27:52 +00001325 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001326 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001327 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001328 loff_t size, pos, i_size;
1329 __be32 *bp;
1330
David Howells3b6492d2018-10-20 00:57:57 +01001331 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001332 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001333
David Howells146a1192017-03-16 16:27:47 +00001334 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001335 if (first != last)
1336 size += (loff_t)(last - first) << PAGE_SHIFT;
1337 pos = (loff_t)first << PAGE_SHIFT;
1338 pos += offset;
1339
1340 i_size = i_size_read(&vnode->vfs_inode);
1341 if (pos + size > i_size)
1342 i_size = size + pos;
1343
1344 _debug("size %llx, at %llx, i_size %llx",
1345 (unsigned long long) size, (unsigned long long) pos,
1346 (unsigned long long) i_size);
1347
David Howellsb9b1f8d2007-05-10 03:15:21 -07001348 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001349 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001350 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001351
David Howellsf044c882017-11-02 15:27:45 +00001352 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001353 (4 + 6 + 3) * 4,
1354 (21 + 6) * 4);
1355 if (!call)
1356 return -ENOMEM;
1357
David Howells4343d002017-11-02 15:27:52 +00001358 call->key = fc->key;
1359 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001360 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001361 call->first = first;
1362 call->last = last;
1363 call->first_offset = offset;
1364 call->last_to = to;
1365 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001366 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001367
1368 /* marshall the parameters */
1369 bp = call->request;
1370 *bp++ = htonl(FSSTOREDATA);
1371 *bp++ = htonl(vnode->fid.vid);
1372 *bp++ = htonl(vnode->fid.vnode);
1373 *bp++ = htonl(vnode->fid.unique);
1374
Marc Dionneab94f5d2017-03-16 16:27:47 +00001375 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1376 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001377 *bp++ = 0; /* owner */
1378 *bp++ = 0; /* group */
1379 *bp++ = 0; /* unix mode */
1380 *bp++ = 0; /* segment size */
1381
1382 *bp++ = htonl(pos);
1383 *bp++ = htonl(size);
1384 *bp++ = htonl(i_size);
1385
David Howellsd2ddc772017-11-02 15:27:50 +00001386 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001387 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001388 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001389}
1390
1391/*
1392 * deliver reply data to an FS.StoreStatus
1393 */
David Howellsd0016482016-08-30 20:42:14 +01001394static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001395{
David Howells97e30432017-11-02 15:27:48 +00001396 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001397 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001398 int ret;
David Howells31143d52007-05-09 02:33:46 -07001399
David Howellsd0016482016-08-30 20:42:14 +01001400 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001401
David Howellsd0016482016-08-30 20:42:14 +01001402 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001403 if (ret < 0)
1404 return ret;
David Howells31143d52007-05-09 02:33:46 -07001405
1406 /* unmarshall the reply once we've received all of it */
David Howells31143d52007-05-09 02:33:46 -07001407 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001408 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1409 &call->expected_version, NULL);
1410 if (ret < 0)
1411 return ret;
David Howells97e30432017-11-02 15:27:48 +00001412 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001413
1414 _leave(" = 0 [done]");
1415 return 0;
1416}
1417
1418/*
1419 * FS.StoreStatus operation type
1420 */
1421static const struct afs_call_type afs_RXFSStoreStatus = {
1422 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001423 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001424 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001425 .destructor = afs_flat_call_destructor,
1426};
1427
1428static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1429 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001430 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001431 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001432 .destructor = afs_flat_call_destructor,
1433};
1434
David Howellsb9b1f8d2007-05-10 03:15:21 -07001435static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1436 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001437 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001438 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001439 .destructor = afs_flat_call_destructor,
1440};
1441
1442/*
1443 * set the attributes on a very large file, using FS.StoreData rather than
1444 * FS.StoreStatus so as to alter the file size also
1445 */
David Howellsd2ddc772017-11-02 15:27:50 +00001446static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001447{
David Howellsd2ddc772017-11-02 15:27:50 +00001448 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001449 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001450 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001451 __be32 *bp;
1452
David Howells3b6492d2018-10-20 00:57:57 +01001453 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001454 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001455
1456 ASSERT(attr->ia_valid & ATTR_SIZE);
1457
David Howellsf044c882017-11-02 15:27:45 +00001458 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001459 (4 + 6 + 3 * 2) * 4,
1460 (21 + 6) * 4);
1461 if (!call)
1462 return -ENOMEM;
1463
David Howellsd2ddc772017-11-02 15:27:50 +00001464 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001465 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001466 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001467
1468 /* marshall the parameters */
1469 bp = call->request;
1470 *bp++ = htonl(FSSTOREDATA64);
1471 *bp++ = htonl(vnode->fid.vid);
1472 *bp++ = htonl(vnode->fid.vnode);
1473 *bp++ = htonl(vnode->fid.unique);
1474
1475 xdr_encode_AFS_StoreStatus(&bp, attr);
1476
1477 *bp++ = 0; /* position of start of write */
1478 *bp++ = 0;
1479 *bp++ = 0; /* size of write */
1480 *bp++ = 0;
1481 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1482 *bp++ = htonl((u32) attr->ia_size);
1483
David Howellsd2ddc772017-11-02 15:27:50 +00001484 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001485 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001486 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001487}
1488
David Howells31143d52007-05-09 02:33:46 -07001489/*
1490 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1491 * so as to alter the file size also
1492 */
David Howellsd2ddc772017-11-02 15:27:50 +00001493static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001494{
David Howellsd2ddc772017-11-02 15:27:50 +00001495 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001496 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001497 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001498 __be32 *bp;
1499
David Howells3b6492d2018-10-20 00:57:57 +01001500 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001501 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001502
1503 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001504 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001505 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001506
David Howellsf044c882017-11-02 15:27:45 +00001507 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001508 (4 + 6 + 3) * 4,
1509 (21 + 6) * 4);
1510 if (!call)
1511 return -ENOMEM;
1512
David Howellsd2ddc772017-11-02 15:27:50 +00001513 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001514 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001515 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001516
1517 /* marshall the parameters */
1518 bp = call->request;
1519 *bp++ = htonl(FSSTOREDATA);
1520 *bp++ = htonl(vnode->fid.vid);
1521 *bp++ = htonl(vnode->fid.vnode);
1522 *bp++ = htonl(vnode->fid.unique);
1523
1524 xdr_encode_AFS_StoreStatus(&bp, attr);
1525
1526 *bp++ = 0; /* position of start of write */
1527 *bp++ = 0; /* size of write */
1528 *bp++ = htonl(attr->ia_size); /* new file length */
1529
David Howellsd2ddc772017-11-02 15:27:50 +00001530 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001531 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001532 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001533}
1534
1535/*
1536 * set the attributes on a file, using FS.StoreData if there's a change in file
1537 * size, and FS.StoreStatus otherwise
1538 */
David Howellsd2ddc772017-11-02 15:27:50 +00001539int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001540{
David Howellsd2ddc772017-11-02 15:27:50 +00001541 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001542 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001543 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001544 __be32 *bp;
1545
1546 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001547 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001548
David Howells3b6492d2018-10-20 00:57:57 +01001549 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001550 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001551
David Howellsf044c882017-11-02 15:27:45 +00001552 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001553 (4 + 6) * 4,
1554 (21 + 6) * 4);
1555 if (!call)
1556 return -ENOMEM;
1557
David Howellsd2ddc772017-11-02 15:27:50 +00001558 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001559 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001560 call->expected_version = vnode->status.data_version;
David Howells31143d52007-05-09 02:33:46 -07001561
1562 /* marshall the parameters */
1563 bp = call->request;
1564 *bp++ = htonl(FSSTORESTATUS);
1565 *bp++ = htonl(vnode->fid.vid);
1566 *bp++ = htonl(vnode->fid.vnode);
1567 *bp++ = htonl(vnode->fid.unique);
1568
1569 xdr_encode_AFS_StoreStatus(&bp, attr);
1570
David Howellsd2ddc772017-11-02 15:27:50 +00001571 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001572 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001573 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001574}
David Howells45222b92007-05-10 22:22:20 -07001575
1576/*
1577 * deliver reply data to an FS.GetVolumeStatus
1578 */
David Howellsd0016482016-08-30 20:42:14 +01001579static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001580{
1581 const __be32 *bp;
1582 char *p;
David Howells12bdcf32018-10-20 00:57:56 +01001583 u32 size;
David Howells45222b92007-05-10 22:22:20 -07001584 int ret;
1585
David Howellsd0016482016-08-30 20:42:14 +01001586 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001587
1588 switch (call->unmarshall) {
1589 case 0:
David Howells45222b92007-05-10 22:22:20 -07001590 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001591 afs_extract_to_buf(call, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001592
1593 /* extract the returned status record */
1594 case 1:
1595 _debug("extract status");
David Howells12bdcf32018-10-20 00:57:56 +01001596 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001597 if (ret < 0)
1598 return ret;
David Howells45222b92007-05-10 22:22:20 -07001599
1600 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001601 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001602 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001603 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001604
1605 /* extract the volume name length */
1606 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001607 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001608 if (ret < 0)
1609 return ret;
David Howells45222b92007-05-10 22:22:20 -07001610
1611 call->count = ntohl(call->tmp);
1612 _debug("volname length: %u", call->count);
1613 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001614 return afs_protocol_error(call, -EBADMSG,
1615 afs_eproto_volname_len);
David Howells12bdcf32018-10-20 00:57:56 +01001616 size = (call->count + 3) & ~3; /* It's padded */
1617 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001618 call->unmarshall++;
1619
1620 /* extract the volume name */
1621 case 3:
1622 _debug("extract volname");
David Howells12bdcf32018-10-20 00:57:56 +01001623 ret = afs_extract_data(call, true);
1624 if (ret < 0)
1625 return ret;
David Howells45222b92007-05-10 22:22:20 -07001626
David Howells97e30432017-11-02 15:27:48 +00001627 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001628 p[call->count] = 0;
1629 _debug("volname '%s'", p);
David Howells12bdcf32018-10-20 00:57:56 +01001630 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001631 call->unmarshall++;
1632
David Howells45222b92007-05-10 22:22:20 -07001633 /* extract the offline message length */
David Howells12bdcf32018-10-20 00:57:56 +01001634 case 4:
1635 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001636 if (ret < 0)
1637 return ret;
David Howells45222b92007-05-10 22:22:20 -07001638
1639 call->count = ntohl(call->tmp);
1640 _debug("offline msg length: %u", call->count);
1641 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001642 return afs_protocol_error(call, -EBADMSG,
1643 afs_eproto_offline_msg_len);
David Howells12bdcf32018-10-20 00:57:56 +01001644 size = (call->count + 3) & ~3; /* It's padded */
1645 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001646 call->unmarshall++;
1647
1648 /* extract the offline message */
David Howells12bdcf32018-10-20 00:57:56 +01001649 case 5:
David Howells45222b92007-05-10 22:22:20 -07001650 _debug("extract offline");
David Howells12bdcf32018-10-20 00:57:56 +01001651 ret = afs_extract_data(call, true);
1652 if (ret < 0)
1653 return ret;
David Howells45222b92007-05-10 22:22:20 -07001654
David Howells97e30432017-11-02 15:27:48 +00001655 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001656 p[call->count] = 0;
1657 _debug("offline '%s'", p);
1658
David Howells12bdcf32018-10-20 00:57:56 +01001659 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001660 call->unmarshall++;
1661
David Howells45222b92007-05-10 22:22:20 -07001662 /* extract the message of the day length */
David Howells12bdcf32018-10-20 00:57:56 +01001663 case 6:
1664 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001665 if (ret < 0)
1666 return ret;
David Howells45222b92007-05-10 22:22:20 -07001667
1668 call->count = ntohl(call->tmp);
1669 _debug("motd length: %u", call->count);
1670 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001671 return afs_protocol_error(call, -EBADMSG,
1672 afs_eproto_motd_len);
David Howells12bdcf32018-10-20 00:57:56 +01001673 size = (call->count + 3) & ~3; /* It's padded */
1674 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001675 call->unmarshall++;
1676
1677 /* extract the message of the day */
David Howells12bdcf32018-10-20 00:57:56 +01001678 case 7:
David Howells45222b92007-05-10 22:22:20 -07001679 _debug("extract motd");
David Howells12bdcf32018-10-20 00:57:56 +01001680 ret = afs_extract_data(call, false);
1681 if (ret < 0)
1682 return ret;
David Howells45222b92007-05-10 22:22:20 -07001683
David Howells97e30432017-11-02 15:27:48 +00001684 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001685 p[call->count] = 0;
1686 _debug("motd '%s'", p);
1687
David Howells45222b92007-05-10 22:22:20 -07001688 call->unmarshall++;
1689
David Howells12bdcf32018-10-20 00:57:56 +01001690 case 8:
David Howells45222b92007-05-10 22:22:20 -07001691 break;
1692 }
1693
David Howells45222b92007-05-10 22:22:20 -07001694 _leave(" = 0 [done]");
1695 return 0;
1696}
1697
1698/*
1699 * destroy an FS.GetVolumeStatus call
1700 */
1701static void afs_get_volume_status_call_destructor(struct afs_call *call)
1702{
David Howells97e30432017-11-02 15:27:48 +00001703 kfree(call->reply[2]);
1704 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001705 afs_flat_call_destructor(call);
1706}
1707
1708/*
1709 * FS.GetVolumeStatus operation type
1710 */
1711static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1712 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001713 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001714 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001715 .destructor = afs_get_volume_status_call_destructor,
1716};
1717
1718/*
1719 * fetch the status of a volume
1720 */
David Howells8b2a4642017-11-02 15:27:50 +00001721int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001722 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001723{
David Howellsd2ddc772017-11-02 15:27:50 +00001724 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001725 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001726 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001727 __be32 *bp;
1728 void *tmpbuf;
1729
1730 _enter("");
1731
1732 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1733 if (!tmpbuf)
1734 return -ENOMEM;
1735
David Howellsf044c882017-11-02 15:27:45 +00001736 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001737 if (!call) {
1738 kfree(tmpbuf);
1739 return -ENOMEM;
1740 }
1741
David Howellsd2ddc772017-11-02 15:27:50 +00001742 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001743 call->reply[0] = vnode;
1744 call->reply[1] = vs;
1745 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001746
1747 /* marshall the parameters */
1748 bp = call->request;
1749 bp[0] = htonl(FSGETVOLUMESTATUS);
1750 bp[1] = htonl(vnode->fid.vid);
1751
David Howellsd2ddc772017-11-02 15:27:50 +00001752 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001753 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001754 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells45222b92007-05-10 22:22:20 -07001755}
David Howellse8d6c552007-07-15 23:40:12 -07001756
1757/*
1758 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1759 */
David Howellsd0016482016-08-30 20:42:14 +01001760static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001761{
1762 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001763 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001764
David Howellsd0016482016-08-30 20:42:14 +01001765 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001766
David Howellsd0016482016-08-30 20:42:14 +01001767 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001768 if (ret < 0)
1769 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001770
1771 /* unmarshall the reply once we've received all of it */
1772 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001773 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001774
1775 _leave(" = 0 [done]");
1776 return 0;
1777}
1778
1779/*
1780 * FS.SetLock operation type
1781 */
1782static const struct afs_call_type afs_RXFSSetLock = {
1783 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001784 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001785 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001786 .destructor = afs_flat_call_destructor,
1787};
1788
1789/*
1790 * FS.ExtendLock operation type
1791 */
1792static const struct afs_call_type afs_RXFSExtendLock = {
1793 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001794 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001795 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001796 .destructor = afs_flat_call_destructor,
1797};
1798
1799/*
1800 * FS.ReleaseLock operation type
1801 */
1802static const struct afs_call_type afs_RXFSReleaseLock = {
1803 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001804 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001805 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001806 .destructor = afs_flat_call_destructor,
1807};
1808
1809/*
David Howellsd2ddc772017-11-02 15:27:50 +00001810 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001811 */
David Howellsd2ddc772017-11-02 15:27:50 +00001812int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001813{
David Howellsd2ddc772017-11-02 15:27:50 +00001814 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001815 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001816 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001817 __be32 *bp;
1818
1819 _enter("");
1820
David Howellsf044c882017-11-02 15:27:45 +00001821 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001822 if (!call)
1823 return -ENOMEM;
1824
David Howellsd2ddc772017-11-02 15:27:50 +00001825 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001826 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001827
1828 /* marshall the parameters */
1829 bp = call->request;
1830 *bp++ = htonl(FSSETLOCK);
1831 *bp++ = htonl(vnode->fid.vid);
1832 *bp++ = htonl(vnode->fid.vnode);
1833 *bp++ = htonl(vnode->fid.unique);
1834 *bp++ = htonl(type);
1835
David Howellsd2ddc772017-11-02 15:27:50 +00001836 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001837 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001838 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001839}
1840
1841/*
1842 * extend a lock on a file
1843 */
David Howellsd2ddc772017-11-02 15:27:50 +00001844int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001845{
David Howellsd2ddc772017-11-02 15:27:50 +00001846 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001847 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001848 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001849 __be32 *bp;
1850
1851 _enter("");
1852
David Howellsf044c882017-11-02 15:27:45 +00001853 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001854 if (!call)
1855 return -ENOMEM;
1856
David Howellsd2ddc772017-11-02 15:27:50 +00001857 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001858 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001859
1860 /* marshall the parameters */
1861 bp = call->request;
1862 *bp++ = htonl(FSEXTENDLOCK);
1863 *bp++ = htonl(vnode->fid.vid);
1864 *bp++ = htonl(vnode->fid.vnode);
1865 *bp++ = htonl(vnode->fid.unique);
1866
David Howellsd2ddc772017-11-02 15:27:50 +00001867 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001868 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001869 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001870}
1871
1872/*
1873 * release a lock on a file
1874 */
David Howellsd2ddc772017-11-02 15:27:50 +00001875int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001876{
David Howellsd2ddc772017-11-02 15:27:50 +00001877 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001878 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001879 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001880 __be32 *bp;
1881
1882 _enter("");
1883
David Howellsf044c882017-11-02 15:27:45 +00001884 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001885 if (!call)
1886 return -ENOMEM;
1887
David Howellsd2ddc772017-11-02 15:27:50 +00001888 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001889 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001890
1891 /* marshall the parameters */
1892 bp = call->request;
1893 *bp++ = htonl(FSRELEASELOCK);
1894 *bp++ = htonl(vnode->fid.vid);
1895 *bp++ = htonl(vnode->fid.vnode);
1896 *bp++ = htonl(vnode->fid.unique);
1897
David Howellsd2ddc772017-11-02 15:27:50 +00001898 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001899 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001900 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsc435ee32017-11-02 15:27:49 +00001901}
1902
1903/*
1904 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1905 */
1906static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1907{
1908 return afs_transfer_reply(call);
1909}
1910
1911/*
1912 * FS.GiveUpAllCallBacks operation type
1913 */
1914static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1915 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001916 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001917 .deliver = afs_deliver_fs_give_up_all_callbacks,
1918 .destructor = afs_flat_call_destructor,
1919};
1920
1921/*
1922 * Flush all the callbacks we have on a server.
1923 */
David Howellsd2ddc772017-11-02 15:27:50 +00001924int afs_fs_give_up_all_callbacks(struct afs_net *net,
1925 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001926 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001927 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001928{
1929 struct afs_call *call;
1930 __be32 *bp;
1931
1932 _enter("");
1933
David Howellsd2ddc772017-11-02 15:27:50 +00001934 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001935 if (!call)
1936 return -ENOMEM;
1937
1938 call->key = key;
1939
1940 /* marshall the parameters */
1941 bp = call->request;
1942 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1943
1944 /* Can't take a ref on server */
David Howellsd2ddc772017-11-02 15:27:50 +00001945 return afs_make_call(ac, call, GFP_NOFS, false);
1946}
1947
1948/*
1949 * Deliver reply data to an FS.GetCapabilities operation.
1950 */
1951static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1952{
1953 u32 count;
1954 int ret;
1955
David Howells12bdcf32018-10-20 00:57:56 +01001956 _enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter));
David Howellsd2ddc772017-11-02 15:27:50 +00001957
David Howellsd2ddc772017-11-02 15:27:50 +00001958 switch (call->unmarshall) {
1959 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01001960 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00001961 call->unmarshall++;
1962
1963 /* Extract the capabilities word count */
1964 case 1:
David Howells12bdcf32018-10-20 00:57:56 +01001965 ret = afs_extract_data(call, true);
David Howellsd2ddc772017-11-02 15:27:50 +00001966 if (ret < 0)
1967 return ret;
1968
1969 count = ntohl(call->tmp);
1970
1971 call->count = count;
1972 call->count2 = count;
David Howells12bdcf32018-10-20 00:57:56 +01001973 iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
David Howellsd2ddc772017-11-02 15:27:50 +00001974 call->unmarshall++;
1975
1976 /* Extract capabilities words */
1977 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001978 ret = afs_extract_data(call, false);
David Howellsd2ddc772017-11-02 15:27:50 +00001979 if (ret < 0)
1980 return ret;
1981
1982 /* TODO: Examine capabilities */
1983
David Howellsd2ddc772017-11-02 15:27:50 +00001984 call->unmarshall++;
1985 break;
1986 }
1987
1988 _leave(" = 0 [done]");
1989 return 0;
1990}
1991
1992/*
1993 * FS.GetCapabilities operation type
1994 */
1995static const struct afs_call_type afs_RXFSGetCapabilities = {
1996 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00001997 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00001998 .deliver = afs_deliver_fs_get_capabilities,
1999 .destructor = afs_flat_call_destructor,
2000};
2001
2002/*
2003 * Probe a fileserver for the capabilities that it supports. This can
2004 * return up to 196 words.
2005 */
2006int afs_fs_get_capabilities(struct afs_net *net,
2007 struct afs_server *server,
2008 struct afs_addr_cursor *ac,
2009 struct key *key)
2010{
2011 struct afs_call *call;
2012 __be32 *bp;
2013
2014 _enter("");
2015
2016 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
2017 if (!call)
2018 return -ENOMEM;
2019
2020 call->key = key;
2021
2022 /* marshall the parameters */
2023 bp = call->request;
2024 *bp++ = htonl(FSGETCAPABILITIES);
2025
2026 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00002027 trace_afs_make_fs_call(call, NULL);
David Howellsd2ddc772017-11-02 15:27:50 +00002028 return afs_make_call(ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07002029}
David Howells5cf9dd52018-04-09 21:12:31 +01002030
2031/*
2032 * Deliver reply data to an FS.FetchStatus with no vnode.
2033 */
2034static int afs_deliver_fs_fetch_status(struct afs_call *call)
2035{
2036 struct afs_file_status *status = call->reply[1];
2037 struct afs_callback *callback = call->reply[2];
2038 struct afs_volsync *volsync = call->reply[3];
David Howells36bb5f42018-10-20 00:57:58 +01002039 struct afs_fid *fid = call->reply[0];
David Howells5cf9dd52018-04-09 21:12:31 +01002040 const __be32 *bp;
2041 int ret;
2042
2043 ret = afs_transfer_reply(call);
2044 if (ret < 0)
2045 return ret;
2046
David Howells36bb5f42018-10-20 00:57:58 +01002047 _enter("{%llx:%llu}", fid->vid, fid->vnode);
David Howells5cf9dd52018-04-09 21:12:31 +01002048
2049 /* unmarshall the reply once we've received all of it */
2050 bp = call->buffer;
David Howells36bb5f42018-10-20 00:57:58 +01002051 ret = afs_decode_status(call, &bp, status, NULL,
David Howells160cb952018-10-20 00:57:56 +01002052 &call->expected_version, NULL);
2053 if (ret < 0)
2054 return ret;
David Howells12d8e952018-10-20 00:57:58 +01002055 xdr_decode_AFSCallBack_raw(call, &bp, callback);
David Howells5cf9dd52018-04-09 21:12:31 +01002056 if (volsync)
2057 xdr_decode_AFSVolSync(&bp, volsync);
2058
2059 _leave(" = 0 [done]");
2060 return 0;
2061}
2062
2063/*
2064 * FS.FetchStatus operation type
2065 */
2066static const struct afs_call_type afs_RXFSFetchStatus = {
2067 .name = "FS.FetchStatus",
2068 .op = afs_FS_FetchStatus,
2069 .deliver = afs_deliver_fs_fetch_status,
2070 .destructor = afs_flat_call_destructor,
2071};
2072
2073/*
2074 * Fetch the status information for a fid without needing a vnode handle.
2075 */
2076int afs_fs_fetch_status(struct afs_fs_cursor *fc,
2077 struct afs_net *net,
2078 struct afs_fid *fid,
2079 struct afs_file_status *status,
2080 struct afs_callback *callback,
2081 struct afs_volsync *volsync)
2082{
2083 struct afs_call *call;
2084 __be32 *bp;
2085
David Howells3b6492d2018-10-20 00:57:57 +01002086 _enter(",%x,{%llx:%llu},,",
David Howells5cf9dd52018-04-09 21:12:31 +01002087 key_serial(fc->key), fid->vid, fid->vnode);
2088
2089 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
2090 if (!call) {
2091 fc->ac.error = -ENOMEM;
2092 return -ENOMEM;
2093 }
2094
2095 call->key = fc->key;
David Howells36bb5f42018-10-20 00:57:58 +01002096 call->reply[0] = fid;
David Howells5cf9dd52018-04-09 21:12:31 +01002097 call->reply[1] = status;
2098 call->reply[2] = callback;
2099 call->reply[3] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +01002100 call->expected_version = 1; /* vnode->status.data_version */
David Howells12d8e952018-10-20 00:57:58 +01002101 call->want_reply_time = true;
David Howells5cf9dd52018-04-09 21:12:31 +01002102
2103 /* marshall the parameters */
2104 bp = call->request;
2105 bp[0] = htonl(FSFETCHSTATUS);
2106 bp[1] = htonl(fid->vid);
2107 bp[2] = htonl(fid->vnode);
2108 bp[3] = htonl(fid->unique);
2109
2110 call->cb_break = fc->cb_break;
2111 afs_use_fs_server(call, fc->cbi);
2112 trace_afs_make_fs_call(call, fid);
2113 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2114}
2115
2116/*
2117 * Deliver reply data to an FS.InlineBulkStatus call
2118 */
2119static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2120{
2121 struct afs_file_status *statuses;
2122 struct afs_callback *callbacks;
2123 struct afs_vnode *vnode = call->reply[0];
2124 const __be32 *bp;
2125 u32 tmp;
2126 int ret;
2127
2128 _enter("{%u}", call->unmarshall);
2129
2130 switch (call->unmarshall) {
2131 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01002132 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002133 call->unmarshall++;
2134
2135 /* Extract the file status count and array in two steps */
2136 case 1:
2137 _debug("extract status count");
David Howells12bdcf32018-10-20 00:57:56 +01002138 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002139 if (ret < 0)
2140 return ret;
2141
2142 tmp = ntohl(call->tmp);
2143 _debug("status count: %u/%u", tmp, call->count2);
2144 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002145 return afs_protocol_error(call, -EBADMSG,
2146 afs_eproto_ibulkst_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002147
2148 call->count = 0;
2149 call->unmarshall++;
2150 more_counts:
David Howells12bdcf32018-10-20 00:57:56 +01002151 afs_extract_to_buf(call, 21 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002152
2153 case 2:
2154 _debug("extract status array %u", call->count);
David Howells12bdcf32018-10-20 00:57:56 +01002155 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002156 if (ret < 0)
2157 return ret;
2158
2159 bp = call->buffer;
2160 statuses = call->reply[1];
David Howells160cb952018-10-20 00:57:56 +01002161 ret = afs_decode_status(call, &bp, &statuses[call->count],
2162 call->count == 0 ? vnode : NULL,
2163 NULL, NULL);
2164 if (ret < 0)
2165 return ret;
David Howells5cf9dd52018-04-09 21:12:31 +01002166
2167 call->count++;
2168 if (call->count < call->count2)
2169 goto more_counts;
2170
2171 call->count = 0;
2172 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01002173 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002174
2175 /* Extract the callback count and array in two steps */
2176 case 3:
2177 _debug("extract CB count");
David Howells12bdcf32018-10-20 00:57:56 +01002178 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002179 if (ret < 0)
2180 return ret;
2181
2182 tmp = ntohl(call->tmp);
2183 _debug("CB count: %u", tmp);
2184 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002185 return afs_protocol_error(call, -EBADMSG,
2186 afs_eproto_ibulkst_cb_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002187 call->count = 0;
2188 call->unmarshall++;
2189 more_cbs:
David Howells12bdcf32018-10-20 00:57:56 +01002190 afs_extract_to_buf(call, 3 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002191
2192 case 4:
2193 _debug("extract CB array");
David Howells12bdcf32018-10-20 00:57:56 +01002194 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002195 if (ret < 0)
2196 return ret;
2197
2198 _debug("unmarshall CB array");
2199 bp = call->buffer;
2200 callbacks = call->reply[2];
2201 callbacks[call->count].version = ntohl(bp[0]);
David Howells12d8e952018-10-20 00:57:58 +01002202 callbacks[call->count].expires_at = xdr_decode_expiry(call, ntohl(bp[1]));
David Howells5cf9dd52018-04-09 21:12:31 +01002203 callbacks[call->count].type = ntohl(bp[2]);
2204 statuses = call->reply[1];
2205 if (call->count == 0 && vnode && statuses[0].abort_code == 0)
2206 xdr_decode_AFSCallBack(call, vnode, &bp);
2207 call->count++;
2208 if (call->count < call->count2)
2209 goto more_cbs;
2210
David Howells12bdcf32018-10-20 00:57:56 +01002211 afs_extract_to_buf(call, 6 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002212 call->unmarshall++;
2213
2214 case 5:
David Howells12bdcf32018-10-20 00:57:56 +01002215 ret = afs_extract_data(call, false);
David Howells5cf9dd52018-04-09 21:12:31 +01002216 if (ret < 0)
2217 return ret;
2218
2219 bp = call->buffer;
2220 if (call->reply[3])
2221 xdr_decode_AFSVolSync(&bp, call->reply[3]);
2222
David Howells5cf9dd52018-04-09 21:12:31 +01002223 call->unmarshall++;
2224
2225 case 6:
2226 break;
2227 }
2228
2229 _leave(" = 0 [done]");
2230 return 0;
2231}
2232
2233/*
2234 * FS.InlineBulkStatus operation type
2235 */
2236static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2237 .name = "FS.InlineBulkStatus",
2238 .op = afs_FS_InlineBulkStatus,
2239 .deliver = afs_deliver_fs_inline_bulk_status,
2240 .destructor = afs_flat_call_destructor,
2241};
2242
2243/*
2244 * Fetch the status information for up to 50 files
2245 */
2246int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2247 struct afs_net *net,
2248 struct afs_fid *fids,
2249 struct afs_file_status *statuses,
2250 struct afs_callback *callbacks,
2251 unsigned int nr_fids,
2252 struct afs_volsync *volsync)
2253{
2254 struct afs_call *call;
2255 __be32 *bp;
2256 int i;
2257
David Howells3b6492d2018-10-20 00:57:57 +01002258 _enter(",%x,{%llx:%llu},%u",
David Howells5cf9dd52018-04-09 21:12:31 +01002259 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2260
2261 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2262 (2 + nr_fids * 3) * 4,
2263 21 * 4);
2264 if (!call) {
2265 fc->ac.error = -ENOMEM;
2266 return -ENOMEM;
2267 }
2268
2269 call->key = fc->key;
2270 call->reply[0] = NULL; /* vnode for fid[0] */
2271 call->reply[1] = statuses;
2272 call->reply[2] = callbacks;
2273 call->reply[3] = volsync;
2274 call->count2 = nr_fids;
David Howells12d8e952018-10-20 00:57:58 +01002275 call->want_reply_time = true;
David Howells5cf9dd52018-04-09 21:12:31 +01002276
2277 /* marshall the parameters */
2278 bp = call->request;
2279 *bp++ = htonl(FSINLINEBULKSTATUS);
2280 *bp++ = htonl(nr_fids);
2281 for (i = 0; i < nr_fids; i++) {
2282 *bp++ = htonl(fids[i].vid);
2283 *bp++ = htonl(fids[i].vnode);
2284 *bp++ = htonl(fids[i].unique);
2285 }
2286
2287 call->cb_break = fc->cb_break;
2288 afs_use_fs_server(call, fc->cbi);
2289 trace_afs_make_fs_call(call, &fids[0]);
2290 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2291}