blob: 0b37867b5c202332b66ba5bede2a31e4287a23e0 [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"
David Howells30062bd2018-10-20 00:57:58 +010020#include "protocol_yfs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
David Howells025db802017-11-02 15:27:51 +000022static const struct afs_fid afs_zero_fid;
23
David Howellsd2ddc772017-11-02 15:27:50 +000024static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
David Howellsc435ee32017-11-02 15:27:49 +000025{
David Howellsd2ddc772017-11-02 15:27:50 +000026 call->cbi = afs_get_cb_interest(cbi);
David Howellsc435ee32017-11-02 15:27:49 +000027}
28
David Howells6db3ac32017-03-16 16:27:44 +000029/*
David Howells260a9802007-04-26 15:59:35 -070030 * decode an AFSFid block
31 */
32static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
33{
34 const __be32 *bp = *_bp;
35
36 fid->vid = ntohl(*bp++);
37 fid->vnode = ntohl(*bp++);
38 fid->unique = ntohl(*bp++);
39 *_bp = bp;
40}
41
42/*
David Howells888b3382018-04-06 14:17:24 +010043 * Dump a bad file status record.
44 */
45static void xdr_dump_bad(const __be32 *bp)
46{
47 __be32 x[4];
48 int i;
49
50 pr_notice("AFS XDR: Bad status record\n");
51 for (i = 0; i < 5 * 4 * 4; i += 16) {
52 memcpy(x, bp, 16);
53 bp += 4;
54 pr_notice("%03x: %08x %08x %08x %08x\n",
55 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
56 }
57
58 memcpy(x, bp, 4);
59 pr_notice("0x50: %08x\n", ntohl(x[0]));
60}
61
62/*
David Howellsdd9fbcb2018-04-06 14:17:24 +010063 * Update the core inode struct from a returned status record.
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 */
David Howellsdd9fbcb2018-04-06 14:17:24 +010065void afs_update_inode_from_status(struct afs_vnode *vnode,
66 struct afs_file_status *status,
67 const afs_dataversion_t *expected_version,
68 u8 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069{
Deepa Dinamani95582b02018-05-08 19:36:02 -070070 struct timespec64 t;
David Howells08e0e7c2007-04-26 15:55:03 -070071 umode_t mode;
David Howells08e0e7c2007-04-26 15:55:03 -070072
David Howellsd4936802018-10-20 00:57:58 +010073 t = status->mtime_client;
David Howellsdd9fbcb2018-04-06 14:17:24 +010074 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
David Howellsd4936802018-10-20 00:57:58 +0100197 status->mtime_client.tv_sec = ntohl(xdr->mtime_client);
198 status->mtime_client.tv_nsec = 0;
199 status->mtime_server.tv_sec = ntohl(xdr->mtime_server);
200 status->mtime_server.tv_nsec = 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100201 status->lock_count = ntohl(xdr->lock_count);
202
203 size = (u64)ntohl(xdr->size_lo);
204 size |= (u64)ntohl(xdr->size_hi) << 32;
David Howells63a46812018-04-06 14:17:25 +0100205 status->size = size;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100206
207 data_version = (u64)ntohl(xdr->data_version_lo);
208 data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
209 if (data_version != status->data_version) {
210 status->data_version = data_version;
211 flags |= AFS_VNODE_DATA_CHANGED;
212 }
David Howellsf3ddee82018-04-06 14:17:25 +0100213
214 if (read_req) {
215 read_req->data_version = data_version;
216 read_req->file_size = size;
217 }
David Howellsdd9fbcb2018-04-06 14:17:24 +0100218
219 *_bp = (const void *)*_bp + sizeof(*xdr);
220
221 if (vnode) {
222 if (test_bit(AFS_VNODE_UNSET, &vnode->flags))
223 flags |= AFS_VNODE_NOT_YET_SET;
224 afs_update_inode_from_status(vnode, status, expected_version,
225 flags);
226 }
227
David Howellsc875c762018-05-23 11:32:06 +0100228 return 0;
David Howellsdd9fbcb2018-04-06 14:17:24 +0100229
230bad:
231 xdr_dump_bad(*_bp);
David Howells160cb952018-10-20 00:57:56 +0100232 return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
David Howellsc875c762018-05-23 11:32:06 +0100233}
234
235/*
236 * Decode the file status. We need to lock the target vnode if we're going to
237 * update its status so that stat() sees the attributes update atomically.
238 */
239static int afs_decode_status(struct afs_call *call,
240 const __be32 **_bp,
241 struct afs_file_status *status,
242 struct afs_vnode *vnode,
243 const afs_dataversion_t *expected_version,
244 struct afs_read *read_req)
245{
246 int ret;
247
248 if (!vnode)
249 return xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
250 expected_version, read_req);
251
252 write_seqlock(&vnode->cb_lock);
253 ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
254 expected_version, read_req);
255 write_sequnlock(&vnode->cb_lock);
256 return ret;
David Howellsec268152007-04-26 15:49:28 -0700257}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259/*
David Howells08e0e7c2007-04-26 15:55:03 -0700260 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 */
David Howellsc435ee32017-11-02 15:27:49 +0000262static void xdr_decode_AFSCallBack(struct afs_call *call,
263 struct afs_vnode *vnode,
264 const __be32 **_bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{
David Howellsd2ddc772017-11-02 15:27:50 +0000266 struct afs_cb_interest *old, *cbi = call->cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700267 const __be32 *bp = *_bp;
David Howellsc435ee32017-11-02 15:27:49 +0000268 u32 cb_expiry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
David Howellsc435ee32017-11-02 15:27:49 +0000270 write_seqlock(&vnode->cb_lock);
271
David Howells18ac6182018-10-20 00:57:59 +0100272 if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) {
David Howellsc435ee32017-11-02 15:27:49 +0000273 vnode->cb_version = ntohl(*bp++);
274 cb_expiry = ntohl(*bp++);
275 vnode->cb_type = ntohl(*bp++);
276 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
David Howellsd2ddc772017-11-02 15:27:50 +0000277 old = vnode->cb_interest;
278 if (old != call->cbi) {
279 vnode->cb_interest = cbi;
280 cbi = old;
281 }
David Howellsc435ee32017-11-02 15:27:49 +0000282 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
283 } else {
284 bp += 3;
285 }
286
287 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +0000288 call->cbi = cbi;
David Howells08e0e7c2007-04-26 15:55:03 -0700289 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700290}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
David Howells12d8e952018-10-20 00:57:58 +0100292static ktime_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
293{
294 return ktime_add_ns(call->reply_time, expiry * NSEC_PER_SEC);
295}
296
297static void xdr_decode_AFSCallBack_raw(struct afs_call *call,
298 const __be32 **_bp,
David Howells260a9802007-04-26 15:59:35 -0700299 struct afs_callback *cb)
300{
301 const __be32 *bp = *_bp;
302
303 cb->version = ntohl(*bp++);
David Howells12d8e952018-10-20 00:57:58 +0100304 cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++));
David Howells260a9802007-04-26 15:59:35 -0700305 cb->type = ntohl(*bp++);
306 *_bp = bp;
307}
308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309/*
David Howells08e0e7c2007-04-26 15:55:03 -0700310 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 */
David Howells08e0e7c2007-04-26 15:55:03 -0700312static void xdr_decode_AFSVolSync(const __be32 **_bp,
313 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314{
David Howells08e0e7c2007-04-26 15:55:03 -0700315 const __be32 *bp = *_bp;
David Howells30062bd2018-10-20 00:57:58 +0100316 u32 creation;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
David Howells30062bd2018-10-20 00:57:58 +0100318 creation = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -0700319 bp++; /* spare2 */
320 bp++; /* spare3 */
321 bp++; /* spare4 */
322 bp++; /* spare5 */
323 bp++; /* spare6 */
324 *_bp = bp;
David Howells30062bd2018-10-20 00:57:58 +0100325
326 if (volsync)
327 volsync->creation = creation;
David Howellsec268152007-04-26 15:49:28 -0700328}
David Howells08e0e7c2007-04-26 15:55:03 -0700329
330/*
David Howells31143d52007-05-09 02:33:46 -0700331 * encode the requested attributes into an AFSStoreStatus block
332 */
333static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
334{
335 __be32 *bp = *_bp;
336 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
337
338 mask = 0;
339 if (attr->ia_valid & ATTR_MTIME) {
340 mask |= AFS_SET_MTIME;
341 mtime = attr->ia_mtime.tv_sec;
342 }
343
344 if (attr->ia_valid & ATTR_UID) {
345 mask |= AFS_SET_OWNER;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800346 owner = from_kuid(&init_user_ns, attr->ia_uid);
David Howells31143d52007-05-09 02:33:46 -0700347 }
348
349 if (attr->ia_valid & ATTR_GID) {
350 mask |= AFS_SET_GROUP;
Eric W. Biedermana0a53862012-02-07 16:20:48 -0800351 group = from_kgid(&init_user_ns, attr->ia_gid);
David Howells31143d52007-05-09 02:33:46 -0700352 }
353
354 if (attr->ia_valid & ATTR_MODE) {
355 mask |= AFS_SET_MODE;
356 mode = attr->ia_mode & S_IALLUGO;
357 }
358
359 *bp++ = htonl(mask);
360 *bp++ = htonl(mtime);
361 *bp++ = htonl(owner);
362 *bp++ = htonl(group);
363 *bp++ = htonl(mode);
364 *bp++ = 0; /* segment size */
365 *_bp = bp;
366}
367
368/*
David Howells45222b92007-05-10 22:22:20 -0700369 * decode an AFSFetchVolumeStatus block
370 */
371static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
372 struct afs_volume_status *vs)
373{
374 const __be32 *bp = *_bp;
375
376 vs->vid = ntohl(*bp++);
377 vs->parent_id = ntohl(*bp++);
378 vs->online = ntohl(*bp++);
379 vs->in_service = ntohl(*bp++);
380 vs->blessed = ntohl(*bp++);
381 vs->needs_salvage = ntohl(*bp++);
382 vs->type = ntohl(*bp++);
383 vs->min_quota = ntohl(*bp++);
384 vs->max_quota = ntohl(*bp++);
385 vs->blocks_in_use = ntohl(*bp++);
386 vs->part_blocks_avail = ntohl(*bp++);
387 vs->part_max_blocks = ntohl(*bp++);
David Howells30062bd2018-10-20 00:57:58 +0100388 vs->vol_copy_date = 0;
389 vs->vol_backup_date = 0;
David Howells45222b92007-05-10 22:22:20 -0700390 *_bp = bp;
391}
392
393/*
David Howells08e0e7c2007-04-26 15:55:03 -0700394 * deliver reply data to an FS.FetchStatus
395 */
David Howells5cf9dd52018-04-09 21:12:31 +0100396static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
David Howells08e0e7c2007-04-26 15:55:03 -0700397{
David Howells97e30432017-11-02 15:27:48 +0000398 struct afs_vnode *vnode = call->reply[0];
David Howells08e0e7c2007-04-26 15:55:03 -0700399 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100400 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700401
David Howellsd0016482016-08-30 20:42:14 +0100402 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100403 if (ret < 0)
404 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700405
David Howells3b6492d2018-10-20 00:57:57 +0100406 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
David Howellsc435ee32017-11-02 15:27:49 +0000407
David Howells08e0e7c2007-04-26 15:55:03 -0700408 /* unmarshall the reply once we've received all of it */
409 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100410 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
411 &call->expected_version, NULL);
412 if (ret < 0)
413 return ret;
David Howellsc435ee32017-11-02 15:27:49 +0000414 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells30062bd2018-10-20 00:57:58 +0100415 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700416
417 _leave(" = 0 [done]");
418 return 0;
419}
420
421/*
422 * FS.FetchStatus operation type
423 */
David Howells5cf9dd52018-04-09 21:12:31 +0100424static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
425 .name = "FS.FetchStatus(vnode)",
David Howells025db802017-11-02 15:27:51 +0000426 .op = afs_FS_FetchStatus,
David Howells5cf9dd52018-04-09 21:12:31 +0100427 .deliver = afs_deliver_fs_fetch_status_vnode,
David Howells08e0e7c2007-04-26 15:55:03 -0700428 .destructor = afs_flat_call_destructor,
429};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431/*
432 * fetch the status information for a file
433 */
David Howells0c3a5ac2018-04-06 14:17:24 +0100434int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync,
435 bool new_inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
David Howellsd2ddc772017-11-02 15:27:50 +0000437 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700438 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000439 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 __be32 *bp;
441
David Howells30062bd2018-10-20 00:57:58 +0100442 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
443 return yfs_fs_fetch_file_status(fc, volsync, new_inode);
444
David Howells3b6492d2018-10-20 00:57:57 +0100445 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +0000446 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
David Howells5cf9dd52018-04-09 21:12:31 +0100448 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode,
449 16, (21 + 3 + 6) * 4);
David Howellsd2ddc772017-11-02 15:27:50 +0000450 if (!call) {
451 fc->ac.error = -ENOMEM;
David Howells08e0e7c2007-04-26 15:55:03 -0700452 return -ENOMEM;
David Howellsd2ddc772017-11-02 15:27:50 +0000453 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
David Howellsd2ddc772017-11-02 15:27:50 +0000455 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000456 call->reply[0] = vnode;
457 call->reply[1] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +0100458 call->expected_version = new_inode ? 1 : vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100459 call->want_reply_time = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700462 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 bp[0] = htonl(FSFETCHSTATUS);
464 bp[1] = htonl(vnode->fid.vid);
465 bp[2] = htonl(vnode->fid.vnode);
466 bp[3] = htonl(vnode->fid.unique);
467
David Howellsd2ddc772017-11-02 15:27:50 +0000468 call->cb_break = fc->cb_break;
469 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000470 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000471 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700472}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474/*
David Howells08e0e7c2007-04-26 15:55:03 -0700475 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 */
David Howellsd0016482016-08-30 20:42:14 +0100477static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478{
David Howells97e30432017-11-02 15:27:48 +0000479 struct afs_vnode *vnode = call->reply[0];
480 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700481 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000482 unsigned int size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700484
David Howells12bdcf32018-10-20 00:57:56 +0100485 _enter("{%u,%zu/%llu}",
486 call->unmarshall, iov_iter_count(&call->iter), req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700487
488 switch (call->unmarshall) {
489 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000490 req->actual_len = 0;
David Howells12bdcf32018-10-20 00:57:56 +0100491 req->index = 0;
492 req->offset = req->pos & (PAGE_SIZE - 1);
David Howells08e0e7c2007-04-26 15:55:03 -0700493 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +0100494 if (call->operation_ID == FSFETCHDATA64) {
495 afs_extract_to_tmp64(call);
496 } else {
497 call->tmp_u = htonl(0);
498 afs_extract_to_tmp(call);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700499 }
David Howells08e0e7c2007-04-26 15:55:03 -0700500
David Howellsb9b1f8d2007-05-10 03:15:21 -0700501 /* extract the returned data length */
David Howells12bdcf32018-10-20 00:57:56 +0100502 case 1:
David Howells08e0e7c2007-04-26 15:55:03 -0700503 _debug("extract data length");
David Howells12bdcf32018-10-20 00:57:56 +0100504 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +0100505 if (ret < 0)
506 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700507
David Howells12bdcf32018-10-20 00:57:56 +0100508 req->actual_len = be64_to_cpu(call->tmp64);
David Howells196ee9c2017-01-05 10:38:34 +0000509 _debug("DATA length: %llu", req->actual_len);
David Howells12bdcf32018-10-20 00:57:56 +0100510 req->remain = min(req->len, req->actual_len);
511 if (req->remain == 0)
David Howells196ee9c2017-01-05 10:38:34 +0000512 goto no_more_data;
David Howells12bdcf32018-10-20 00:57:56 +0100513
David Howells08e0e7c2007-04-26 15:55:03 -0700514 call->unmarshall++;
515
David Howells196ee9c2017-01-05 10:38:34 +0000516 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000517 ASSERTCMP(req->index, <, req->nr_pages);
David Howells12bdcf32018-10-20 00:57:56 +0100518 if (req->remain > PAGE_SIZE - req->offset)
519 size = PAGE_SIZE - req->offset;
David Howells196ee9c2017-01-05 10:38:34 +0000520 else
521 size = req->remain;
David Howells12bdcf32018-10-20 00:57:56 +0100522 call->bvec[0].bv_len = size;
523 call->bvec[0].bv_offset = req->offset;
524 call->bvec[0].bv_page = req->pages[req->index];
525 iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
526 ASSERTCMP(size, <=, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000527
David Howells08e0e7c2007-04-26 15:55:03 -0700528 /* extract the returned data */
David Howells12bdcf32018-10-20 00:57:56 +0100529 case 2:
530 _debug("extract data %zu/%llu",
531 iov_iter_count(&call->iter), req->remain);
David Howells196ee9c2017-01-05 10:38:34 +0000532
David Howells12bdcf32018-10-20 00:57:56 +0100533 ret = afs_extract_data(call, true);
David Howells196ee9c2017-01-05 10:38:34 +0000534 if (ret < 0)
535 return ret;
David Howells12bdcf32018-10-20 00:57:56 +0100536 req->remain -= call->bvec[0].bv_len;
537 req->offset += call->bvec[0].bv_len;
538 ASSERTCMP(req->offset, <=, PAGE_SIZE);
539 if (req->offset == PAGE_SIZE) {
540 req->offset = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000541 if (req->page_done)
542 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000543 req->index++;
David Howells12bdcf32018-10-20 00:57:56 +0100544 if (req->remain > 0)
David Howells196ee9c2017-01-05 10:38:34 +0000545 goto begin_page;
David Howells08e0e7c2007-04-26 15:55:03 -0700546 }
David Howells12bdcf32018-10-20 00:57:56 +0100547
548 ASSERTCMP(req->remain, ==, 0);
549 if (req->actual_len <= req->len)
550 goto no_more_data;
David Howells6db3ac32017-03-16 16:27:44 +0000551
552 /* Discard any excess data the server gave us */
David Howells12bdcf32018-10-20 00:57:56 +0100553 iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
554 call->unmarshall = 3;
555 case 3:
556 _debug("extract discard %zu/%llu",
557 iov_iter_count(&call->iter), req->actual_len - req->len);
David Howells6db3ac32017-03-16 16:27:44 +0000558
David Howells12bdcf32018-10-20 00:57:56 +0100559 ret = afs_extract_data(call, true);
David Howells6db3ac32017-03-16 16:27:44 +0000560 if (ret < 0)
561 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700562
David Howells196ee9c2017-01-05 10:38:34 +0000563 no_more_data:
David Howells12bdcf32018-10-20 00:57:56 +0100564 call->unmarshall = 4;
565 afs_extract_to_buf(call, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700566
567 /* extract the metadata */
David Howells12bdcf32018-10-20 00:57:56 +0100568 case 4:
569 ret = afs_extract_data(call, false);
David Howells372ee162016-08-03 14:11:40 +0100570 if (ret < 0)
571 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700572
573 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100574 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
575 &vnode->status.data_version, req);
576 if (ret < 0)
577 return ret;
David Howellsc435ee32017-11-02 15:27:49 +0000578 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells30062bd2018-10-20 00:57:58 +0100579 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700580
David Howells08e0e7c2007-04-26 15:55:03 -0700581 call->unmarshall++;
582
David Howells12bdcf32018-10-20 00:57:56 +0100583 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700584 break;
585 }
586
David Howells6db3ac32017-03-16 16:27:44 +0000587 for (; req->index < req->nr_pages; req->index++) {
David Howells12bdcf32018-10-20 00:57:56 +0100588 if (req->offset < PAGE_SIZE)
David Howells6db3ac32017-03-16 16:27:44 +0000589 zero_user_segment(req->pages[req->index],
David Howells12bdcf32018-10-20 00:57:56 +0100590 req->offset, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000591 if (req->page_done)
592 req->page_done(call, req);
David Howells12bdcf32018-10-20 00:57:56 +0100593 req->offset = 0;
David Howells416351f2007-05-09 02:33:45 -0700594 }
595
David Howells08e0e7c2007-04-26 15:55:03 -0700596 _leave(" = 0 [done]");
597 return 0;
598}
599
David Howells196ee9c2017-01-05 10:38:34 +0000600static void afs_fetch_data_destructor(struct afs_call *call)
601{
David Howells97e30432017-11-02 15:27:48 +0000602 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000603
604 afs_put_read(req);
605 afs_flat_call_destructor(call);
606}
607
David Howells08e0e7c2007-04-26 15:55:03 -0700608/*
609 * FS.FetchData operation type
610 */
611static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700612 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000613 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700614 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000615 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700616};
617
David Howellsb9b1f8d2007-05-10 03:15:21 -0700618static const struct afs_call_type afs_RXFSFetchData64 = {
619 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000620 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700621 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000622 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700623};
624
625/*
626 * fetch data from a very large file
627 */
David Howellsd2ddc772017-11-02 15:27:50 +0000628static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700629{
David Howellsd2ddc772017-11-02 15:27:50 +0000630 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700631 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000632 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700633 __be32 *bp;
634
635 _enter("");
636
David Howellsf044c882017-11-02 15:27:45 +0000637 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700638 if (!call)
639 return -ENOMEM;
640
David Howellsd2ddc772017-11-02 15:27:50 +0000641 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000642 call->reply[0] = vnode;
643 call->reply[1] = NULL; /* volsync */
644 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100645 call->expected_version = vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100646 call->want_reply_time = true;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700647
648 /* marshall the parameters */
649 bp = call->request;
650 bp[0] = htonl(FSFETCHDATA64);
651 bp[1] = htonl(vnode->fid.vid);
652 bp[2] = htonl(vnode->fid.vnode);
653 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000654 bp[4] = htonl(upper_32_bits(req->pos));
655 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700656 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000657 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700658
David Howellsf3ddee82018-04-06 14:17:25 +0100659 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000660 call->cb_break = fc->cb_break;
661 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000662 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000663 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700664}
665
David Howells08e0e7c2007-04-26 15:55:03 -0700666/*
667 * fetch data from a file
668 */
David Howellsd2ddc772017-11-02 15:27:50 +0000669int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700670{
David Howellsd2ddc772017-11-02 15:27:50 +0000671 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700672 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000673 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 __be32 *bp;
675
David Howells30062bd2018-10-20 00:57:58 +0100676 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
677 return yfs_fs_fetch_data(fc, req);
678
David Howells196ee9c2017-01-05 10:38:34 +0000679 if (upper_32_bits(req->pos) ||
680 upper_32_bits(req->len) ||
681 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000682 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700683
David Howells08e0e7c2007-04-26 15:55:03 -0700684 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
David Howellsf044c882017-11-02 15:27:45 +0000686 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700687 if (!call)
688 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
David Howellsd2ddc772017-11-02 15:27:50 +0000690 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000691 call->reply[0] = vnode;
692 call->reply[1] = NULL; /* volsync */
693 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100694 call->expected_version = vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100695 call->want_reply_time = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700698 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700700 bp[1] = htonl(vnode->fid.vid);
701 bp[2] = htonl(vnode->fid.vnode);
702 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000703 bp[4] = htonl(lower_32_bits(req->pos));
704 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
David Howellsf3ddee82018-04-06 14:17:25 +0100706 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000707 call->cb_break = fc->cb_break;
708 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000709 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000710 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsec268152007-04-26 15:49:28 -0700711}
David Howells260a9802007-04-26 15:59:35 -0700712
713/*
714 * deliver reply data to an FS.CreateFile or an FS.MakeDir
715 */
David Howellsd0016482016-08-30 20:42:14 +0100716static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700717{
David Howells97e30432017-11-02 15:27:48 +0000718 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700719 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100720 int ret;
David Howells260a9802007-04-26 15:59:35 -0700721
David Howellsd0016482016-08-30 20:42:14 +0100722 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700723
David Howellsd0016482016-08-30 20:42:14 +0100724 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100725 if (ret < 0)
726 return ret;
David Howells260a9802007-04-26 15:59:35 -0700727
728 /* unmarshall the reply once we've received all of it */
729 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000730 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +0100731 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
732 if (ret < 0)
733 return ret;
734 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
735 &call->expected_version, NULL);
736 if (ret < 0)
737 return ret;
David Howells12d8e952018-10-20 00:57:58 +0100738 xdr_decode_AFSCallBack_raw(call, &bp, call->reply[3]);
David Howells97e30432017-11-02 15:27:48 +0000739 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700740
741 _leave(" = 0 [done]");
742 return 0;
743}
744
745/*
746 * FS.CreateFile and FS.MakeDir operation type
747 */
David Howells025db802017-11-02 15:27:51 +0000748static const struct afs_call_type afs_RXFSCreateFile = {
749 .name = "FS.CreateFile",
750 .op = afs_FS_CreateFile,
751 .deliver = afs_deliver_fs_create_vnode,
752 .destructor = afs_flat_call_destructor,
753};
754
755static const struct afs_call_type afs_RXFSMakeDir = {
756 .name = "FS.MakeDir",
757 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700758 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700759 .destructor = afs_flat_call_destructor,
760};
761
762/*
763 * create a file or make a directory
764 */
David Howells8b2a4642017-11-02 15:27:50 +0000765int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700766 const char *name,
767 umode_t mode,
David Howells63a46812018-04-06 14:17:25 +0100768 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -0700769 struct afs_fid *newfid,
770 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000771 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700772{
David Howellsd2ddc772017-11-02 15:27:50 +0000773 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700774 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000775 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700776 size_t namesz, reqsz, padsz;
777 __be32 *bp;
778
David Howells30062bd2018-10-20 00:57:58 +0100779 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){
780 if (S_ISDIR(mode))
781 return yfs_fs_make_dir(fc, name, mode, current_data_version,
782 newfid, newstatus, newcb);
783 else
784 return yfs_fs_create_file(fc, name, mode, current_data_version,
785 newfid, newstatus, newcb);
786 }
787
David Howells260a9802007-04-26 15:59:35 -0700788 _enter("");
789
790 namesz = strlen(name);
791 padsz = (4 - (namesz & 3)) & 3;
792 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
793
David Howells025db802017-11-02 15:27:51 +0000794 call = afs_alloc_flat_call(
795 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
796 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700797 if (!call)
798 return -ENOMEM;
799
David Howellsd2ddc772017-11-02 15:27:50 +0000800 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000801 call->reply[0] = vnode;
802 call->reply[1] = newfid;
803 call->reply[2] = newstatus;
804 call->reply[3] = newcb;
David Howells63a46812018-04-06 14:17:25 +0100805 call->expected_version = current_data_version + 1;
David Howells12d8e952018-10-20 00:57:58 +0100806 call->want_reply_time = true;
David Howells260a9802007-04-26 15:59:35 -0700807
808 /* marshall the parameters */
809 bp = call->request;
810 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
811 *bp++ = htonl(vnode->fid.vid);
812 *bp++ = htonl(vnode->fid.vnode);
813 *bp++ = htonl(vnode->fid.unique);
814 *bp++ = htonl(namesz);
815 memcpy(bp, name, namesz);
816 bp = (void *) bp + namesz;
817 if (padsz > 0) {
818 memset(bp, 0, padsz);
819 bp = (void *) bp + padsz;
820 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000821 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
822 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700823 *bp++ = 0; /* owner */
824 *bp++ = 0; /* group */
825 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
826 *bp++ = 0; /* segment size */
827
David Howellsd2ddc772017-11-02 15:27:50 +0000828 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000829 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000830 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700831}
832
833/*
834 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
835 */
David Howellsd0016482016-08-30 20:42:14 +0100836static int afs_deliver_fs_remove(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700837{
David Howells97e30432017-11-02 15:27:48 +0000838 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700839 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100840 int ret;
David Howells260a9802007-04-26 15:59:35 -0700841
David Howellsd0016482016-08-30 20:42:14 +0100842 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700843
David Howellsd0016482016-08-30 20:42:14 +0100844 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100845 if (ret < 0)
846 return ret;
David Howells260a9802007-04-26 15:59:35 -0700847
848 /* unmarshall the reply once we've received all of it */
849 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100850 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
851 &call->expected_version, NULL);
852 if (ret < 0)
853 return ret;
David Howells97e30432017-11-02 15:27:48 +0000854 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700855
856 _leave(" = 0 [done]");
857 return 0;
858}
859
860/*
861 * FS.RemoveDir/FS.RemoveFile operation type
862 */
David Howells025db802017-11-02 15:27:51 +0000863static const struct afs_call_type afs_RXFSRemoveFile = {
864 .name = "FS.RemoveFile",
865 .op = afs_FS_RemoveFile,
866 .deliver = afs_deliver_fs_remove,
867 .destructor = afs_flat_call_destructor,
868};
869
870static const struct afs_call_type afs_RXFSRemoveDir = {
871 .name = "FS.RemoveDir",
872 .op = afs_FS_RemoveDir,
David Howells260a9802007-04-26 15:59:35 -0700873 .deliver = afs_deliver_fs_remove,
David Howells260a9802007-04-26 15:59:35 -0700874 .destructor = afs_flat_call_destructor,
875};
876
877/*
878 * remove a file or directory
879 */
David Howells30062bd2018-10-20 00:57:58 +0100880int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
881 const char *name, bool isdir, u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700882{
David Howells30062bd2018-10-20 00:57:58 +0100883 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700884 struct afs_call *call;
David Howells30062bd2018-10-20 00:57:58 +0100885 struct afs_net *net = afs_v2net(dvnode);
David Howells260a9802007-04-26 15:59:35 -0700886 size_t namesz, reqsz, padsz;
887 __be32 *bp;
888
David Howells30062bd2018-10-20 00:57:58 +0100889 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
890 return yfs_fs_remove(fc, vnode, name, isdir, current_data_version);
891
David Howells260a9802007-04-26 15:59:35 -0700892 _enter("");
893
894 namesz = strlen(name);
895 padsz = (4 - (namesz & 3)) & 3;
896 reqsz = (5 * 4) + namesz + padsz;
897
David Howells025db802017-11-02 15:27:51 +0000898 call = afs_alloc_flat_call(
899 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
900 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700901 if (!call)
902 return -ENOMEM;
903
David Howellsd2ddc772017-11-02 15:27:50 +0000904 call->key = fc->key;
David Howells30062bd2018-10-20 00:57:58 +0100905 call->reply[0] = dvnode;
906 call->reply[1] = vnode;
David Howells63a46812018-04-06 14:17:25 +0100907 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700908
909 /* marshall the parameters */
910 bp = call->request;
911 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
David Howells30062bd2018-10-20 00:57:58 +0100912 *bp++ = htonl(dvnode->fid.vid);
913 *bp++ = htonl(dvnode->fid.vnode);
914 *bp++ = htonl(dvnode->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700915 *bp++ = htonl(namesz);
916 memcpy(bp, name, namesz);
917 bp = (void *) bp + namesz;
918 if (padsz > 0) {
919 memset(bp, 0, padsz);
920 bp = (void *) bp + padsz;
921 }
922
David Howellsd2ddc772017-11-02 15:27:50 +0000923 afs_use_fs_server(call, fc->cbi);
David Howells30062bd2018-10-20 00:57:58 +0100924 trace_afs_make_fs_call(call, &dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +0000925 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -0700926}
927
928/*
929 * deliver reply data to an FS.Link
930 */
David Howellsd0016482016-08-30 20:42:14 +0100931static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700932{
David Howells97e30432017-11-02 15:27:48 +0000933 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700934 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100935 int ret;
David Howells260a9802007-04-26 15:59:35 -0700936
David Howellsd0016482016-08-30 20:42:14 +0100937 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700938
David Howellsd0016482016-08-30 20:42:14 +0100939 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100940 if (ret < 0)
941 return ret;
David Howells260a9802007-04-26 15:59:35 -0700942
943 /* unmarshall the reply once we've received all of it */
944 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100945 ret = afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
946 if (ret < 0)
947 return ret;
948 ret = afs_decode_status(call, &bp, &dvnode->status, dvnode,
949 &call->expected_version, NULL);
950 if (ret < 0)
951 return ret;
David Howells97e30432017-11-02 15:27:48 +0000952 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700953
954 _leave(" = 0 [done]");
955 return 0;
956}
957
958/*
959 * FS.Link operation type
960 */
961static const struct afs_call_type afs_RXFSLink = {
962 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000963 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700964 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700965 .destructor = afs_flat_call_destructor,
966};
967
968/*
969 * make a hard link
970 */
David Howellsd2ddc772017-11-02 15:27:50 +0000971int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
David Howells63a46812018-04-06 14:17:25 +0100972 const char *name, u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700973{
David Howellsd2ddc772017-11-02 15:27:50 +0000974 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700975 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000976 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700977 size_t namesz, reqsz, padsz;
978 __be32 *bp;
979
David Howells30062bd2018-10-20 00:57:58 +0100980 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
981 return yfs_fs_link(fc, vnode, name, current_data_version);
982
David Howells260a9802007-04-26 15:59:35 -0700983 _enter("");
984
985 namesz = strlen(name);
986 padsz = (4 - (namesz & 3)) & 3;
987 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
988
David Howellsf044c882017-11-02 15:27:45 +0000989 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700990 if (!call)
991 return -ENOMEM;
992
David Howellsd2ddc772017-11-02 15:27:50 +0000993 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000994 call->reply[0] = dvnode;
995 call->reply[1] = vnode;
David Howells63a46812018-04-06 14:17:25 +0100996 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700997
998 /* marshall the parameters */
999 bp = call->request;
1000 *bp++ = htonl(FSLINK);
1001 *bp++ = htonl(dvnode->fid.vid);
1002 *bp++ = htonl(dvnode->fid.vnode);
1003 *bp++ = htonl(dvnode->fid.unique);
1004 *bp++ = htonl(namesz);
1005 memcpy(bp, name, namesz);
1006 bp = (void *) bp + namesz;
1007 if (padsz > 0) {
1008 memset(bp, 0, padsz);
1009 bp = (void *) bp + padsz;
1010 }
1011 *bp++ = htonl(vnode->fid.vid);
1012 *bp++ = htonl(vnode->fid.vnode);
1013 *bp++ = htonl(vnode->fid.unique);
1014
David Howellsd2ddc772017-11-02 15:27:50 +00001015 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001016 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001017 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001018}
1019
1020/*
1021 * deliver reply data to an FS.Symlink
1022 */
David Howellsd0016482016-08-30 20:42:14 +01001023static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001024{
David Howells97e30432017-11-02 15:27:48 +00001025 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -07001026 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001027 int ret;
David Howells260a9802007-04-26 15:59:35 -07001028
David Howellsd0016482016-08-30 20:42:14 +01001029 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001030
David Howellsd0016482016-08-30 20:42:14 +01001031 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001032 if (ret < 0)
1033 return ret;
David Howells260a9802007-04-26 15:59:35 -07001034
1035 /* unmarshall the reply once we've received all of it */
1036 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001037 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +01001038 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
1039 if (ret < 0)
1040 return ret;
1041 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1042 &call->expected_version, NULL);
1043 if (ret < 0)
1044 return ret;
David Howells97e30432017-11-02 15:27:48 +00001045 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001046
1047 _leave(" = 0 [done]");
1048 return 0;
1049}
1050
1051/*
1052 * FS.Symlink operation type
1053 */
1054static const struct afs_call_type afs_RXFSSymlink = {
1055 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +00001056 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -07001057 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -07001058 .destructor = afs_flat_call_destructor,
1059};
1060
1061/*
1062 * create a symbolic link
1063 */
David Howells8b2a4642017-11-02 15:27:50 +00001064int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001065 const char *name,
1066 const char *contents,
David Howells63a46812018-04-06 14:17:25 +01001067 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -07001068 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +00001069 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -07001070{
David Howellsd2ddc772017-11-02 15:27:50 +00001071 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001072 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001073 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -07001074 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
1075 __be32 *bp;
1076
David Howells30062bd2018-10-20 00:57:58 +01001077 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1078 return yfs_fs_symlink(fc, name, contents, current_data_version,
1079 newfid, newstatus);
1080
David Howells260a9802007-04-26 15:59:35 -07001081 _enter("");
1082
1083 namesz = strlen(name);
1084 padsz = (4 - (namesz & 3)) & 3;
1085
1086 c_namesz = strlen(contents);
1087 c_padsz = (4 - (c_namesz & 3)) & 3;
1088
1089 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
1090
David Howellsf044c882017-11-02 15:27:45 +00001091 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -07001092 (3 + 21 + 21 + 6) * 4);
1093 if (!call)
1094 return -ENOMEM;
1095
David Howellsd2ddc772017-11-02 15:27:50 +00001096 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001097 call->reply[0] = vnode;
1098 call->reply[1] = newfid;
1099 call->reply[2] = newstatus;
David Howells63a46812018-04-06 14:17:25 +01001100 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001101
1102 /* marshall the parameters */
1103 bp = call->request;
1104 *bp++ = htonl(FSSYMLINK);
1105 *bp++ = htonl(vnode->fid.vid);
1106 *bp++ = htonl(vnode->fid.vnode);
1107 *bp++ = htonl(vnode->fid.unique);
1108 *bp++ = htonl(namesz);
1109 memcpy(bp, name, namesz);
1110 bp = (void *) bp + namesz;
1111 if (padsz > 0) {
1112 memset(bp, 0, padsz);
1113 bp = (void *) bp + padsz;
1114 }
1115 *bp++ = htonl(c_namesz);
1116 memcpy(bp, contents, c_namesz);
1117 bp = (void *) bp + c_namesz;
1118 if (c_padsz > 0) {
1119 memset(bp, 0, c_padsz);
1120 bp = (void *) bp + c_padsz;
1121 }
Marc Dionneab94f5d2017-03-16 16:27:47 +00001122 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
1123 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -07001124 *bp++ = 0; /* owner */
1125 *bp++ = 0; /* group */
1126 *bp++ = htonl(S_IRWXUGO); /* unix mode */
1127 *bp++ = 0; /* segment size */
1128
David Howellsd2ddc772017-11-02 15:27:50 +00001129 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001130 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001131 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001132}
1133
1134/*
1135 * deliver reply data to an FS.Rename
1136 */
David Howellsd0016482016-08-30 20:42:14 +01001137static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001138{
David Howells97e30432017-11-02 15:27:48 +00001139 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -07001140 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001141 int ret;
David Howells260a9802007-04-26 15:59:35 -07001142
David Howellsd0016482016-08-30 20:42:14 +01001143 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001144
David Howellsd0016482016-08-30 20:42:14 +01001145 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001146 if (ret < 0)
1147 return ret;
David Howells260a9802007-04-26 15:59:35 -07001148
1149 /* unmarshall the reply once we've received all of it */
1150 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001151 ret = afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
1152 &call->expected_version, NULL);
1153 if (ret < 0)
1154 return ret;
1155 if (new_dvnode != orig_dvnode) {
1156 ret = afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
1157 &call->expected_version_2, NULL);
1158 if (ret < 0)
1159 return ret;
1160 }
David Howells97e30432017-11-02 15:27:48 +00001161 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001162
1163 _leave(" = 0 [done]");
1164 return 0;
1165}
1166
1167/*
1168 * FS.Rename operation type
1169 */
1170static const struct afs_call_type afs_RXFSRename = {
1171 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001172 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001173 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001174 .destructor = afs_flat_call_destructor,
1175};
1176
1177/*
1178 * create a symbolic link
1179 */
David Howells8b2a4642017-11-02 15:27:50 +00001180int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001181 const char *orig_name,
1182 struct afs_vnode *new_dvnode,
David Howells63a46812018-04-06 14:17:25 +01001183 const char *new_name,
1184 u64 current_orig_data_version,
1185 u64 current_new_data_version)
David Howells260a9802007-04-26 15:59:35 -07001186{
David Howellsd2ddc772017-11-02 15:27:50 +00001187 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001188 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001189 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001190 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1191 __be32 *bp;
1192
David Howells30062bd2018-10-20 00:57:58 +01001193 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1194 return yfs_fs_rename(fc, orig_name,
1195 new_dvnode, new_name,
1196 current_orig_data_version,
1197 current_new_data_version);
1198
David Howells260a9802007-04-26 15:59:35 -07001199 _enter("");
1200
1201 o_namesz = strlen(orig_name);
1202 o_padsz = (4 - (o_namesz & 3)) & 3;
1203
1204 n_namesz = strlen(new_name);
1205 n_padsz = (4 - (n_namesz & 3)) & 3;
1206
1207 reqsz = (4 * 4) +
1208 4 + o_namesz + o_padsz +
1209 (3 * 4) +
1210 4 + n_namesz + n_padsz;
1211
David Howellsf044c882017-11-02 15:27:45 +00001212 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001213 if (!call)
1214 return -ENOMEM;
1215
David Howellsd2ddc772017-11-02 15:27:50 +00001216 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001217 call->reply[0] = orig_dvnode;
1218 call->reply[1] = new_dvnode;
David Howells63a46812018-04-06 14:17:25 +01001219 call->expected_version = current_orig_data_version + 1;
1220 call->expected_version_2 = current_new_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001221
1222 /* marshall the parameters */
1223 bp = call->request;
1224 *bp++ = htonl(FSRENAME);
1225 *bp++ = htonl(orig_dvnode->fid.vid);
1226 *bp++ = htonl(orig_dvnode->fid.vnode);
1227 *bp++ = htonl(orig_dvnode->fid.unique);
1228 *bp++ = htonl(o_namesz);
1229 memcpy(bp, orig_name, o_namesz);
1230 bp = (void *) bp + o_namesz;
1231 if (o_padsz > 0) {
1232 memset(bp, 0, o_padsz);
1233 bp = (void *) bp + o_padsz;
1234 }
1235
1236 *bp++ = htonl(new_dvnode->fid.vid);
1237 *bp++ = htonl(new_dvnode->fid.vnode);
1238 *bp++ = htonl(new_dvnode->fid.unique);
1239 *bp++ = htonl(n_namesz);
1240 memcpy(bp, new_name, n_namesz);
1241 bp = (void *) bp + n_namesz;
1242 if (n_padsz > 0) {
1243 memset(bp, 0, n_padsz);
1244 bp = (void *) bp + n_padsz;
1245 }
1246
David Howellsd2ddc772017-11-02 15:27:50 +00001247 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001248 trace_afs_make_fs_call(call, &orig_dvnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001249 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells260a9802007-04-26 15:59:35 -07001250}
David Howells31143d52007-05-09 02:33:46 -07001251
1252/*
1253 * deliver reply data to an FS.StoreData
1254 */
David Howellsd0016482016-08-30 20:42:14 +01001255static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001256{
David Howells97e30432017-11-02 15:27:48 +00001257 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001258 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001259 int ret;
David Howells31143d52007-05-09 02:33:46 -07001260
David Howellsd0016482016-08-30 20:42:14 +01001261 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001262
David Howellsd0016482016-08-30 20:42:14 +01001263 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001264 if (ret < 0)
1265 return ret;
David Howells31143d52007-05-09 02:33:46 -07001266
1267 /* unmarshall the reply once we've received all of it */
1268 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001269 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1270 &call->expected_version, NULL);
1271 if (ret < 0)
1272 return ret;
David Howells97e30432017-11-02 15:27:48 +00001273 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001274
1275 afs_pages_written_back(vnode, call);
1276
1277 _leave(" = 0 [done]");
1278 return 0;
1279}
1280
1281/*
1282 * FS.StoreData operation type
1283 */
1284static const struct afs_call_type afs_RXFSStoreData = {
1285 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001286 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001287 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001288 .destructor = afs_flat_call_destructor,
1289};
1290
David Howellsb9b1f8d2007-05-10 03:15:21 -07001291static const struct afs_call_type afs_RXFSStoreData64 = {
1292 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001293 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001294 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001295 .destructor = afs_flat_call_destructor,
1296};
1297
1298/*
1299 * store a set of pages to a very large file
1300 */
David Howells8b2a4642017-11-02 15:27:50 +00001301static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001302 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001303 pgoff_t first, pgoff_t last,
1304 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001305 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001306{
David Howells4343d002017-11-02 15:27:52 +00001307 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001308 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001309 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001310 __be32 *bp;
1311
David Howells3b6492d2018-10-20 00:57:57 +01001312 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001313 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001314
David Howellsf044c882017-11-02 15:27:45 +00001315 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001316 (4 + 6 + 3 * 2) * 4,
1317 (21 + 6) * 4);
1318 if (!call)
1319 return -ENOMEM;
1320
David Howells4343d002017-11-02 15:27:52 +00001321 call->key = fc->key;
1322 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001323 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001324 call->first = first;
1325 call->last = last;
1326 call->first_offset = offset;
1327 call->last_to = to;
1328 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001329 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001330
1331 /* marshall the parameters */
1332 bp = call->request;
1333 *bp++ = htonl(FSSTOREDATA64);
1334 *bp++ = htonl(vnode->fid.vid);
1335 *bp++ = htonl(vnode->fid.vnode);
1336 *bp++ = htonl(vnode->fid.unique);
1337
Marc Dionneab94f5d2017-03-16 16:27:47 +00001338 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1339 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001340 *bp++ = 0; /* owner */
1341 *bp++ = 0; /* group */
1342 *bp++ = 0; /* unix mode */
1343 *bp++ = 0; /* segment size */
1344
1345 *bp++ = htonl(pos >> 32);
1346 *bp++ = htonl((u32) pos);
1347 *bp++ = htonl(size >> 32);
1348 *bp++ = htonl((u32) size);
1349 *bp++ = htonl(i_size >> 32);
1350 *bp++ = htonl((u32) i_size);
1351
David Howells025db802017-11-02 15:27:51 +00001352 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001353 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001354}
1355
David Howells31143d52007-05-09 02:33:46 -07001356/*
1357 * store a set of pages
1358 */
David Howells4343d002017-11-02 15:27:52 +00001359int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001360 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001361 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001362{
David Howells4343d002017-11-02 15:27:52 +00001363 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001364 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001365 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001366 loff_t size, pos, i_size;
1367 __be32 *bp;
1368
David Howells30062bd2018-10-20 00:57:58 +01001369 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1370 return yfs_fs_store_data(fc, mapping, first, last, offset, to);
1371
David Howells3b6492d2018-10-20 00:57:57 +01001372 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001373 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001374
David Howells146a1192017-03-16 16:27:47 +00001375 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001376 if (first != last)
1377 size += (loff_t)(last - first) << PAGE_SHIFT;
1378 pos = (loff_t)first << PAGE_SHIFT;
1379 pos += offset;
1380
1381 i_size = i_size_read(&vnode->vfs_inode);
1382 if (pos + size > i_size)
1383 i_size = size + pos;
1384
1385 _debug("size %llx, at %llx, i_size %llx",
1386 (unsigned long long) size, (unsigned long long) pos,
1387 (unsigned long long) i_size);
1388
David Howellsb9b1f8d2007-05-10 03:15:21 -07001389 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001390 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001391 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001392
David Howellsf044c882017-11-02 15:27:45 +00001393 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001394 (4 + 6 + 3) * 4,
1395 (21 + 6) * 4);
1396 if (!call)
1397 return -ENOMEM;
1398
David Howells4343d002017-11-02 15:27:52 +00001399 call->key = fc->key;
1400 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001401 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001402 call->first = first;
1403 call->last = last;
1404 call->first_offset = offset;
1405 call->last_to = to;
1406 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001407 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001408
1409 /* marshall the parameters */
1410 bp = call->request;
1411 *bp++ = htonl(FSSTOREDATA);
1412 *bp++ = htonl(vnode->fid.vid);
1413 *bp++ = htonl(vnode->fid.vnode);
1414 *bp++ = htonl(vnode->fid.unique);
1415
Marc Dionneab94f5d2017-03-16 16:27:47 +00001416 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1417 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001418 *bp++ = 0; /* owner */
1419 *bp++ = 0; /* group */
1420 *bp++ = 0; /* unix mode */
1421 *bp++ = 0; /* segment size */
1422
1423 *bp++ = htonl(pos);
1424 *bp++ = htonl(size);
1425 *bp++ = htonl(i_size);
1426
David Howellsd2ddc772017-11-02 15:27:50 +00001427 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001428 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001429 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001430}
1431
1432/*
1433 * deliver reply data to an FS.StoreStatus
1434 */
David Howellsd0016482016-08-30 20:42:14 +01001435static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001436{
David Howells97e30432017-11-02 15:27:48 +00001437 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001438 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001439 int ret;
David Howells31143d52007-05-09 02:33:46 -07001440
David Howellsd0016482016-08-30 20:42:14 +01001441 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001442
David Howellsd0016482016-08-30 20:42:14 +01001443 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001444 if (ret < 0)
1445 return ret;
David Howells31143d52007-05-09 02:33:46 -07001446
1447 /* unmarshall the reply once we've received all of it */
David Howells31143d52007-05-09 02:33:46 -07001448 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001449 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1450 &call->expected_version, NULL);
1451 if (ret < 0)
1452 return ret;
David Howells97e30432017-11-02 15:27:48 +00001453 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001454
1455 _leave(" = 0 [done]");
1456 return 0;
1457}
1458
1459/*
1460 * FS.StoreStatus operation type
1461 */
1462static const struct afs_call_type afs_RXFSStoreStatus = {
1463 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001464 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001465 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001466 .destructor = afs_flat_call_destructor,
1467};
1468
1469static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1470 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001471 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001472 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001473 .destructor = afs_flat_call_destructor,
1474};
1475
David Howellsb9b1f8d2007-05-10 03:15:21 -07001476static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1477 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001478 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001479 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001480 .destructor = afs_flat_call_destructor,
1481};
1482
1483/*
1484 * set the attributes on a very large file, using FS.StoreData rather than
1485 * FS.StoreStatus so as to alter the file size also
1486 */
David Howellsd2ddc772017-11-02 15:27:50 +00001487static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001488{
David Howellsd2ddc772017-11-02 15:27:50 +00001489 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001490 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001491 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001492 __be32 *bp;
1493
David Howells3b6492d2018-10-20 00:57:57 +01001494 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001495 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001496
1497 ASSERT(attr->ia_valid & ATTR_SIZE);
1498
David Howellsf044c882017-11-02 15:27:45 +00001499 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001500 (4 + 6 + 3 * 2) * 4,
1501 (21 + 6) * 4);
1502 if (!call)
1503 return -ENOMEM;
1504
David Howellsd2ddc772017-11-02 15:27:50 +00001505 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001506 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001507 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001508
1509 /* marshall the parameters */
1510 bp = call->request;
1511 *bp++ = htonl(FSSTOREDATA64);
1512 *bp++ = htonl(vnode->fid.vid);
1513 *bp++ = htonl(vnode->fid.vnode);
1514 *bp++ = htonl(vnode->fid.unique);
1515
1516 xdr_encode_AFS_StoreStatus(&bp, attr);
1517
David Howells8c7ae382019-03-27 22:48:02 +00001518 *bp++ = htonl(attr->ia_size >> 32); /* position of start of write */
1519 *bp++ = htonl((u32) attr->ia_size);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001520 *bp++ = 0; /* size of write */
1521 *bp++ = 0;
1522 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1523 *bp++ = htonl((u32) attr->ia_size);
1524
David Howellsd2ddc772017-11-02 15:27:50 +00001525 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001526 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001527 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001528}
1529
David Howells31143d52007-05-09 02:33:46 -07001530/*
1531 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1532 * so as to alter the file size also
1533 */
David Howellsd2ddc772017-11-02 15:27:50 +00001534static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001535{
David Howellsd2ddc772017-11-02 15:27:50 +00001536 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001537 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001538 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001539 __be32 *bp;
1540
David Howells3b6492d2018-10-20 00:57:57 +01001541 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001542 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001543
1544 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001545 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001546 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001547
David Howellsf044c882017-11-02 15:27:45 +00001548 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001549 (4 + 6 + 3) * 4,
1550 (21 + 6) * 4);
1551 if (!call)
1552 return -ENOMEM;
1553
David Howellsd2ddc772017-11-02 15:27:50 +00001554 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001555 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001556 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001557
1558 /* marshall the parameters */
1559 bp = call->request;
1560 *bp++ = htonl(FSSTOREDATA);
1561 *bp++ = htonl(vnode->fid.vid);
1562 *bp++ = htonl(vnode->fid.vnode);
1563 *bp++ = htonl(vnode->fid.unique);
1564
1565 xdr_encode_AFS_StoreStatus(&bp, attr);
1566
David Howells8c7ae382019-03-27 22:48:02 +00001567 *bp++ = htonl(attr->ia_size); /* position of start of write */
David Howells31143d52007-05-09 02:33:46 -07001568 *bp++ = 0; /* size of write */
1569 *bp++ = htonl(attr->ia_size); /* new file length */
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}
1575
1576/*
1577 * set the attributes on a file, using FS.StoreData if there's a change in file
1578 * size, and FS.StoreStatus otherwise
1579 */
David Howellsd2ddc772017-11-02 15:27:50 +00001580int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001581{
David Howellsd2ddc772017-11-02 15:27:50 +00001582 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001583 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001584 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001585 __be32 *bp;
1586
David Howells30062bd2018-10-20 00:57:58 +01001587 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1588 return yfs_fs_setattr(fc, attr);
1589
David Howells31143d52007-05-09 02:33:46 -07001590 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001591 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001592
David Howells3b6492d2018-10-20 00:57:57 +01001593 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001594 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001595
David Howellsf044c882017-11-02 15:27:45 +00001596 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001597 (4 + 6) * 4,
1598 (21 + 6) * 4);
1599 if (!call)
1600 return -ENOMEM;
1601
David Howellsd2ddc772017-11-02 15:27:50 +00001602 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001603 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001604 call->expected_version = vnode->status.data_version;
David Howells31143d52007-05-09 02:33:46 -07001605
1606 /* marshall the parameters */
1607 bp = call->request;
1608 *bp++ = htonl(FSSTORESTATUS);
1609 *bp++ = htonl(vnode->fid.vid);
1610 *bp++ = htonl(vnode->fid.vnode);
1611 *bp++ = htonl(vnode->fid.unique);
1612
1613 xdr_encode_AFS_StoreStatus(&bp, attr);
1614
David Howellsd2ddc772017-11-02 15:27:50 +00001615 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001616 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001617 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells31143d52007-05-09 02:33:46 -07001618}
David Howells45222b92007-05-10 22:22:20 -07001619
1620/*
1621 * deliver reply data to an FS.GetVolumeStatus
1622 */
David Howellsd0016482016-08-30 20:42:14 +01001623static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001624{
1625 const __be32 *bp;
1626 char *p;
David Howells12bdcf32018-10-20 00:57:56 +01001627 u32 size;
David Howells45222b92007-05-10 22:22:20 -07001628 int ret;
1629
David Howellsd0016482016-08-30 20:42:14 +01001630 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001631
1632 switch (call->unmarshall) {
1633 case 0:
David Howells45222b92007-05-10 22:22:20 -07001634 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001635 afs_extract_to_buf(call, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001636
1637 /* extract the returned status record */
1638 case 1:
1639 _debug("extract status");
David Howells12bdcf32018-10-20 00:57:56 +01001640 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001641 if (ret < 0)
1642 return ret;
David Howells45222b92007-05-10 22:22:20 -07001643
1644 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001645 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001646 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001647 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001648
1649 /* extract the volume name length */
1650 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001651 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001652 if (ret < 0)
1653 return ret;
David Howells45222b92007-05-10 22:22:20 -07001654
1655 call->count = ntohl(call->tmp);
1656 _debug("volname length: %u", call->count);
1657 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001658 return afs_protocol_error(call, -EBADMSG,
1659 afs_eproto_volname_len);
David Howells12bdcf32018-10-20 00:57:56 +01001660 size = (call->count + 3) & ~3; /* It's padded */
1661 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001662 call->unmarshall++;
1663
1664 /* extract the volume name */
1665 case 3:
1666 _debug("extract volname");
David Howells12bdcf32018-10-20 00:57:56 +01001667 ret = afs_extract_data(call, true);
1668 if (ret < 0)
1669 return ret;
David Howells45222b92007-05-10 22:22:20 -07001670
David Howells97e30432017-11-02 15:27:48 +00001671 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001672 p[call->count] = 0;
1673 _debug("volname '%s'", p);
David Howells12bdcf32018-10-20 00:57:56 +01001674 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001675 call->unmarshall++;
1676
David Howells45222b92007-05-10 22:22:20 -07001677 /* extract the offline message length */
David Howells12bdcf32018-10-20 00:57:56 +01001678 case 4:
1679 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001680 if (ret < 0)
1681 return ret;
David Howells45222b92007-05-10 22:22:20 -07001682
1683 call->count = ntohl(call->tmp);
1684 _debug("offline msg length: %u", call->count);
1685 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001686 return afs_protocol_error(call, -EBADMSG,
1687 afs_eproto_offline_msg_len);
David Howells12bdcf32018-10-20 00:57:56 +01001688 size = (call->count + 3) & ~3; /* It's padded */
1689 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001690 call->unmarshall++;
1691
1692 /* extract the offline message */
David Howells12bdcf32018-10-20 00:57:56 +01001693 case 5:
David Howells45222b92007-05-10 22:22:20 -07001694 _debug("extract offline");
David Howells12bdcf32018-10-20 00:57:56 +01001695 ret = afs_extract_data(call, true);
1696 if (ret < 0)
1697 return ret;
David Howells45222b92007-05-10 22:22:20 -07001698
David Howells97e30432017-11-02 15:27:48 +00001699 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001700 p[call->count] = 0;
1701 _debug("offline '%s'", p);
1702
David Howells12bdcf32018-10-20 00:57:56 +01001703 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001704 call->unmarshall++;
1705
David Howells45222b92007-05-10 22:22:20 -07001706 /* extract the message of the day length */
David Howells12bdcf32018-10-20 00:57:56 +01001707 case 6:
1708 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001709 if (ret < 0)
1710 return ret;
David Howells45222b92007-05-10 22:22:20 -07001711
1712 call->count = ntohl(call->tmp);
1713 _debug("motd length: %u", call->count);
1714 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001715 return afs_protocol_error(call, -EBADMSG,
1716 afs_eproto_motd_len);
David Howells12bdcf32018-10-20 00:57:56 +01001717 size = (call->count + 3) & ~3; /* It's padded */
1718 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001719 call->unmarshall++;
1720
1721 /* extract the message of the day */
David Howells12bdcf32018-10-20 00:57:56 +01001722 case 7:
David Howells45222b92007-05-10 22:22:20 -07001723 _debug("extract motd");
David Howells12bdcf32018-10-20 00:57:56 +01001724 ret = afs_extract_data(call, false);
1725 if (ret < 0)
1726 return ret;
David Howells45222b92007-05-10 22:22:20 -07001727
David Howells97e30432017-11-02 15:27:48 +00001728 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001729 p[call->count] = 0;
1730 _debug("motd '%s'", p);
1731
David Howells45222b92007-05-10 22:22:20 -07001732 call->unmarshall++;
1733
David Howells12bdcf32018-10-20 00:57:56 +01001734 case 8:
David Howells45222b92007-05-10 22:22:20 -07001735 break;
1736 }
1737
David Howells45222b92007-05-10 22:22:20 -07001738 _leave(" = 0 [done]");
1739 return 0;
1740}
1741
1742/*
1743 * destroy an FS.GetVolumeStatus call
1744 */
1745static void afs_get_volume_status_call_destructor(struct afs_call *call)
1746{
David Howells97e30432017-11-02 15:27:48 +00001747 kfree(call->reply[2]);
1748 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001749 afs_flat_call_destructor(call);
1750}
1751
1752/*
1753 * FS.GetVolumeStatus operation type
1754 */
1755static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1756 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001757 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001758 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001759 .destructor = afs_get_volume_status_call_destructor,
1760};
1761
1762/*
1763 * fetch the status of a volume
1764 */
David Howells8b2a4642017-11-02 15:27:50 +00001765int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001766 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001767{
David Howellsd2ddc772017-11-02 15:27:50 +00001768 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001769 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001770 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001771 __be32 *bp;
1772 void *tmpbuf;
1773
David Howells30062bd2018-10-20 00:57:58 +01001774 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1775 return yfs_fs_get_volume_status(fc, vs);
1776
David Howells45222b92007-05-10 22:22:20 -07001777 _enter("");
1778
1779 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1780 if (!tmpbuf)
1781 return -ENOMEM;
1782
David Howellsf044c882017-11-02 15:27:45 +00001783 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001784 if (!call) {
1785 kfree(tmpbuf);
1786 return -ENOMEM;
1787 }
1788
David Howellsd2ddc772017-11-02 15:27:50 +00001789 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001790 call->reply[0] = vnode;
1791 call->reply[1] = vs;
1792 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001793
1794 /* marshall the parameters */
1795 bp = call->request;
1796 bp[0] = htonl(FSGETVOLUMESTATUS);
1797 bp[1] = htonl(vnode->fid.vid);
1798
David Howellsd2ddc772017-11-02 15:27:50 +00001799 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001800 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001801 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howells45222b92007-05-10 22:22:20 -07001802}
David Howellse8d6c552007-07-15 23:40:12 -07001803
1804/*
1805 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1806 */
David Howellsd0016482016-08-30 20:42:14 +01001807static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001808{
1809 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001810 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001811
David Howellsd0016482016-08-30 20:42:14 +01001812 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001813
David Howellsd0016482016-08-30 20:42:14 +01001814 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001815 if (ret < 0)
1816 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001817
1818 /* unmarshall the reply once we've received all of it */
1819 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001820 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001821
1822 _leave(" = 0 [done]");
1823 return 0;
1824}
1825
1826/*
1827 * FS.SetLock operation type
1828 */
1829static const struct afs_call_type afs_RXFSSetLock = {
1830 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001831 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001832 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001833 .destructor = afs_flat_call_destructor,
1834};
1835
1836/*
1837 * FS.ExtendLock operation type
1838 */
1839static const struct afs_call_type afs_RXFSExtendLock = {
1840 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001841 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001842 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001843 .destructor = afs_flat_call_destructor,
1844};
1845
1846/*
1847 * FS.ReleaseLock operation type
1848 */
1849static const struct afs_call_type afs_RXFSReleaseLock = {
1850 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001851 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001852 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001853 .destructor = afs_flat_call_destructor,
1854};
1855
1856/*
David Howellsd2ddc772017-11-02 15:27:50 +00001857 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001858 */
David Howellsd2ddc772017-11-02 15:27:50 +00001859int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001860{
David Howellsd2ddc772017-11-02 15:27:50 +00001861 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001862 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001863 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001864 __be32 *bp;
1865
David Howells30062bd2018-10-20 00:57:58 +01001866 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1867 return yfs_fs_set_lock(fc, type);
1868
David Howellse8d6c552007-07-15 23:40:12 -07001869 _enter("");
1870
David Howellsf044c882017-11-02 15:27:45 +00001871 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001872 if (!call)
1873 return -ENOMEM;
1874
David Howellsd2ddc772017-11-02 15:27:50 +00001875 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001876 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001877
1878 /* marshall the parameters */
1879 bp = call->request;
1880 *bp++ = htonl(FSSETLOCK);
1881 *bp++ = htonl(vnode->fid.vid);
1882 *bp++ = htonl(vnode->fid.vnode);
1883 *bp++ = htonl(vnode->fid.unique);
1884 *bp++ = htonl(type);
1885
David Howellsd2ddc772017-11-02 15:27:50 +00001886 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001887 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001888 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001889}
1890
1891/*
1892 * extend a lock on a file
1893 */
David Howellsd2ddc772017-11-02 15:27:50 +00001894int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001895{
David Howellsd2ddc772017-11-02 15:27:50 +00001896 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001897 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001898 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001899 __be32 *bp;
1900
David Howells30062bd2018-10-20 00:57:58 +01001901 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1902 return yfs_fs_extend_lock(fc);
1903
David Howellse8d6c552007-07-15 23:40:12 -07001904 _enter("");
1905
David Howellsf044c882017-11-02 15:27:45 +00001906 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001907 if (!call)
1908 return -ENOMEM;
1909
David Howellsd2ddc772017-11-02 15:27:50 +00001910 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001911 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001912
1913 /* marshall the parameters */
1914 bp = call->request;
1915 *bp++ = htonl(FSEXTENDLOCK);
1916 *bp++ = htonl(vnode->fid.vid);
1917 *bp++ = htonl(vnode->fid.vnode);
1918 *bp++ = htonl(vnode->fid.unique);
1919
David Howellsd2ddc772017-11-02 15:27:50 +00001920 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001921 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001922 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellse8d6c552007-07-15 23:40:12 -07001923}
1924
1925/*
1926 * release a lock on a file
1927 */
David Howellsd2ddc772017-11-02 15:27:50 +00001928int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001929{
David Howellsd2ddc772017-11-02 15:27:50 +00001930 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001931 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001932 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001933 __be32 *bp;
1934
David Howells30062bd2018-10-20 00:57:58 +01001935 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1936 return yfs_fs_release_lock(fc);
1937
David Howellse8d6c552007-07-15 23:40:12 -07001938 _enter("");
1939
David Howellsf044c882017-11-02 15:27:45 +00001940 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001941 if (!call)
1942 return -ENOMEM;
1943
David Howellsd2ddc772017-11-02 15:27:50 +00001944 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001945 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001946
1947 /* marshall the parameters */
1948 bp = call->request;
1949 *bp++ = htonl(FSRELEASELOCK);
1950 *bp++ = htonl(vnode->fid.vid);
1951 *bp++ = htonl(vnode->fid.vnode);
1952 *bp++ = htonl(vnode->fid.unique);
1953
David Howellsd2ddc772017-11-02 15:27:50 +00001954 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001955 trace_afs_make_fs_call(call, &vnode->fid);
David Howellsd2ddc772017-11-02 15:27:50 +00001956 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
David Howellsc435ee32017-11-02 15:27:49 +00001957}
1958
1959/*
1960 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1961 */
1962static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1963{
1964 return afs_transfer_reply(call);
1965}
1966
1967/*
1968 * FS.GiveUpAllCallBacks operation type
1969 */
1970static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1971 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001972 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001973 .deliver = afs_deliver_fs_give_up_all_callbacks,
1974 .destructor = afs_flat_call_destructor,
1975};
1976
1977/*
1978 * Flush all the callbacks we have on a server.
1979 */
David Howellsd2ddc772017-11-02 15:27:50 +00001980int afs_fs_give_up_all_callbacks(struct afs_net *net,
1981 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00001982 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00001983 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00001984{
1985 struct afs_call *call;
1986 __be32 *bp;
1987
1988 _enter("");
1989
David Howellsd2ddc772017-11-02 15:27:50 +00001990 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00001991 if (!call)
1992 return -ENOMEM;
1993
1994 call->key = key;
1995
1996 /* marshall the parameters */
1997 bp = call->request;
1998 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1999
2000 /* Can't take a ref on server */
David Howellsd2ddc772017-11-02 15:27:50 +00002001 return afs_make_call(ac, call, GFP_NOFS, false);
2002}
2003
2004/*
2005 * Deliver reply data to an FS.GetCapabilities operation.
2006 */
2007static int afs_deliver_fs_get_capabilities(struct afs_call *call)
2008{
2009 u32 count;
2010 int ret;
2011
David Howells12bdcf32018-10-20 00:57:56 +01002012 _enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter));
David Howellsd2ddc772017-11-02 15:27:50 +00002013
David Howellsd2ddc772017-11-02 15:27:50 +00002014 switch (call->unmarshall) {
2015 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01002016 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00002017 call->unmarshall++;
2018
2019 /* Extract the capabilities word count */
2020 case 1:
David Howells12bdcf32018-10-20 00:57:56 +01002021 ret = afs_extract_data(call, true);
David Howellsd2ddc772017-11-02 15:27:50 +00002022 if (ret < 0)
2023 return ret;
2024
2025 count = ntohl(call->tmp);
2026
2027 call->count = count;
2028 call->count2 = count;
David Howells12bdcf32018-10-20 00:57:56 +01002029 iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
David Howellsd2ddc772017-11-02 15:27:50 +00002030 call->unmarshall++;
2031
2032 /* Extract capabilities words */
2033 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01002034 ret = afs_extract_data(call, false);
David Howellsd2ddc772017-11-02 15:27:50 +00002035 if (ret < 0)
2036 return ret;
2037
2038 /* TODO: Examine capabilities */
2039
David Howellsd2ddc772017-11-02 15:27:50 +00002040 call->unmarshall++;
2041 break;
2042 }
2043
2044 _leave(" = 0 [done]");
2045 return 0;
2046}
2047
David Howells3bf0fb62018-10-20 00:57:59 +01002048static void afs_destroy_fs_get_capabilities(struct afs_call *call)
2049{
2050 struct afs_server *server = call->reply[0];
2051
2052 afs_put_server(call->net, server);
2053 afs_flat_call_destructor(call);
2054}
2055
David Howellsd2ddc772017-11-02 15:27:50 +00002056/*
2057 * FS.GetCapabilities operation type
2058 */
2059static const struct afs_call_type afs_RXFSGetCapabilities = {
2060 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00002061 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00002062 .deliver = afs_deliver_fs_get_capabilities,
David Howells3bf0fb62018-10-20 00:57:59 +01002063 .done = afs_fileserver_probe_result,
2064 .destructor = afs_destroy_fs_get_capabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00002065};
2066
2067/*
2068 * Probe a fileserver for the capabilities that it supports. This can
2069 * return up to 196 words.
2070 */
2071int afs_fs_get_capabilities(struct afs_net *net,
2072 struct afs_server *server,
2073 struct afs_addr_cursor *ac,
David Howells3bf0fb62018-10-20 00:57:59 +01002074 struct key *key,
2075 unsigned int server_index,
2076 bool async)
David Howellsd2ddc772017-11-02 15:27:50 +00002077{
2078 struct afs_call *call;
2079 __be32 *bp;
2080
2081 _enter("");
2082
2083 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
2084 if (!call)
2085 return -ENOMEM;
2086
2087 call->key = key;
David Howells3bf0fb62018-10-20 00:57:59 +01002088 call->reply[0] = afs_get_server(server);
2089 call->reply[1] = (void *)(long)server_index;
David Howells30062bd2018-10-20 00:57:58 +01002090 call->upgrade = true;
David Howells3bf0fb62018-10-20 00:57:59 +01002091 call->want_reply_time = true;
David Howellsd2ddc772017-11-02 15:27:50 +00002092
2093 /* marshall the parameters */
2094 bp = call->request;
2095 *bp++ = htonl(FSGETCAPABILITIES);
2096
2097 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00002098 trace_afs_make_fs_call(call, NULL);
David Howells3bf0fb62018-10-20 00:57:59 +01002099 return afs_make_call(ac, call, GFP_NOFS, async);
David Howellse8d6c552007-07-15 23:40:12 -07002100}
David Howells5cf9dd52018-04-09 21:12:31 +01002101
2102/*
2103 * Deliver reply data to an FS.FetchStatus with no vnode.
2104 */
2105static int afs_deliver_fs_fetch_status(struct afs_call *call)
2106{
2107 struct afs_file_status *status = call->reply[1];
2108 struct afs_callback *callback = call->reply[2];
2109 struct afs_volsync *volsync = call->reply[3];
David Howells36bb5f42018-10-20 00:57:58 +01002110 struct afs_fid *fid = call->reply[0];
David Howells5cf9dd52018-04-09 21:12:31 +01002111 const __be32 *bp;
2112 int ret;
2113
2114 ret = afs_transfer_reply(call);
2115 if (ret < 0)
2116 return ret;
2117
David Howells36bb5f42018-10-20 00:57:58 +01002118 _enter("{%llx:%llu}", fid->vid, fid->vnode);
David Howells5cf9dd52018-04-09 21:12:31 +01002119
2120 /* unmarshall the reply once we've received all of it */
2121 bp = call->buffer;
David Howells36bb5f42018-10-20 00:57:58 +01002122 ret = afs_decode_status(call, &bp, status, NULL,
David Howells160cb952018-10-20 00:57:56 +01002123 &call->expected_version, NULL);
2124 if (ret < 0)
2125 return ret;
David Howells12d8e952018-10-20 00:57:58 +01002126 xdr_decode_AFSCallBack_raw(call, &bp, callback);
David Howells30062bd2018-10-20 00:57:58 +01002127 xdr_decode_AFSVolSync(&bp, volsync);
David Howells5cf9dd52018-04-09 21:12:31 +01002128
2129 _leave(" = 0 [done]");
2130 return 0;
2131}
2132
2133/*
2134 * FS.FetchStatus operation type
2135 */
2136static const struct afs_call_type afs_RXFSFetchStatus = {
2137 .name = "FS.FetchStatus",
2138 .op = afs_FS_FetchStatus,
2139 .deliver = afs_deliver_fs_fetch_status,
2140 .destructor = afs_flat_call_destructor,
2141};
2142
2143/*
2144 * Fetch the status information for a fid without needing a vnode handle.
2145 */
2146int afs_fs_fetch_status(struct afs_fs_cursor *fc,
2147 struct afs_net *net,
2148 struct afs_fid *fid,
2149 struct afs_file_status *status,
2150 struct afs_callback *callback,
2151 struct afs_volsync *volsync)
2152{
2153 struct afs_call *call;
2154 __be32 *bp;
2155
David Howells30062bd2018-10-20 00:57:58 +01002156 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
2157 return yfs_fs_fetch_status(fc, net, fid, status, callback, volsync);
2158
David Howells3b6492d2018-10-20 00:57:57 +01002159 _enter(",%x,{%llx:%llu},,",
David Howells5cf9dd52018-04-09 21:12:31 +01002160 key_serial(fc->key), fid->vid, fid->vnode);
2161
2162 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
2163 if (!call) {
2164 fc->ac.error = -ENOMEM;
2165 return -ENOMEM;
2166 }
2167
2168 call->key = fc->key;
David Howells36bb5f42018-10-20 00:57:58 +01002169 call->reply[0] = fid;
David Howells5cf9dd52018-04-09 21:12:31 +01002170 call->reply[1] = status;
2171 call->reply[2] = callback;
2172 call->reply[3] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +01002173 call->expected_version = 1; /* vnode->status.data_version */
David Howells12d8e952018-10-20 00:57:58 +01002174 call->want_reply_time = true;
David Howells5cf9dd52018-04-09 21:12:31 +01002175
2176 /* marshall the parameters */
2177 bp = call->request;
2178 bp[0] = htonl(FSFETCHSTATUS);
2179 bp[1] = htonl(fid->vid);
2180 bp[2] = htonl(fid->vnode);
2181 bp[3] = htonl(fid->unique);
2182
2183 call->cb_break = fc->cb_break;
2184 afs_use_fs_server(call, fc->cbi);
2185 trace_afs_make_fs_call(call, fid);
2186 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2187}
2188
2189/*
2190 * Deliver reply data to an FS.InlineBulkStatus call
2191 */
2192static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2193{
2194 struct afs_file_status *statuses;
2195 struct afs_callback *callbacks;
2196 struct afs_vnode *vnode = call->reply[0];
2197 const __be32 *bp;
2198 u32 tmp;
2199 int ret;
2200
2201 _enter("{%u}", call->unmarshall);
2202
2203 switch (call->unmarshall) {
2204 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01002205 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002206 call->unmarshall++;
2207
2208 /* Extract the file status count and array in two steps */
2209 case 1:
2210 _debug("extract status count");
David Howells12bdcf32018-10-20 00:57:56 +01002211 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002212 if (ret < 0)
2213 return ret;
2214
2215 tmp = ntohl(call->tmp);
2216 _debug("status count: %u/%u", tmp, call->count2);
2217 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002218 return afs_protocol_error(call, -EBADMSG,
2219 afs_eproto_ibulkst_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002220
2221 call->count = 0;
2222 call->unmarshall++;
2223 more_counts:
David Howells12bdcf32018-10-20 00:57:56 +01002224 afs_extract_to_buf(call, 21 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002225
2226 case 2:
2227 _debug("extract status array %u", call->count);
David Howells12bdcf32018-10-20 00:57:56 +01002228 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002229 if (ret < 0)
2230 return ret;
2231
2232 bp = call->buffer;
2233 statuses = call->reply[1];
David Howells160cb952018-10-20 00:57:56 +01002234 ret = afs_decode_status(call, &bp, &statuses[call->count],
2235 call->count == 0 ? vnode : NULL,
2236 NULL, NULL);
2237 if (ret < 0)
2238 return ret;
David Howells5cf9dd52018-04-09 21:12:31 +01002239
2240 call->count++;
2241 if (call->count < call->count2)
2242 goto more_counts;
2243
2244 call->count = 0;
2245 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01002246 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002247
2248 /* Extract the callback count and array in two steps */
2249 case 3:
2250 _debug("extract CB count");
David Howells12bdcf32018-10-20 00:57:56 +01002251 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002252 if (ret < 0)
2253 return ret;
2254
2255 tmp = ntohl(call->tmp);
2256 _debug("CB count: %u", tmp);
2257 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002258 return afs_protocol_error(call, -EBADMSG,
2259 afs_eproto_ibulkst_cb_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002260 call->count = 0;
2261 call->unmarshall++;
2262 more_cbs:
David Howells12bdcf32018-10-20 00:57:56 +01002263 afs_extract_to_buf(call, 3 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002264
2265 case 4:
2266 _debug("extract CB array");
David Howells12bdcf32018-10-20 00:57:56 +01002267 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002268 if (ret < 0)
2269 return ret;
2270
2271 _debug("unmarshall CB array");
2272 bp = call->buffer;
2273 callbacks = call->reply[2];
2274 callbacks[call->count].version = ntohl(bp[0]);
David Howells12d8e952018-10-20 00:57:58 +01002275 callbacks[call->count].expires_at = xdr_decode_expiry(call, ntohl(bp[1]));
David Howells5cf9dd52018-04-09 21:12:31 +01002276 callbacks[call->count].type = ntohl(bp[2]);
2277 statuses = call->reply[1];
2278 if (call->count == 0 && vnode && statuses[0].abort_code == 0)
2279 xdr_decode_AFSCallBack(call, vnode, &bp);
2280 call->count++;
2281 if (call->count < call->count2)
2282 goto more_cbs;
2283
David Howells12bdcf32018-10-20 00:57:56 +01002284 afs_extract_to_buf(call, 6 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002285 call->unmarshall++;
2286
2287 case 5:
David Howells12bdcf32018-10-20 00:57:56 +01002288 ret = afs_extract_data(call, false);
David Howells5cf9dd52018-04-09 21:12:31 +01002289 if (ret < 0)
2290 return ret;
2291
2292 bp = call->buffer;
David Howells30062bd2018-10-20 00:57:58 +01002293 xdr_decode_AFSVolSync(&bp, call->reply[3]);
David Howells5cf9dd52018-04-09 21:12:31 +01002294
David Howells5cf9dd52018-04-09 21:12:31 +01002295 call->unmarshall++;
2296
2297 case 6:
2298 break;
2299 }
2300
2301 _leave(" = 0 [done]");
2302 return 0;
2303}
2304
2305/*
2306 * FS.InlineBulkStatus operation type
2307 */
2308static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2309 .name = "FS.InlineBulkStatus",
2310 .op = afs_FS_InlineBulkStatus,
2311 .deliver = afs_deliver_fs_inline_bulk_status,
2312 .destructor = afs_flat_call_destructor,
2313};
2314
2315/*
2316 * Fetch the status information for up to 50 files
2317 */
2318int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2319 struct afs_net *net,
2320 struct afs_fid *fids,
2321 struct afs_file_status *statuses,
2322 struct afs_callback *callbacks,
2323 unsigned int nr_fids,
2324 struct afs_volsync *volsync)
2325{
2326 struct afs_call *call;
2327 __be32 *bp;
2328 int i;
2329
David Howells30062bd2018-10-20 00:57:58 +01002330 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
2331 return yfs_fs_inline_bulk_status(fc, net, fids, statuses, callbacks,
2332 nr_fids, volsync);
2333
David Howells3b6492d2018-10-20 00:57:57 +01002334 _enter(",%x,{%llx:%llu},%u",
David Howells5cf9dd52018-04-09 21:12:31 +01002335 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2336
2337 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2338 (2 + nr_fids * 3) * 4,
2339 21 * 4);
2340 if (!call) {
2341 fc->ac.error = -ENOMEM;
2342 return -ENOMEM;
2343 }
2344
2345 call->key = fc->key;
2346 call->reply[0] = NULL; /* vnode for fid[0] */
2347 call->reply[1] = statuses;
2348 call->reply[2] = callbacks;
2349 call->reply[3] = volsync;
2350 call->count2 = nr_fids;
David Howells12d8e952018-10-20 00:57:58 +01002351 call->want_reply_time = true;
David Howells5cf9dd52018-04-09 21:12:31 +01002352
2353 /* marshall the parameters */
2354 bp = call->request;
2355 *bp++ = htonl(FSINLINEBULKSTATUS);
2356 *bp++ = htonl(nr_fids);
2357 for (i = 0; i < nr_fids; i++) {
2358 *bp++ = htonl(fids[i].vid);
2359 *bp++ = htonl(fids[i].vnode);
2360 *bp++ = htonl(fids[i].unique);
2361 }
2362
2363 call->cb_break = fc->cb_break;
2364 afs_use_fs_server(call, fc->cbi);
2365 trace_afs_make_fs_call(call, &fids[0]);
2366 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2367}