blob: 7f1722b9e432b94ae8495b31e6cda2267bdcbe68 [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 Howells0b9bf382019-04-25 14:26:50 +0100471
472 afs_make_call(&fc->ac, call, GFP_NOFS);
473 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsec268152007-04-26 15:49:28 -0700474}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476/*
David Howells08e0e7c2007-04-26 15:55:03 -0700477 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 */
David Howellsd0016482016-08-30 20:42:14 +0100479static int afs_deliver_fs_fetch_data(struct afs_call *call)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
David Howells97e30432017-11-02 15:27:48 +0000481 struct afs_vnode *vnode = call->reply[0];
482 struct afs_read *req = call->reply[2];
David Howells08e0e7c2007-04-26 15:55:03 -0700483 const __be32 *bp;
David Howells196ee9c2017-01-05 10:38:34 +0000484 unsigned int size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700486
David Howells12bdcf32018-10-20 00:57:56 +0100487 _enter("{%u,%zu/%llu}",
488 call->unmarshall, iov_iter_count(&call->iter), req->actual_len);
David Howells08e0e7c2007-04-26 15:55:03 -0700489
490 switch (call->unmarshall) {
491 case 0:
David Howells196ee9c2017-01-05 10:38:34 +0000492 req->actual_len = 0;
David Howells12bdcf32018-10-20 00:57:56 +0100493 req->index = 0;
494 req->offset = req->pos & (PAGE_SIZE - 1);
David Howells08e0e7c2007-04-26 15:55:03 -0700495 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +0100496 if (call->operation_ID == FSFETCHDATA64) {
497 afs_extract_to_tmp64(call);
498 } else {
499 call->tmp_u = htonl(0);
500 afs_extract_to_tmp(call);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700501 }
David Howells08e0e7c2007-04-26 15:55:03 -0700502
David Howellsb9b1f8d2007-05-10 03:15:21 -0700503 /* extract the returned data length */
David Howells12bdcf32018-10-20 00:57:56 +0100504 case 1:
David Howells08e0e7c2007-04-26 15:55:03 -0700505 _debug("extract data length");
David Howells12bdcf32018-10-20 00:57:56 +0100506 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +0100507 if (ret < 0)
508 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700509
David Howells12bdcf32018-10-20 00:57:56 +0100510 req->actual_len = be64_to_cpu(call->tmp64);
David Howells196ee9c2017-01-05 10:38:34 +0000511 _debug("DATA length: %llu", req->actual_len);
David Howells12bdcf32018-10-20 00:57:56 +0100512 req->remain = min(req->len, req->actual_len);
513 if (req->remain == 0)
David Howells196ee9c2017-01-05 10:38:34 +0000514 goto no_more_data;
David Howells12bdcf32018-10-20 00:57:56 +0100515
David Howells08e0e7c2007-04-26 15:55:03 -0700516 call->unmarshall++;
517
David Howells196ee9c2017-01-05 10:38:34 +0000518 begin_page:
David Howells6db3ac32017-03-16 16:27:44 +0000519 ASSERTCMP(req->index, <, req->nr_pages);
David Howells12bdcf32018-10-20 00:57:56 +0100520 if (req->remain > PAGE_SIZE - req->offset)
521 size = PAGE_SIZE - req->offset;
David Howells196ee9c2017-01-05 10:38:34 +0000522 else
523 size = req->remain;
David Howells12bdcf32018-10-20 00:57:56 +0100524 call->bvec[0].bv_len = size;
525 call->bvec[0].bv_offset = req->offset;
526 call->bvec[0].bv_page = req->pages[req->index];
527 iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
528 ASSERTCMP(size, <=, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000529
David Howells08e0e7c2007-04-26 15:55:03 -0700530 /* extract the returned data */
David Howells12bdcf32018-10-20 00:57:56 +0100531 case 2:
532 _debug("extract data %zu/%llu",
533 iov_iter_count(&call->iter), req->remain);
David Howells196ee9c2017-01-05 10:38:34 +0000534
David Howells12bdcf32018-10-20 00:57:56 +0100535 ret = afs_extract_data(call, true);
David Howells196ee9c2017-01-05 10:38:34 +0000536 if (ret < 0)
537 return ret;
David Howells12bdcf32018-10-20 00:57:56 +0100538 req->remain -= call->bvec[0].bv_len;
539 req->offset += call->bvec[0].bv_len;
540 ASSERTCMP(req->offset, <=, PAGE_SIZE);
541 if (req->offset == PAGE_SIZE) {
542 req->offset = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000543 if (req->page_done)
544 req->page_done(call, req);
David Howells29f06982017-03-16 16:27:46 +0000545 req->index++;
David Howells12bdcf32018-10-20 00:57:56 +0100546 if (req->remain > 0)
David Howells196ee9c2017-01-05 10:38:34 +0000547 goto begin_page;
David Howells08e0e7c2007-04-26 15:55:03 -0700548 }
David Howells12bdcf32018-10-20 00:57:56 +0100549
550 ASSERTCMP(req->remain, ==, 0);
551 if (req->actual_len <= req->len)
552 goto no_more_data;
David Howells6db3ac32017-03-16 16:27:44 +0000553
554 /* Discard any excess data the server gave us */
David Howells12bdcf32018-10-20 00:57:56 +0100555 iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
556 call->unmarshall = 3;
557 case 3:
558 _debug("extract discard %zu/%llu",
559 iov_iter_count(&call->iter), req->actual_len - req->len);
David Howells6db3ac32017-03-16 16:27:44 +0000560
David Howells12bdcf32018-10-20 00:57:56 +0100561 ret = afs_extract_data(call, true);
David Howells6db3ac32017-03-16 16:27:44 +0000562 if (ret < 0)
563 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700564
David Howells196ee9c2017-01-05 10:38:34 +0000565 no_more_data:
David Howells12bdcf32018-10-20 00:57:56 +0100566 call->unmarshall = 4;
567 afs_extract_to_buf(call, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700568
569 /* extract the metadata */
David Howells12bdcf32018-10-20 00:57:56 +0100570 case 4:
571 ret = afs_extract_data(call, false);
David Howells372ee162016-08-03 14:11:40 +0100572 if (ret < 0)
573 return ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700574
575 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100576 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
577 &vnode->status.data_version, req);
578 if (ret < 0)
579 return ret;
David Howellsc435ee32017-11-02 15:27:49 +0000580 xdr_decode_AFSCallBack(call, vnode, &bp);
David Howells30062bd2018-10-20 00:57:58 +0100581 xdr_decode_AFSVolSync(&bp, call->reply[1]);
David Howells08e0e7c2007-04-26 15:55:03 -0700582
David Howells08e0e7c2007-04-26 15:55:03 -0700583 call->unmarshall++;
584
David Howells12bdcf32018-10-20 00:57:56 +0100585 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700586 break;
587 }
588
David Howells6db3ac32017-03-16 16:27:44 +0000589 for (; req->index < req->nr_pages; req->index++) {
David Howells12bdcf32018-10-20 00:57:56 +0100590 if (req->offset < PAGE_SIZE)
David Howells6db3ac32017-03-16 16:27:44 +0000591 zero_user_segment(req->pages[req->index],
David Howells12bdcf32018-10-20 00:57:56 +0100592 req->offset, PAGE_SIZE);
David Howells196ee9c2017-01-05 10:38:34 +0000593 if (req->page_done)
594 req->page_done(call, req);
David Howells12bdcf32018-10-20 00:57:56 +0100595 req->offset = 0;
David Howells416351f2007-05-09 02:33:45 -0700596 }
597
David Howells08e0e7c2007-04-26 15:55:03 -0700598 _leave(" = 0 [done]");
599 return 0;
600}
601
David Howells196ee9c2017-01-05 10:38:34 +0000602static void afs_fetch_data_destructor(struct afs_call *call)
603{
David Howells97e30432017-11-02 15:27:48 +0000604 struct afs_read *req = call->reply[2];
David Howells196ee9c2017-01-05 10:38:34 +0000605
606 afs_put_read(req);
607 afs_flat_call_destructor(call);
608}
609
David Howells08e0e7c2007-04-26 15:55:03 -0700610/*
611 * FS.FetchData operation type
612 */
613static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700614 .name = "FS.FetchData",
David Howells025db802017-11-02 15:27:51 +0000615 .op = afs_FS_FetchData,
David Howells08e0e7c2007-04-26 15:55:03 -0700616 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000617 .destructor = afs_fetch_data_destructor,
David Howells08e0e7c2007-04-26 15:55:03 -0700618};
619
David Howellsb9b1f8d2007-05-10 03:15:21 -0700620static const struct afs_call_type afs_RXFSFetchData64 = {
621 .name = "FS.FetchData64",
David Howells025db802017-11-02 15:27:51 +0000622 .op = afs_FS_FetchData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700623 .deliver = afs_deliver_fs_fetch_data,
David Howells196ee9c2017-01-05 10:38:34 +0000624 .destructor = afs_fetch_data_destructor,
David Howellsb9b1f8d2007-05-10 03:15:21 -0700625};
626
627/*
628 * fetch data from a very large file
629 */
David Howellsd2ddc772017-11-02 15:27:50 +0000630static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
David Howellsb9b1f8d2007-05-10 03:15:21 -0700631{
David Howellsd2ddc772017-11-02 15:27:50 +0000632 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700633 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000634 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700635 __be32 *bp;
636
637 _enter("");
638
David Howellsf044c882017-11-02 15:27:45 +0000639 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700640 if (!call)
641 return -ENOMEM;
642
David Howellsd2ddc772017-11-02 15:27:50 +0000643 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000644 call->reply[0] = vnode;
645 call->reply[1] = NULL; /* volsync */
646 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100647 call->expected_version = vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100648 call->want_reply_time = true;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700649
650 /* marshall the parameters */
651 bp = call->request;
652 bp[0] = htonl(FSFETCHDATA64);
653 bp[1] = htonl(vnode->fid.vid);
654 bp[2] = htonl(vnode->fid.vnode);
655 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000656 bp[4] = htonl(upper_32_bits(req->pos));
657 bp[5] = htonl(lower_32_bits(req->pos));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700658 bp[6] = 0;
David Howells196ee9c2017-01-05 10:38:34 +0000659 bp[7] = htonl(lower_32_bits(req->len));
David Howellsb9b1f8d2007-05-10 03:15:21 -0700660
David Howellsf3ddee82018-04-06 14:17:25 +0100661 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000662 call->cb_break = fc->cb_break;
663 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000664 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +0100665 afs_make_call(&fc->ac, call, GFP_NOFS);
666 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700667}
668
David Howells08e0e7c2007-04-26 15:55:03 -0700669/*
670 * fetch data from a file
671 */
David Howellsd2ddc772017-11-02 15:27:50 +0000672int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
David Howells08e0e7c2007-04-26 15:55:03 -0700673{
David Howellsd2ddc772017-11-02 15:27:50 +0000674 struct afs_vnode *vnode = fc->vnode;
David Howells08e0e7c2007-04-26 15:55:03 -0700675 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000676 struct afs_net *net = afs_v2net(vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 __be32 *bp;
678
David Howells30062bd2018-10-20 00:57:58 +0100679 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
680 return yfs_fs_fetch_data(fc, req);
681
David Howells196ee9c2017-01-05 10:38:34 +0000682 if (upper_32_bits(req->pos) ||
683 upper_32_bits(req->len) ||
684 upper_32_bits(req->pos + req->len))
David Howellsd2ddc772017-11-02 15:27:50 +0000685 return afs_fs_fetch_data64(fc, req);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700686
David Howells08e0e7c2007-04-26 15:55:03 -0700687 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
David Howellsf044c882017-11-02 15:27:45 +0000689 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700690 if (!call)
691 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
David Howellsd2ddc772017-11-02 15:27:50 +0000693 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000694 call->reply[0] = vnode;
695 call->reply[1] = NULL; /* volsync */
696 call->reply[2] = req;
David Howells0c3a5ac2018-04-06 14:17:24 +0100697 call->expected_version = vnode->status.data_version;
David Howells12d8e952018-10-20 00:57:58 +0100698 call->want_reply_time = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
700 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700701 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700703 bp[1] = htonl(vnode->fid.vid);
704 bp[2] = htonl(vnode->fid.vnode);
705 bp[3] = htonl(vnode->fid.unique);
David Howells196ee9c2017-01-05 10:38:34 +0000706 bp[4] = htonl(lower_32_bits(req->pos));
707 bp[5] = htonl(lower_32_bits(req->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
David Howellsf3ddee82018-04-06 14:17:25 +0100709 refcount_inc(&req->usage);
David Howellsd2ddc772017-11-02 15:27:50 +0000710 call->cb_break = fc->cb_break;
711 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +0000712 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +0100713 afs_make_call(&fc->ac, call, GFP_NOFS);
714 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsec268152007-04-26 15:49:28 -0700715}
David Howells260a9802007-04-26 15:59:35 -0700716
717/*
718 * deliver reply data to an FS.CreateFile or an FS.MakeDir
719 */
David Howellsd0016482016-08-30 20:42:14 +0100720static int afs_deliver_fs_create_vnode(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700721{
David Howells97e30432017-11-02 15:27:48 +0000722 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700723 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100724 int ret;
David Howells260a9802007-04-26 15:59:35 -0700725
David Howellsd0016482016-08-30 20:42:14 +0100726 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700727
David Howellsd0016482016-08-30 20:42:14 +0100728 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100729 if (ret < 0)
730 return ret;
David Howells260a9802007-04-26 15:59:35 -0700731
732 /* unmarshall the reply once we've received all of it */
733 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +0000734 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +0100735 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
736 if (ret < 0)
737 return ret;
738 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
739 &call->expected_version, NULL);
740 if (ret < 0)
741 return ret;
David Howells12d8e952018-10-20 00:57:58 +0100742 xdr_decode_AFSCallBack_raw(call, &bp, call->reply[3]);
David Howells97e30432017-11-02 15:27:48 +0000743 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700744
745 _leave(" = 0 [done]");
746 return 0;
747}
748
749/*
750 * FS.CreateFile and FS.MakeDir operation type
751 */
David Howells025db802017-11-02 15:27:51 +0000752static const struct afs_call_type afs_RXFSCreateFile = {
753 .name = "FS.CreateFile",
754 .op = afs_FS_CreateFile,
755 .deliver = afs_deliver_fs_create_vnode,
756 .destructor = afs_flat_call_destructor,
757};
758
759static const struct afs_call_type afs_RXFSMakeDir = {
760 .name = "FS.MakeDir",
761 .op = afs_FS_MakeDir,
David Howells260a9802007-04-26 15:59:35 -0700762 .deliver = afs_deliver_fs_create_vnode,
David Howells260a9802007-04-26 15:59:35 -0700763 .destructor = afs_flat_call_destructor,
764};
765
766/*
767 * create a file or make a directory
768 */
David Howells8b2a4642017-11-02 15:27:50 +0000769int afs_fs_create(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -0700770 const char *name,
771 umode_t mode,
David Howells63a46812018-04-06 14:17:25 +0100772 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -0700773 struct afs_fid *newfid,
774 struct afs_file_status *newstatus,
David Howellsd2ddc772017-11-02 15:27:50 +0000775 struct afs_callback *newcb)
David Howells260a9802007-04-26 15:59:35 -0700776{
David Howellsd2ddc772017-11-02 15:27:50 +0000777 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700778 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000779 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700780 size_t namesz, reqsz, padsz;
781 __be32 *bp;
782
David Howells30062bd2018-10-20 00:57:58 +0100783 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){
784 if (S_ISDIR(mode))
785 return yfs_fs_make_dir(fc, name, mode, current_data_version,
786 newfid, newstatus, newcb);
787 else
788 return yfs_fs_create_file(fc, name, mode, current_data_version,
789 newfid, newstatus, newcb);
790 }
791
David Howells260a9802007-04-26 15:59:35 -0700792 _enter("");
793
794 namesz = strlen(name);
795 padsz = (4 - (namesz & 3)) & 3;
796 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
797
David Howells025db802017-11-02 15:27:51 +0000798 call = afs_alloc_flat_call(
799 net, S_ISDIR(mode) ? &afs_RXFSMakeDir : &afs_RXFSCreateFile,
800 reqsz, (3 + 21 + 21 + 3 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700801 if (!call)
802 return -ENOMEM;
803
David Howellsd2ddc772017-11-02 15:27:50 +0000804 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +0000805 call->reply[0] = vnode;
806 call->reply[1] = newfid;
807 call->reply[2] = newstatus;
808 call->reply[3] = newcb;
David Howells63a46812018-04-06 14:17:25 +0100809 call->expected_version = current_data_version + 1;
David Howells12d8e952018-10-20 00:57:58 +0100810 call->want_reply_time = true;
David Howells260a9802007-04-26 15:59:35 -0700811
812 /* marshall the parameters */
813 bp = call->request;
814 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
815 *bp++ = htonl(vnode->fid.vid);
816 *bp++ = htonl(vnode->fid.vnode);
817 *bp++ = htonl(vnode->fid.unique);
818 *bp++ = htonl(namesz);
819 memcpy(bp, name, namesz);
820 bp = (void *) bp + namesz;
821 if (padsz > 0) {
822 memset(bp, 0, padsz);
823 bp = (void *) bp + padsz;
824 }
Marc Dionneab94f5d2017-03-16 16:27:47 +0000825 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
826 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -0700827 *bp++ = 0; /* owner */
828 *bp++ = 0; /* group */
829 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
830 *bp++ = 0; /* segment size */
831
David Howellsd2ddc772017-11-02 15:27:50 +0000832 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +0100833 trace_afs_make_fs_call1(call, &vnode->fid, name);
David Howells0b9bf382019-04-25 14:26:50 +0100834 afs_make_call(&fc->ac, call, GFP_NOFS);
835 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -0700836}
837
838/*
Joe Gorseb10494a2019-04-25 14:26:52 +0100839 * Deliver reply data to any operation that returns file status and volume
840 * sync.
David Howells260a9802007-04-26 15:59:35 -0700841 */
Joe Gorseb10494a2019-04-25 14:26:52 +0100842static int afs_deliver_fs_status_and_vol(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700843{
David Howells97e30432017-11-02 15:27:48 +0000844 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -0700845 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100846 int ret;
David Howells260a9802007-04-26 15:59:35 -0700847
David Howellsd0016482016-08-30 20:42:14 +0100848 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700849
David Howellsd0016482016-08-30 20:42:14 +0100850 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100851 if (ret < 0)
852 return ret;
David Howells260a9802007-04-26 15:59:35 -0700853
854 /* unmarshall the reply once we've received all of it */
855 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100856 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
857 &call->expected_version, NULL);
858 if (ret < 0)
859 return ret;
David Howells97e30432017-11-02 15:27:48 +0000860 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700861
862 _leave(" = 0 [done]");
863 return 0;
864}
865
866/*
867 * FS.RemoveDir/FS.RemoveFile operation type
868 */
David Howells025db802017-11-02 15:27:51 +0000869static const struct afs_call_type afs_RXFSRemoveFile = {
870 .name = "FS.RemoveFile",
871 .op = afs_FS_RemoveFile,
Joe Gorseb10494a2019-04-25 14:26:52 +0100872 .deliver = afs_deliver_fs_status_and_vol,
David Howells025db802017-11-02 15:27:51 +0000873 .destructor = afs_flat_call_destructor,
874};
875
876static const struct afs_call_type afs_RXFSRemoveDir = {
877 .name = "FS.RemoveDir",
878 .op = afs_FS_RemoveDir,
Joe Gorseb10494a2019-04-25 14:26:52 +0100879 .deliver = afs_deliver_fs_status_and_vol,
David Howells260a9802007-04-26 15:59:35 -0700880 .destructor = afs_flat_call_destructor,
881};
882
883/*
884 * remove a file or directory
885 */
David Howells30062bd2018-10-20 00:57:58 +0100886int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
887 const char *name, bool isdir, u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700888{
David Howells30062bd2018-10-20 00:57:58 +0100889 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700890 struct afs_call *call;
David Howells30062bd2018-10-20 00:57:58 +0100891 struct afs_net *net = afs_v2net(dvnode);
David Howells260a9802007-04-26 15:59:35 -0700892 size_t namesz, reqsz, padsz;
893 __be32 *bp;
894
David Howells30062bd2018-10-20 00:57:58 +0100895 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
896 return yfs_fs_remove(fc, vnode, name, isdir, current_data_version);
897
David Howells260a9802007-04-26 15:59:35 -0700898 _enter("");
899
900 namesz = strlen(name);
901 padsz = (4 - (namesz & 3)) & 3;
902 reqsz = (5 * 4) + namesz + padsz;
903
David Howells025db802017-11-02 15:27:51 +0000904 call = afs_alloc_flat_call(
905 net, isdir ? &afs_RXFSRemoveDir : &afs_RXFSRemoveFile,
906 reqsz, (21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700907 if (!call)
908 return -ENOMEM;
909
David Howellsd2ddc772017-11-02 15:27:50 +0000910 call->key = fc->key;
David Howells30062bd2018-10-20 00:57:58 +0100911 call->reply[0] = dvnode;
912 call->reply[1] = vnode;
David Howells63a46812018-04-06 14:17:25 +0100913 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -0700914
915 /* marshall the parameters */
916 bp = call->request;
917 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
David Howells30062bd2018-10-20 00:57:58 +0100918 *bp++ = htonl(dvnode->fid.vid);
919 *bp++ = htonl(dvnode->fid.vnode);
920 *bp++ = htonl(dvnode->fid.unique);
David Howells260a9802007-04-26 15:59:35 -0700921 *bp++ = htonl(namesz);
922 memcpy(bp, name, namesz);
923 bp = (void *) bp + namesz;
924 if (padsz > 0) {
925 memset(bp, 0, padsz);
926 bp = (void *) bp + padsz;
927 }
928
David Howellsd2ddc772017-11-02 15:27:50 +0000929 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +0100930 trace_afs_make_fs_call1(call, &dvnode->fid, name);
David Howells0b9bf382019-04-25 14:26:50 +0100931 afs_make_call(&fc->ac, call, GFP_NOFS);
932 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -0700933}
934
935/*
936 * deliver reply data to an FS.Link
937 */
David Howellsd0016482016-08-30 20:42:14 +0100938static int afs_deliver_fs_link(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -0700939{
David Howells97e30432017-11-02 15:27:48 +0000940 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -0700941 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +0100942 int ret;
David Howells260a9802007-04-26 15:59:35 -0700943
David Howellsd0016482016-08-30 20:42:14 +0100944 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -0700945
David Howellsd0016482016-08-30 20:42:14 +0100946 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +0100947 if (ret < 0)
948 return ret;
David Howells260a9802007-04-26 15:59:35 -0700949
950 /* unmarshall the reply once we've received all of it */
951 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +0100952 ret = afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
953 if (ret < 0)
954 return ret;
955 ret = afs_decode_status(call, &bp, &dvnode->status, dvnode,
956 &call->expected_version, NULL);
957 if (ret < 0)
958 return ret;
David Howells97e30432017-11-02 15:27:48 +0000959 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -0700960
961 _leave(" = 0 [done]");
962 return 0;
963}
964
965/*
966 * FS.Link operation type
967 */
968static const struct afs_call_type afs_RXFSLink = {
969 .name = "FS.Link",
David Howells025db802017-11-02 15:27:51 +0000970 .op = afs_FS_Link,
David Howells260a9802007-04-26 15:59:35 -0700971 .deliver = afs_deliver_fs_link,
David Howells260a9802007-04-26 15:59:35 -0700972 .destructor = afs_flat_call_destructor,
973};
974
975/*
976 * make a hard link
977 */
David Howellsd2ddc772017-11-02 15:27:50 +0000978int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
David Howells63a46812018-04-06 14:17:25 +0100979 const char *name, u64 current_data_version)
David Howells260a9802007-04-26 15:59:35 -0700980{
David Howellsd2ddc772017-11-02 15:27:50 +0000981 struct afs_vnode *dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -0700982 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +0000983 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -0700984 size_t namesz, reqsz, padsz;
985 __be32 *bp;
986
David Howells30062bd2018-10-20 00:57:58 +0100987 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
988 return yfs_fs_link(fc, vnode, name, current_data_version);
989
David Howells260a9802007-04-26 15:59:35 -0700990 _enter("");
991
992 namesz = strlen(name);
993 padsz = (4 - (namesz & 3)) & 3;
994 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
995
David Howellsf044c882017-11-02 15:27:45 +0000996 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -0700997 if (!call)
998 return -ENOMEM;
999
David Howellsd2ddc772017-11-02 15:27:50 +00001000 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001001 call->reply[0] = dvnode;
1002 call->reply[1] = vnode;
David Howells63a46812018-04-06 14:17:25 +01001003 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001004
1005 /* marshall the parameters */
1006 bp = call->request;
1007 *bp++ = htonl(FSLINK);
1008 *bp++ = htonl(dvnode->fid.vid);
1009 *bp++ = htonl(dvnode->fid.vnode);
1010 *bp++ = htonl(dvnode->fid.unique);
1011 *bp++ = htonl(namesz);
1012 memcpy(bp, name, namesz);
1013 bp = (void *) bp + namesz;
1014 if (padsz > 0) {
1015 memset(bp, 0, padsz);
1016 bp = (void *) bp + padsz;
1017 }
1018 *bp++ = htonl(vnode->fid.vid);
1019 *bp++ = htonl(vnode->fid.vnode);
1020 *bp++ = htonl(vnode->fid.unique);
1021
David Howellsd2ddc772017-11-02 15:27:50 +00001022 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +01001023 trace_afs_make_fs_call1(call, &vnode->fid, name);
David Howells0b9bf382019-04-25 14:26:50 +01001024 afs_make_call(&fc->ac, call, GFP_NOFS);
1025 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -07001026}
1027
1028/*
1029 * deliver reply data to an FS.Symlink
1030 */
David Howellsd0016482016-08-30 20:42:14 +01001031static int afs_deliver_fs_symlink(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001032{
David Howells97e30432017-11-02 15:27:48 +00001033 struct afs_vnode *vnode = call->reply[0];
David Howells260a9802007-04-26 15:59:35 -07001034 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001035 int ret;
David Howells260a9802007-04-26 15:59:35 -07001036
David Howellsd0016482016-08-30 20:42:14 +01001037 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001038
David Howellsd0016482016-08-30 20:42:14 +01001039 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001040 if (ret < 0)
1041 return ret;
David Howells260a9802007-04-26 15:59:35 -07001042
1043 /* unmarshall the reply once we've received all of it */
1044 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001045 xdr_decode_AFSFid(&bp, call->reply[1]);
David Howells160cb952018-10-20 00:57:56 +01001046 ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
1047 if (ret < 0)
1048 return ret;
1049 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1050 &call->expected_version, NULL);
1051 if (ret < 0)
1052 return ret;
David Howells97e30432017-11-02 15:27:48 +00001053 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001054
1055 _leave(" = 0 [done]");
1056 return 0;
1057}
1058
1059/*
1060 * FS.Symlink operation type
1061 */
1062static const struct afs_call_type afs_RXFSSymlink = {
1063 .name = "FS.Symlink",
David Howells025db802017-11-02 15:27:51 +00001064 .op = afs_FS_Symlink,
David Howells260a9802007-04-26 15:59:35 -07001065 .deliver = afs_deliver_fs_symlink,
David Howells260a9802007-04-26 15:59:35 -07001066 .destructor = afs_flat_call_destructor,
1067};
1068
1069/*
1070 * create a symbolic link
1071 */
David Howells8b2a4642017-11-02 15:27:50 +00001072int afs_fs_symlink(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001073 const char *name,
1074 const char *contents,
David Howells63a46812018-04-06 14:17:25 +01001075 u64 current_data_version,
David Howells260a9802007-04-26 15:59:35 -07001076 struct afs_fid *newfid,
David Howellsd2ddc772017-11-02 15:27:50 +00001077 struct afs_file_status *newstatus)
David Howells260a9802007-04-26 15:59:35 -07001078{
David Howellsd2ddc772017-11-02 15:27:50 +00001079 struct afs_vnode *vnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001080 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001081 struct afs_net *net = afs_v2net(vnode);
David Howells260a9802007-04-26 15:59:35 -07001082 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
1083 __be32 *bp;
1084
David Howells30062bd2018-10-20 00:57:58 +01001085 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1086 return yfs_fs_symlink(fc, name, contents, current_data_version,
1087 newfid, newstatus);
1088
David Howells260a9802007-04-26 15:59:35 -07001089 _enter("");
1090
1091 namesz = strlen(name);
1092 padsz = (4 - (namesz & 3)) & 3;
1093
1094 c_namesz = strlen(contents);
1095 c_padsz = (4 - (c_namesz & 3)) & 3;
1096
1097 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
1098
David Howellsf044c882017-11-02 15:27:45 +00001099 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
David Howells260a9802007-04-26 15:59:35 -07001100 (3 + 21 + 21 + 6) * 4);
1101 if (!call)
1102 return -ENOMEM;
1103
David Howellsd2ddc772017-11-02 15:27:50 +00001104 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001105 call->reply[0] = vnode;
1106 call->reply[1] = newfid;
1107 call->reply[2] = newstatus;
David Howells63a46812018-04-06 14:17:25 +01001108 call->expected_version = current_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001109
1110 /* marshall the parameters */
1111 bp = call->request;
1112 *bp++ = htonl(FSSYMLINK);
1113 *bp++ = htonl(vnode->fid.vid);
1114 *bp++ = htonl(vnode->fid.vnode);
1115 *bp++ = htonl(vnode->fid.unique);
1116 *bp++ = htonl(namesz);
1117 memcpy(bp, name, namesz);
1118 bp = (void *) bp + namesz;
1119 if (padsz > 0) {
1120 memset(bp, 0, padsz);
1121 bp = (void *) bp + padsz;
1122 }
1123 *bp++ = htonl(c_namesz);
1124 memcpy(bp, contents, c_namesz);
1125 bp = (void *) bp + c_namesz;
1126 if (c_padsz > 0) {
1127 memset(bp, 0, c_padsz);
1128 bp = (void *) bp + c_padsz;
1129 }
Marc Dionneab94f5d2017-03-16 16:27:47 +00001130 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
1131 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells260a9802007-04-26 15:59:35 -07001132 *bp++ = 0; /* owner */
1133 *bp++ = 0; /* group */
1134 *bp++ = htonl(S_IRWXUGO); /* unix mode */
1135 *bp++ = 0; /* segment size */
1136
David Howellsd2ddc772017-11-02 15:27:50 +00001137 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +01001138 trace_afs_make_fs_call1(call, &vnode->fid, name);
David Howells0b9bf382019-04-25 14:26:50 +01001139 afs_make_call(&fc->ac, call, GFP_NOFS);
1140 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -07001141}
1142
1143/*
1144 * deliver reply data to an FS.Rename
1145 */
David Howellsd0016482016-08-30 20:42:14 +01001146static int afs_deliver_fs_rename(struct afs_call *call)
David Howells260a9802007-04-26 15:59:35 -07001147{
David Howells97e30432017-11-02 15:27:48 +00001148 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
David Howells260a9802007-04-26 15:59:35 -07001149 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001150 int ret;
David Howells260a9802007-04-26 15:59:35 -07001151
David Howellsd0016482016-08-30 20:42:14 +01001152 _enter("{%u}", call->unmarshall);
David Howells260a9802007-04-26 15:59:35 -07001153
David Howellsd0016482016-08-30 20:42:14 +01001154 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001155 if (ret < 0)
1156 return ret;
David Howells260a9802007-04-26 15:59:35 -07001157
1158 /* unmarshall the reply once we've received all of it */
1159 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001160 ret = afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
1161 &call->expected_version, NULL);
1162 if (ret < 0)
1163 return ret;
1164 if (new_dvnode != orig_dvnode) {
1165 ret = afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
1166 &call->expected_version_2, NULL);
1167 if (ret < 0)
1168 return ret;
1169 }
David Howells97e30432017-11-02 15:27:48 +00001170 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells260a9802007-04-26 15:59:35 -07001171
1172 _leave(" = 0 [done]");
1173 return 0;
1174}
1175
1176/*
1177 * FS.Rename operation type
1178 */
1179static const struct afs_call_type afs_RXFSRename = {
1180 .name = "FS.Rename",
David Howells025db802017-11-02 15:27:51 +00001181 .op = afs_FS_Rename,
David Howells260a9802007-04-26 15:59:35 -07001182 .deliver = afs_deliver_fs_rename,
David Howells260a9802007-04-26 15:59:35 -07001183 .destructor = afs_flat_call_destructor,
1184};
1185
1186/*
1187 * create a symbolic link
1188 */
David Howells8b2a4642017-11-02 15:27:50 +00001189int afs_fs_rename(struct afs_fs_cursor *fc,
David Howells260a9802007-04-26 15:59:35 -07001190 const char *orig_name,
1191 struct afs_vnode *new_dvnode,
David Howells63a46812018-04-06 14:17:25 +01001192 const char *new_name,
1193 u64 current_orig_data_version,
1194 u64 current_new_data_version)
David Howells260a9802007-04-26 15:59:35 -07001195{
David Howellsd2ddc772017-11-02 15:27:50 +00001196 struct afs_vnode *orig_dvnode = fc->vnode;
David Howells260a9802007-04-26 15:59:35 -07001197 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001198 struct afs_net *net = afs_v2net(orig_dvnode);
David Howells260a9802007-04-26 15:59:35 -07001199 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1200 __be32 *bp;
1201
David Howells30062bd2018-10-20 00:57:58 +01001202 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1203 return yfs_fs_rename(fc, orig_name,
1204 new_dvnode, new_name,
1205 current_orig_data_version,
1206 current_new_data_version);
1207
David Howells260a9802007-04-26 15:59:35 -07001208 _enter("");
1209
1210 o_namesz = strlen(orig_name);
1211 o_padsz = (4 - (o_namesz & 3)) & 3;
1212
1213 n_namesz = strlen(new_name);
1214 n_padsz = (4 - (n_namesz & 3)) & 3;
1215
1216 reqsz = (4 * 4) +
1217 4 + o_namesz + o_padsz +
1218 (3 * 4) +
1219 4 + n_namesz + n_padsz;
1220
David Howellsf044c882017-11-02 15:27:45 +00001221 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
David Howells260a9802007-04-26 15:59:35 -07001222 if (!call)
1223 return -ENOMEM;
1224
David Howellsd2ddc772017-11-02 15:27:50 +00001225 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001226 call->reply[0] = orig_dvnode;
1227 call->reply[1] = new_dvnode;
David Howells63a46812018-04-06 14:17:25 +01001228 call->expected_version = current_orig_data_version + 1;
1229 call->expected_version_2 = current_new_data_version + 1;
David Howells260a9802007-04-26 15:59:35 -07001230
1231 /* marshall the parameters */
1232 bp = call->request;
1233 *bp++ = htonl(FSRENAME);
1234 *bp++ = htonl(orig_dvnode->fid.vid);
1235 *bp++ = htonl(orig_dvnode->fid.vnode);
1236 *bp++ = htonl(orig_dvnode->fid.unique);
1237 *bp++ = htonl(o_namesz);
1238 memcpy(bp, orig_name, o_namesz);
1239 bp = (void *) bp + o_namesz;
1240 if (o_padsz > 0) {
1241 memset(bp, 0, o_padsz);
1242 bp = (void *) bp + o_padsz;
1243 }
1244
1245 *bp++ = htonl(new_dvnode->fid.vid);
1246 *bp++ = htonl(new_dvnode->fid.vnode);
1247 *bp++ = htonl(new_dvnode->fid.unique);
1248 *bp++ = htonl(n_namesz);
1249 memcpy(bp, new_name, n_namesz);
1250 bp = (void *) bp + n_namesz;
1251 if (n_padsz > 0) {
1252 memset(bp, 0, n_padsz);
1253 bp = (void *) bp + n_padsz;
1254 }
1255
David Howellsd2ddc772017-11-02 15:27:50 +00001256 afs_use_fs_server(call, fc->cbi);
David Howells80548b02019-04-25 14:26:51 +01001257 trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name);
David Howells0b9bf382019-04-25 14:26:50 +01001258 afs_make_call(&fc->ac, call, GFP_NOFS);
1259 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells260a9802007-04-26 15:59:35 -07001260}
David Howells31143d52007-05-09 02:33:46 -07001261
1262/*
1263 * deliver reply data to an FS.StoreData
1264 */
David Howellsd0016482016-08-30 20:42:14 +01001265static int afs_deliver_fs_store_data(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001266{
David Howells97e30432017-11-02 15:27:48 +00001267 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001268 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001269 int ret;
David Howells31143d52007-05-09 02:33:46 -07001270
David Howellsd0016482016-08-30 20:42:14 +01001271 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001272
David Howellsd0016482016-08-30 20:42:14 +01001273 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001274 if (ret < 0)
1275 return ret;
David Howells31143d52007-05-09 02:33:46 -07001276
1277 /* unmarshall the reply once we've received all of it */
1278 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001279 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1280 &call->expected_version, NULL);
1281 if (ret < 0)
1282 return ret;
David Howells97e30432017-11-02 15:27:48 +00001283 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001284
1285 afs_pages_written_back(vnode, call);
1286
1287 _leave(" = 0 [done]");
1288 return 0;
1289}
1290
1291/*
1292 * FS.StoreData operation type
1293 */
1294static const struct afs_call_type afs_RXFSStoreData = {
1295 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001296 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001297 .deliver = afs_deliver_fs_store_data,
David Howells31143d52007-05-09 02:33:46 -07001298 .destructor = afs_flat_call_destructor,
1299};
1300
David Howellsb9b1f8d2007-05-10 03:15:21 -07001301static const struct afs_call_type afs_RXFSStoreData64 = {
1302 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001303 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001304 .deliver = afs_deliver_fs_store_data,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001305 .destructor = afs_flat_call_destructor,
1306};
1307
1308/*
1309 * store a set of pages to a very large file
1310 */
David Howells8b2a4642017-11-02 15:27:50 +00001311static int afs_fs_store_data64(struct afs_fs_cursor *fc,
David Howells4343d002017-11-02 15:27:52 +00001312 struct address_space *mapping,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001313 pgoff_t first, pgoff_t last,
1314 unsigned offset, unsigned to,
David Howellsd2ddc772017-11-02 15:27:50 +00001315 loff_t size, loff_t pos, loff_t i_size)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001316{
David Howells4343d002017-11-02 15:27:52 +00001317 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001318 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001319 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001320 __be32 *bp;
1321
David Howells3b6492d2018-10-20 00:57:57 +01001322 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001323 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001324
David Howellsf044c882017-11-02 15:27:45 +00001325 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001326 (4 + 6 + 3 * 2) * 4,
1327 (21 + 6) * 4);
1328 if (!call)
1329 return -ENOMEM;
1330
David Howells4343d002017-11-02 15:27:52 +00001331 call->key = fc->key;
1332 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001333 call->reply[0] = vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001334 call->first = first;
1335 call->last = last;
1336 call->first_offset = offset;
1337 call->last_to = to;
1338 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001339 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001340
1341 /* marshall the parameters */
1342 bp = call->request;
1343 *bp++ = htonl(FSSTOREDATA64);
1344 *bp++ = htonl(vnode->fid.vid);
1345 *bp++ = htonl(vnode->fid.vnode);
1346 *bp++ = htonl(vnode->fid.unique);
1347
Marc Dionneab94f5d2017-03-16 16:27:47 +00001348 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1349 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howellsb9b1f8d2007-05-10 03:15:21 -07001350 *bp++ = 0; /* owner */
1351 *bp++ = 0; /* group */
1352 *bp++ = 0; /* unix mode */
1353 *bp++ = 0; /* segment size */
1354
1355 *bp++ = htonl(pos >> 32);
1356 *bp++ = htonl((u32) pos);
1357 *bp++ = htonl(size >> 32);
1358 *bp++ = htonl((u32) size);
1359 *bp++ = htonl(i_size >> 32);
1360 *bp++ = htonl((u32) i_size);
1361
David Howells025db802017-11-02 15:27:51 +00001362 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001363 afs_make_call(&fc->ac, call, GFP_NOFS);
1364 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001365}
1366
David Howells31143d52007-05-09 02:33:46 -07001367/*
1368 * store a set of pages
1369 */
David Howells4343d002017-11-02 15:27:52 +00001370int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
David Howells31143d52007-05-09 02:33:46 -07001371 pgoff_t first, pgoff_t last,
David Howellsd2ddc772017-11-02 15:27:50 +00001372 unsigned offset, unsigned to)
David Howells31143d52007-05-09 02:33:46 -07001373{
David Howells4343d002017-11-02 15:27:52 +00001374 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001375 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001376 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001377 loff_t size, pos, i_size;
1378 __be32 *bp;
1379
David Howells30062bd2018-10-20 00:57:58 +01001380 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1381 return yfs_fs_store_data(fc, mapping, first, last, offset, to);
1382
David Howells3b6492d2018-10-20 00:57:57 +01001383 _enter(",%x,{%llx:%llu},,",
David Howells4343d002017-11-02 15:27:52 +00001384 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001385
David Howells146a1192017-03-16 16:27:47 +00001386 size = (loff_t)to - (loff_t)offset;
David Howells31143d52007-05-09 02:33:46 -07001387 if (first != last)
1388 size += (loff_t)(last - first) << PAGE_SHIFT;
1389 pos = (loff_t)first << PAGE_SHIFT;
1390 pos += offset;
1391
1392 i_size = i_size_read(&vnode->vfs_inode);
1393 if (pos + size > i_size)
1394 i_size = size + pos;
1395
1396 _debug("size %llx, at %llx, i_size %llx",
1397 (unsigned long long) size, (unsigned long long) pos,
1398 (unsigned long long) i_size);
1399
David Howellsb9b1f8d2007-05-10 03:15:21 -07001400 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
David Howells4343d002017-11-02 15:27:52 +00001401 return afs_fs_store_data64(fc, mapping, first, last, offset, to,
David Howellsd2ddc772017-11-02 15:27:50 +00001402 size, pos, i_size);
David Howells31143d52007-05-09 02:33:46 -07001403
David Howellsf044c882017-11-02 15:27:45 +00001404 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
David Howells31143d52007-05-09 02:33:46 -07001405 (4 + 6 + 3) * 4,
1406 (21 + 6) * 4);
1407 if (!call)
1408 return -ENOMEM;
1409
David Howells4343d002017-11-02 15:27:52 +00001410 call->key = fc->key;
1411 call->mapping = mapping;
David Howells97e30432017-11-02 15:27:48 +00001412 call->reply[0] = vnode;
David Howells31143d52007-05-09 02:33:46 -07001413 call->first = first;
1414 call->last = last;
1415 call->first_offset = offset;
1416 call->last_to = to;
1417 call->send_pages = true;
David Howells0c3a5ac2018-04-06 14:17:24 +01001418 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001419
1420 /* marshall the parameters */
1421 bp = call->request;
1422 *bp++ = htonl(FSSTOREDATA);
1423 *bp++ = htonl(vnode->fid.vid);
1424 *bp++ = htonl(vnode->fid.vnode);
1425 *bp++ = htonl(vnode->fid.unique);
1426
Marc Dionneab94f5d2017-03-16 16:27:47 +00001427 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1428 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
David Howells31143d52007-05-09 02:33:46 -07001429 *bp++ = 0; /* owner */
1430 *bp++ = 0; /* group */
1431 *bp++ = 0; /* unix mode */
1432 *bp++ = 0; /* segment size */
1433
1434 *bp++ = htonl(pos);
1435 *bp++ = htonl(size);
1436 *bp++ = htonl(i_size);
1437
David Howellsd2ddc772017-11-02 15:27:50 +00001438 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001439 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001440 afs_make_call(&fc->ac, call, GFP_NOFS);
1441 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells31143d52007-05-09 02:33:46 -07001442}
1443
1444/*
1445 * deliver reply data to an FS.StoreStatus
1446 */
David Howellsd0016482016-08-30 20:42:14 +01001447static int afs_deliver_fs_store_status(struct afs_call *call)
David Howells31143d52007-05-09 02:33:46 -07001448{
David Howells97e30432017-11-02 15:27:48 +00001449 struct afs_vnode *vnode = call->reply[0];
David Howells31143d52007-05-09 02:33:46 -07001450 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001451 int ret;
David Howells31143d52007-05-09 02:33:46 -07001452
David Howellsd0016482016-08-30 20:42:14 +01001453 _enter("");
David Howells31143d52007-05-09 02:33:46 -07001454
David Howellsd0016482016-08-30 20:42:14 +01001455 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001456 if (ret < 0)
1457 return ret;
David Howells31143d52007-05-09 02:33:46 -07001458
1459 /* unmarshall the reply once we've received all of it */
David Howells31143d52007-05-09 02:33:46 -07001460 bp = call->buffer;
David Howells160cb952018-10-20 00:57:56 +01001461 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
1462 &call->expected_version, NULL);
1463 if (ret < 0)
1464 return ret;
David Howells97e30432017-11-02 15:27:48 +00001465 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howells31143d52007-05-09 02:33:46 -07001466
1467 _leave(" = 0 [done]");
1468 return 0;
1469}
1470
1471/*
1472 * FS.StoreStatus operation type
1473 */
1474static const struct afs_call_type afs_RXFSStoreStatus = {
1475 .name = "FS.StoreStatus",
David Howells025db802017-11-02 15:27:51 +00001476 .op = afs_FS_StoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001477 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001478 .destructor = afs_flat_call_destructor,
1479};
1480
1481static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1482 .name = "FS.StoreData",
David Howells025db802017-11-02 15:27:51 +00001483 .op = afs_FS_StoreData,
David Howells31143d52007-05-09 02:33:46 -07001484 .deliver = afs_deliver_fs_store_status,
David Howells31143d52007-05-09 02:33:46 -07001485 .destructor = afs_flat_call_destructor,
1486};
1487
David Howellsb9b1f8d2007-05-10 03:15:21 -07001488static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1489 .name = "FS.StoreData64",
David Howells025db802017-11-02 15:27:51 +00001490 .op = afs_FS_StoreData64,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001491 .deliver = afs_deliver_fs_store_status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001492 .destructor = afs_flat_call_destructor,
1493};
1494
1495/*
1496 * set the attributes on a very large file, using FS.StoreData rather than
1497 * FS.StoreStatus so as to alter the file size also
1498 */
David Howellsd2ddc772017-11-02 15:27:50 +00001499static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
David Howellsb9b1f8d2007-05-10 03:15:21 -07001500{
David Howellsd2ddc772017-11-02 15:27:50 +00001501 struct afs_vnode *vnode = fc->vnode;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001502 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001503 struct afs_net *net = afs_v2net(vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001504 __be32 *bp;
1505
David Howells3b6492d2018-10-20 00:57:57 +01001506 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001507 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001508
1509 ASSERT(attr->ia_valid & ATTR_SIZE);
1510
David Howellsf044c882017-11-02 15:27:45 +00001511 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
David Howellsb9b1f8d2007-05-10 03:15:21 -07001512 (4 + 6 + 3 * 2) * 4,
1513 (21 + 6) * 4);
1514 if (!call)
1515 return -ENOMEM;
1516
David Howellsd2ddc772017-11-02 15:27:50 +00001517 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001518 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001519 call->expected_version = vnode->status.data_version + 1;
David Howellsb9b1f8d2007-05-10 03:15:21 -07001520
1521 /* marshall the parameters */
1522 bp = call->request;
1523 *bp++ = htonl(FSSTOREDATA64);
1524 *bp++ = htonl(vnode->fid.vid);
1525 *bp++ = htonl(vnode->fid.vnode);
1526 *bp++ = htonl(vnode->fid.unique);
1527
1528 xdr_encode_AFS_StoreStatus(&bp, attr);
1529
David Howells8c7ae382019-03-27 22:48:02 +00001530 *bp++ = htonl(attr->ia_size >> 32); /* position of start of write */
1531 *bp++ = htonl((u32) attr->ia_size);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001532 *bp++ = 0; /* size of write */
1533 *bp++ = 0;
1534 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1535 *bp++ = htonl((u32) attr->ia_size);
1536
David Howellsd2ddc772017-11-02 15:27:50 +00001537 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001538 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001539 afs_make_call(&fc->ac, call, GFP_NOFS);
1540 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001541}
1542
David Howells31143d52007-05-09 02:33:46 -07001543/*
1544 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1545 * so as to alter the file size also
1546 */
David Howellsd2ddc772017-11-02 15:27:50 +00001547static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001548{
David Howellsd2ddc772017-11-02 15:27:50 +00001549 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001550 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001551 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001552 __be32 *bp;
1553
David Howells3b6492d2018-10-20 00:57:57 +01001554 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001555 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001556
1557 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001558 if (attr->ia_size >> 32)
David Howellsd2ddc772017-11-02 15:27:50 +00001559 return afs_fs_setattr_size64(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001560
David Howellsf044c882017-11-02 15:27:45 +00001561 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
David Howells31143d52007-05-09 02:33:46 -07001562 (4 + 6 + 3) * 4,
1563 (21 + 6) * 4);
1564 if (!call)
1565 return -ENOMEM;
1566
David Howellsd2ddc772017-11-02 15:27:50 +00001567 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001568 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001569 call->expected_version = vnode->status.data_version + 1;
David Howells31143d52007-05-09 02:33:46 -07001570
1571 /* marshall the parameters */
1572 bp = call->request;
1573 *bp++ = htonl(FSSTOREDATA);
1574 *bp++ = htonl(vnode->fid.vid);
1575 *bp++ = htonl(vnode->fid.vnode);
1576 *bp++ = htonl(vnode->fid.unique);
1577
1578 xdr_encode_AFS_StoreStatus(&bp, attr);
1579
David Howells8c7ae382019-03-27 22:48:02 +00001580 *bp++ = htonl(attr->ia_size); /* position of start of write */
David Howells31143d52007-05-09 02:33:46 -07001581 *bp++ = 0; /* size of write */
1582 *bp++ = htonl(attr->ia_size); /* new file length */
1583
David Howellsd2ddc772017-11-02 15:27:50 +00001584 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001585 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001586 afs_make_call(&fc->ac, call, GFP_NOFS);
1587 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells31143d52007-05-09 02:33:46 -07001588}
1589
1590/*
1591 * set the attributes on a file, using FS.StoreData if there's a change in file
1592 * size, and FS.StoreStatus otherwise
1593 */
David Howellsd2ddc772017-11-02 15:27:50 +00001594int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
David Howells31143d52007-05-09 02:33:46 -07001595{
David Howellsd2ddc772017-11-02 15:27:50 +00001596 struct afs_vnode *vnode = fc->vnode;
David Howells31143d52007-05-09 02:33:46 -07001597 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001598 struct afs_net *net = afs_v2net(vnode);
David Howells31143d52007-05-09 02:33:46 -07001599 __be32 *bp;
1600
David Howells30062bd2018-10-20 00:57:58 +01001601 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1602 return yfs_fs_setattr(fc, attr);
1603
David Howells31143d52007-05-09 02:33:46 -07001604 if (attr->ia_valid & ATTR_SIZE)
David Howellsd2ddc772017-11-02 15:27:50 +00001605 return afs_fs_setattr_size(fc, attr);
David Howells31143d52007-05-09 02:33:46 -07001606
David Howells3b6492d2018-10-20 00:57:57 +01001607 _enter(",%x,{%llx:%llu},,",
David Howellsd2ddc772017-11-02 15:27:50 +00001608 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
David Howells31143d52007-05-09 02:33:46 -07001609
David Howellsf044c882017-11-02 15:27:45 +00001610 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
David Howells31143d52007-05-09 02:33:46 -07001611 (4 + 6) * 4,
1612 (21 + 6) * 4);
1613 if (!call)
1614 return -ENOMEM;
1615
David Howellsd2ddc772017-11-02 15:27:50 +00001616 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001617 call->reply[0] = vnode;
David Howells0c3a5ac2018-04-06 14:17:24 +01001618 call->expected_version = vnode->status.data_version;
David Howells31143d52007-05-09 02:33:46 -07001619
1620 /* marshall the parameters */
1621 bp = call->request;
1622 *bp++ = htonl(FSSTORESTATUS);
1623 *bp++ = htonl(vnode->fid.vid);
1624 *bp++ = htonl(vnode->fid.vnode);
1625 *bp++ = htonl(vnode->fid.unique);
1626
1627 xdr_encode_AFS_StoreStatus(&bp, attr);
1628
David Howellsd2ddc772017-11-02 15:27:50 +00001629 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001630 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001631 afs_make_call(&fc->ac, call, GFP_NOFS);
1632 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells31143d52007-05-09 02:33:46 -07001633}
David Howells45222b92007-05-10 22:22:20 -07001634
1635/*
1636 * deliver reply data to an FS.GetVolumeStatus
1637 */
David Howellsd0016482016-08-30 20:42:14 +01001638static int afs_deliver_fs_get_volume_status(struct afs_call *call)
David Howells45222b92007-05-10 22:22:20 -07001639{
1640 const __be32 *bp;
1641 char *p;
David Howells12bdcf32018-10-20 00:57:56 +01001642 u32 size;
David Howells45222b92007-05-10 22:22:20 -07001643 int ret;
1644
David Howellsd0016482016-08-30 20:42:14 +01001645 _enter("{%u}", call->unmarshall);
David Howells45222b92007-05-10 22:22:20 -07001646
1647 switch (call->unmarshall) {
1648 case 0:
David Howells45222b92007-05-10 22:22:20 -07001649 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001650 afs_extract_to_buf(call, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001651
1652 /* extract the returned status record */
1653 case 1:
1654 _debug("extract status");
David Howells12bdcf32018-10-20 00:57:56 +01001655 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001656 if (ret < 0)
1657 return ret;
David Howells45222b92007-05-10 22:22:20 -07001658
1659 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001660 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
David Howells45222b92007-05-10 22:22:20 -07001661 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01001662 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001663
1664 /* extract the volume name length */
1665 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01001666 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001667 if (ret < 0)
1668 return ret;
David Howells45222b92007-05-10 22:22:20 -07001669
1670 call->count = ntohl(call->tmp);
1671 _debug("volname length: %u", call->count);
1672 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001673 return afs_protocol_error(call, -EBADMSG,
1674 afs_eproto_volname_len);
David Howells12bdcf32018-10-20 00:57:56 +01001675 size = (call->count + 3) & ~3; /* It's padded */
1676 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001677 call->unmarshall++;
1678
1679 /* extract the volume name */
1680 case 3:
1681 _debug("extract volname");
David Howells12bdcf32018-10-20 00:57:56 +01001682 ret = afs_extract_data(call, true);
1683 if (ret < 0)
1684 return ret;
David Howells45222b92007-05-10 22:22:20 -07001685
David Howells97e30432017-11-02 15:27:48 +00001686 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001687 p[call->count] = 0;
1688 _debug("volname '%s'", p);
David Howells12bdcf32018-10-20 00:57:56 +01001689 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001690 call->unmarshall++;
1691
David Howells45222b92007-05-10 22:22:20 -07001692 /* extract the offline message length */
David Howells12bdcf32018-10-20 00:57:56 +01001693 case 4:
1694 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001695 if (ret < 0)
1696 return ret;
David Howells45222b92007-05-10 22:22:20 -07001697
1698 call->count = ntohl(call->tmp);
1699 _debug("offline msg length: %u", call->count);
1700 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001701 return afs_protocol_error(call, -EBADMSG,
1702 afs_eproto_offline_msg_len);
David Howells12bdcf32018-10-20 00:57:56 +01001703 size = (call->count + 3) & ~3; /* It's padded */
1704 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001705 call->unmarshall++;
1706
1707 /* extract the offline message */
David Howells12bdcf32018-10-20 00:57:56 +01001708 case 5:
David Howells45222b92007-05-10 22:22:20 -07001709 _debug("extract offline");
David Howells12bdcf32018-10-20 00:57:56 +01001710 ret = afs_extract_data(call, true);
1711 if (ret < 0)
1712 return ret;
David Howells45222b92007-05-10 22:22:20 -07001713
David Howells97e30432017-11-02 15:27:48 +00001714 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001715 p[call->count] = 0;
1716 _debug("offline '%s'", p);
1717
David Howells12bdcf32018-10-20 00:57:56 +01001718 afs_extract_to_tmp(call);
David Howells45222b92007-05-10 22:22:20 -07001719 call->unmarshall++;
1720
David Howells45222b92007-05-10 22:22:20 -07001721 /* extract the message of the day length */
David Howells12bdcf32018-10-20 00:57:56 +01001722 case 6:
1723 ret = afs_extract_data(call, true);
David Howells372ee162016-08-03 14:11:40 +01001724 if (ret < 0)
1725 return ret;
David Howells45222b92007-05-10 22:22:20 -07001726
1727 call->count = ntohl(call->tmp);
1728 _debug("motd length: %u", call->count);
1729 if (call->count >= AFSNAMEMAX)
David Howells160cb952018-10-20 00:57:56 +01001730 return afs_protocol_error(call, -EBADMSG,
1731 afs_eproto_motd_len);
David Howells12bdcf32018-10-20 00:57:56 +01001732 size = (call->count + 3) & ~3; /* It's padded */
1733 afs_extract_begin(call, call->reply[2], size);
David Howells45222b92007-05-10 22:22:20 -07001734 call->unmarshall++;
1735
1736 /* extract the message of the day */
David Howells12bdcf32018-10-20 00:57:56 +01001737 case 7:
David Howells45222b92007-05-10 22:22:20 -07001738 _debug("extract motd");
David Howells12bdcf32018-10-20 00:57:56 +01001739 ret = afs_extract_data(call, false);
1740 if (ret < 0)
1741 return ret;
David Howells45222b92007-05-10 22:22:20 -07001742
David Howells97e30432017-11-02 15:27:48 +00001743 p = call->reply[2];
David Howells45222b92007-05-10 22:22:20 -07001744 p[call->count] = 0;
1745 _debug("motd '%s'", p);
1746
David Howells45222b92007-05-10 22:22:20 -07001747 call->unmarshall++;
1748
David Howells12bdcf32018-10-20 00:57:56 +01001749 case 8:
David Howells45222b92007-05-10 22:22:20 -07001750 break;
1751 }
1752
David Howells45222b92007-05-10 22:22:20 -07001753 _leave(" = 0 [done]");
1754 return 0;
1755}
1756
1757/*
1758 * destroy an FS.GetVolumeStatus call
1759 */
1760static void afs_get_volume_status_call_destructor(struct afs_call *call)
1761{
David Howells97e30432017-11-02 15:27:48 +00001762 kfree(call->reply[2]);
1763 call->reply[2] = NULL;
David Howells45222b92007-05-10 22:22:20 -07001764 afs_flat_call_destructor(call);
1765}
1766
1767/*
1768 * FS.GetVolumeStatus operation type
1769 */
1770static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1771 .name = "FS.GetVolumeStatus",
David Howells025db802017-11-02 15:27:51 +00001772 .op = afs_FS_GetVolumeStatus,
David Howells45222b92007-05-10 22:22:20 -07001773 .deliver = afs_deliver_fs_get_volume_status,
David Howells45222b92007-05-10 22:22:20 -07001774 .destructor = afs_get_volume_status_call_destructor,
1775};
1776
1777/*
1778 * fetch the status of a volume
1779 */
David Howells8b2a4642017-11-02 15:27:50 +00001780int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
David Howellsd2ddc772017-11-02 15:27:50 +00001781 struct afs_volume_status *vs)
David Howells45222b92007-05-10 22:22:20 -07001782{
David Howellsd2ddc772017-11-02 15:27:50 +00001783 struct afs_vnode *vnode = fc->vnode;
David Howells45222b92007-05-10 22:22:20 -07001784 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001785 struct afs_net *net = afs_v2net(vnode);
David Howells45222b92007-05-10 22:22:20 -07001786 __be32 *bp;
1787 void *tmpbuf;
1788
David Howells30062bd2018-10-20 00:57:58 +01001789 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1790 return yfs_fs_get_volume_status(fc, vs);
1791
David Howells45222b92007-05-10 22:22:20 -07001792 _enter("");
1793
1794 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1795 if (!tmpbuf)
1796 return -ENOMEM;
1797
David Howellsf044c882017-11-02 15:27:45 +00001798 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
David Howells45222b92007-05-10 22:22:20 -07001799 if (!call) {
1800 kfree(tmpbuf);
1801 return -ENOMEM;
1802 }
1803
David Howellsd2ddc772017-11-02 15:27:50 +00001804 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001805 call->reply[0] = vnode;
1806 call->reply[1] = vs;
1807 call->reply[2] = tmpbuf;
David Howells45222b92007-05-10 22:22:20 -07001808
1809 /* marshall the parameters */
1810 bp = call->request;
1811 bp[0] = htonl(FSGETVOLUMESTATUS);
1812 bp[1] = htonl(vnode->fid.vid);
1813
David Howellsd2ddc772017-11-02 15:27:50 +00001814 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001815 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001816 afs_make_call(&fc->ac, call, GFP_NOFS);
1817 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells45222b92007-05-10 22:22:20 -07001818}
David Howellse8d6c552007-07-15 23:40:12 -07001819
1820/*
1821 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1822 */
David Howellsd0016482016-08-30 20:42:14 +01001823static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
David Howellse8d6c552007-07-15 23:40:12 -07001824{
1825 const __be32 *bp;
David Howells372ee162016-08-03 14:11:40 +01001826 int ret;
David Howellse8d6c552007-07-15 23:40:12 -07001827
David Howellsd0016482016-08-30 20:42:14 +01001828 _enter("{%u}", call->unmarshall);
David Howellse8d6c552007-07-15 23:40:12 -07001829
David Howellsd0016482016-08-30 20:42:14 +01001830 ret = afs_transfer_reply(call);
David Howells372ee162016-08-03 14:11:40 +01001831 if (ret < 0)
1832 return ret;
David Howellse8d6c552007-07-15 23:40:12 -07001833
1834 /* unmarshall the reply once we've received all of it */
1835 bp = call->buffer;
David Howells97e30432017-11-02 15:27:48 +00001836 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
David Howellse8d6c552007-07-15 23:40:12 -07001837
1838 _leave(" = 0 [done]");
1839 return 0;
1840}
1841
1842/*
1843 * FS.SetLock operation type
1844 */
1845static const struct afs_call_type afs_RXFSSetLock = {
1846 .name = "FS.SetLock",
David Howells025db802017-11-02 15:27:51 +00001847 .op = afs_FS_SetLock,
David Howellse8d6c552007-07-15 23:40:12 -07001848 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001849 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001850 .destructor = afs_flat_call_destructor,
1851};
1852
1853/*
1854 * FS.ExtendLock operation type
1855 */
1856static const struct afs_call_type afs_RXFSExtendLock = {
1857 .name = "FS.ExtendLock",
David Howells025db802017-11-02 15:27:51 +00001858 .op = afs_FS_ExtendLock,
David Howellse8d6c552007-07-15 23:40:12 -07001859 .deliver = afs_deliver_fs_xxxx_lock,
David Howellsa690f602019-04-25 14:26:50 +01001860 .done = afs_lock_op_done,
David Howellse8d6c552007-07-15 23:40:12 -07001861 .destructor = afs_flat_call_destructor,
1862};
1863
1864/*
1865 * FS.ReleaseLock operation type
1866 */
1867static const struct afs_call_type afs_RXFSReleaseLock = {
1868 .name = "FS.ReleaseLock",
David Howells025db802017-11-02 15:27:51 +00001869 .op = afs_FS_ReleaseLock,
David Howellse8d6c552007-07-15 23:40:12 -07001870 .deliver = afs_deliver_fs_xxxx_lock,
David Howellse8d6c552007-07-15 23:40:12 -07001871 .destructor = afs_flat_call_destructor,
1872};
1873
1874/*
David Howellsd2ddc772017-11-02 15:27:50 +00001875 * Set a lock on a file
David Howellse8d6c552007-07-15 23:40:12 -07001876 */
David Howellsd2ddc772017-11-02 15:27:50 +00001877int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
David Howellse8d6c552007-07-15 23:40:12 -07001878{
David Howellsd2ddc772017-11-02 15:27:50 +00001879 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001880 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001881 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001882 __be32 *bp;
1883
David Howells30062bd2018-10-20 00:57:58 +01001884 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1885 return yfs_fs_set_lock(fc, type);
1886
David Howellse8d6c552007-07-15 23:40:12 -07001887 _enter("");
1888
David Howellsf044c882017-11-02 15:27:45 +00001889 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001890 if (!call)
1891 return -ENOMEM;
1892
David Howellsd2ddc772017-11-02 15:27:50 +00001893 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001894 call->reply[0] = vnode;
David Howellsa690f602019-04-25 14:26:50 +01001895 call->want_reply_time = true;
David Howellse8d6c552007-07-15 23:40:12 -07001896
1897 /* marshall the parameters */
1898 bp = call->request;
1899 *bp++ = htonl(FSSETLOCK);
1900 *bp++ = htonl(vnode->fid.vid);
1901 *bp++ = htonl(vnode->fid.vnode);
1902 *bp++ = htonl(vnode->fid.unique);
1903 *bp++ = htonl(type);
1904
David Howellsd2ddc772017-11-02 15:27:50 +00001905 afs_use_fs_server(call, fc->cbi);
David Howells6c6c1d62019-04-25 14:26:52 +01001906 trace_afs_make_fs_calli(call, &vnode->fid, type);
David Howells0b9bf382019-04-25 14:26:50 +01001907 afs_make_call(&fc->ac, call, GFP_NOFS);
1908 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellse8d6c552007-07-15 23:40:12 -07001909}
1910
1911/*
1912 * extend a lock on a file
1913 */
David Howellsd2ddc772017-11-02 15:27:50 +00001914int afs_fs_extend_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001915{
David Howellsd2ddc772017-11-02 15:27:50 +00001916 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001917 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001918 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001919 __be32 *bp;
1920
David Howells30062bd2018-10-20 00:57:58 +01001921 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1922 return yfs_fs_extend_lock(fc);
1923
David Howellse8d6c552007-07-15 23:40:12 -07001924 _enter("");
1925
David Howellsf044c882017-11-02 15:27:45 +00001926 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001927 if (!call)
1928 return -ENOMEM;
1929
David Howellsd2ddc772017-11-02 15:27:50 +00001930 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001931 call->reply[0] = vnode;
David Howellsa690f602019-04-25 14:26:50 +01001932 call->want_reply_time = true;
David Howellse8d6c552007-07-15 23:40:12 -07001933
1934 /* marshall the parameters */
1935 bp = call->request;
1936 *bp++ = htonl(FSEXTENDLOCK);
1937 *bp++ = htonl(vnode->fid.vid);
1938 *bp++ = htonl(vnode->fid.vnode);
1939 *bp++ = htonl(vnode->fid.unique);
1940
David Howellsd2ddc772017-11-02 15:27:50 +00001941 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001942 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001943 afs_make_call(&fc->ac, call, GFP_NOFS);
1944 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellse8d6c552007-07-15 23:40:12 -07001945}
1946
1947/*
1948 * release a lock on a file
1949 */
David Howellsd2ddc772017-11-02 15:27:50 +00001950int afs_fs_release_lock(struct afs_fs_cursor *fc)
David Howellse8d6c552007-07-15 23:40:12 -07001951{
David Howellsd2ddc772017-11-02 15:27:50 +00001952 struct afs_vnode *vnode = fc->vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001953 struct afs_call *call;
David Howellsf044c882017-11-02 15:27:45 +00001954 struct afs_net *net = afs_v2net(vnode);
David Howellse8d6c552007-07-15 23:40:12 -07001955 __be32 *bp;
1956
David Howells30062bd2018-10-20 00:57:58 +01001957 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
1958 return yfs_fs_release_lock(fc);
1959
David Howellse8d6c552007-07-15 23:40:12 -07001960 _enter("");
1961
David Howellsf044c882017-11-02 15:27:45 +00001962 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
David Howellse8d6c552007-07-15 23:40:12 -07001963 if (!call)
1964 return -ENOMEM;
1965
David Howellsd2ddc772017-11-02 15:27:50 +00001966 call->key = fc->key;
David Howells97e30432017-11-02 15:27:48 +00001967 call->reply[0] = vnode;
David Howellse8d6c552007-07-15 23:40:12 -07001968
1969 /* marshall the parameters */
1970 bp = call->request;
1971 *bp++ = htonl(FSRELEASELOCK);
1972 *bp++ = htonl(vnode->fid.vid);
1973 *bp++ = htonl(vnode->fid.vnode);
1974 *bp++ = htonl(vnode->fid.unique);
1975
David Howellsd2ddc772017-11-02 15:27:50 +00001976 afs_use_fs_server(call, fc->cbi);
David Howells025db802017-11-02 15:27:51 +00001977 trace_afs_make_fs_call(call, &vnode->fid);
David Howells0b9bf382019-04-25 14:26:50 +01001978 afs_make_call(&fc->ac, call, GFP_NOFS);
1979 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howellsc435ee32017-11-02 15:27:49 +00001980}
1981
1982/*
1983 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1984 */
1985static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1986{
1987 return afs_transfer_reply(call);
1988}
1989
1990/*
1991 * FS.GiveUpAllCallBacks operation type
1992 */
1993static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1994 .name = "FS.GiveUpAllCallBacks",
David Howells025db802017-11-02 15:27:51 +00001995 .op = afs_FS_GiveUpAllCallBacks,
David Howellsc435ee32017-11-02 15:27:49 +00001996 .deliver = afs_deliver_fs_give_up_all_callbacks,
1997 .destructor = afs_flat_call_destructor,
1998};
1999
2000/*
2001 * Flush all the callbacks we have on a server.
2002 */
David Howellsd2ddc772017-11-02 15:27:50 +00002003int afs_fs_give_up_all_callbacks(struct afs_net *net,
2004 struct afs_server *server,
David Howells8b2a4642017-11-02 15:27:50 +00002005 struct afs_addr_cursor *ac,
David Howellsd2ddc772017-11-02 15:27:50 +00002006 struct key *key)
David Howellsc435ee32017-11-02 15:27:49 +00002007{
2008 struct afs_call *call;
2009 __be32 *bp;
2010
2011 _enter("");
2012
David Howellsd2ddc772017-11-02 15:27:50 +00002013 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
David Howellsc435ee32017-11-02 15:27:49 +00002014 if (!call)
2015 return -ENOMEM;
2016
2017 call->key = key;
2018
2019 /* marshall the parameters */
2020 bp = call->request;
2021 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
2022
2023 /* Can't take a ref on server */
David Howells0b9bf382019-04-25 14:26:50 +01002024 afs_make_call(ac, call, GFP_NOFS);
2025 return afs_wait_for_call_to_complete(call, ac);
David Howellsd2ddc772017-11-02 15:27:50 +00002026}
2027
2028/*
2029 * Deliver reply data to an FS.GetCapabilities operation.
2030 */
2031static int afs_deliver_fs_get_capabilities(struct afs_call *call)
2032{
2033 u32 count;
2034 int ret;
2035
David Howells12bdcf32018-10-20 00:57:56 +01002036 _enter("{%u,%zu}", call->unmarshall, iov_iter_count(&call->iter));
David Howellsd2ddc772017-11-02 15:27:50 +00002037
David Howellsd2ddc772017-11-02 15:27:50 +00002038 switch (call->unmarshall) {
2039 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01002040 afs_extract_to_tmp(call);
David Howellsd2ddc772017-11-02 15:27:50 +00002041 call->unmarshall++;
2042
2043 /* Extract the capabilities word count */
2044 case 1:
David Howells12bdcf32018-10-20 00:57:56 +01002045 ret = afs_extract_data(call, true);
David Howellsd2ddc772017-11-02 15:27:50 +00002046 if (ret < 0)
2047 return ret;
2048
2049 count = ntohl(call->tmp);
2050
2051 call->count = count;
2052 call->count2 = count;
David Howells12bdcf32018-10-20 00:57:56 +01002053 iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
David Howellsd2ddc772017-11-02 15:27:50 +00002054 call->unmarshall++;
2055
2056 /* Extract capabilities words */
2057 case 2:
David Howells12bdcf32018-10-20 00:57:56 +01002058 ret = afs_extract_data(call, false);
David Howellsd2ddc772017-11-02 15:27:50 +00002059 if (ret < 0)
2060 return ret;
2061
2062 /* TODO: Examine capabilities */
2063
David Howellsd2ddc772017-11-02 15:27:50 +00002064 call->unmarshall++;
2065 break;
2066 }
2067
2068 _leave(" = 0 [done]");
2069 return 0;
2070}
2071
David Howells3bf0fb62018-10-20 00:57:59 +01002072static void afs_destroy_fs_get_capabilities(struct afs_call *call)
2073{
2074 struct afs_server *server = call->reply[0];
2075
2076 afs_put_server(call->net, server);
2077 afs_flat_call_destructor(call);
2078}
2079
David Howellsd2ddc772017-11-02 15:27:50 +00002080/*
2081 * FS.GetCapabilities operation type
2082 */
2083static const struct afs_call_type afs_RXFSGetCapabilities = {
2084 .name = "FS.GetCapabilities",
David Howells025db802017-11-02 15:27:51 +00002085 .op = afs_FS_GetCapabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00002086 .deliver = afs_deliver_fs_get_capabilities,
David Howells3bf0fb62018-10-20 00:57:59 +01002087 .done = afs_fileserver_probe_result,
2088 .destructor = afs_destroy_fs_get_capabilities,
David Howellsd2ddc772017-11-02 15:27:50 +00002089};
2090
2091/*
2092 * Probe a fileserver for the capabilities that it supports. This can
2093 * return up to 196 words.
2094 */
David Howells0b9bf382019-04-25 14:26:50 +01002095struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
2096 struct afs_server *server,
2097 struct afs_addr_cursor *ac,
2098 struct key *key,
2099 unsigned int server_index)
David Howellsd2ddc772017-11-02 15:27:50 +00002100{
2101 struct afs_call *call;
2102 __be32 *bp;
2103
2104 _enter("");
2105
2106 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
2107 if (!call)
David Howells0b9bf382019-04-25 14:26:50 +01002108 return ERR_PTR(-ENOMEM);
David Howellsd2ddc772017-11-02 15:27:50 +00002109
2110 call->key = key;
David Howells3bf0fb62018-10-20 00:57:59 +01002111 call->reply[0] = afs_get_server(server);
2112 call->reply[1] = (void *)(long)server_index;
David Howells30062bd2018-10-20 00:57:58 +01002113 call->upgrade = true;
David Howells3bf0fb62018-10-20 00:57:59 +01002114 call->want_reply_time = true;
David Howells0b9bf382019-04-25 14:26:50 +01002115 call->async = true;
David Howellsd2ddc772017-11-02 15:27:50 +00002116
2117 /* marshall the parameters */
2118 bp = call->request;
2119 *bp++ = htonl(FSGETCAPABILITIES);
2120
2121 /* Can't take a ref on server */
David Howells025db802017-11-02 15:27:51 +00002122 trace_afs_make_fs_call(call, NULL);
David Howells0b9bf382019-04-25 14:26:50 +01002123 afs_make_call(ac, call, GFP_NOFS);
2124 return call;
David Howellse8d6c552007-07-15 23:40:12 -07002125}
David Howells5cf9dd52018-04-09 21:12:31 +01002126
2127/*
2128 * Deliver reply data to an FS.FetchStatus with no vnode.
2129 */
2130static int afs_deliver_fs_fetch_status(struct afs_call *call)
2131{
2132 struct afs_file_status *status = call->reply[1];
2133 struct afs_callback *callback = call->reply[2];
2134 struct afs_volsync *volsync = call->reply[3];
David Howells36bb5f42018-10-20 00:57:58 +01002135 struct afs_fid *fid = call->reply[0];
David Howells5cf9dd52018-04-09 21:12:31 +01002136 const __be32 *bp;
2137 int ret;
2138
2139 ret = afs_transfer_reply(call);
2140 if (ret < 0)
2141 return ret;
2142
David Howells36bb5f42018-10-20 00:57:58 +01002143 _enter("{%llx:%llu}", fid->vid, fid->vnode);
David Howells5cf9dd52018-04-09 21:12:31 +01002144
2145 /* unmarshall the reply once we've received all of it */
2146 bp = call->buffer;
David Howells36bb5f42018-10-20 00:57:58 +01002147 ret = afs_decode_status(call, &bp, status, NULL,
David Howells160cb952018-10-20 00:57:56 +01002148 &call->expected_version, NULL);
2149 if (ret < 0)
2150 return ret;
David Howells12d8e952018-10-20 00:57:58 +01002151 xdr_decode_AFSCallBack_raw(call, &bp, callback);
David Howells30062bd2018-10-20 00:57:58 +01002152 xdr_decode_AFSVolSync(&bp, volsync);
David Howells5cf9dd52018-04-09 21:12:31 +01002153
2154 _leave(" = 0 [done]");
2155 return 0;
2156}
2157
2158/*
2159 * FS.FetchStatus operation type
2160 */
2161static const struct afs_call_type afs_RXFSFetchStatus = {
2162 .name = "FS.FetchStatus",
2163 .op = afs_FS_FetchStatus,
2164 .deliver = afs_deliver_fs_fetch_status,
2165 .destructor = afs_flat_call_destructor,
2166};
2167
2168/*
2169 * Fetch the status information for a fid without needing a vnode handle.
2170 */
2171int afs_fs_fetch_status(struct afs_fs_cursor *fc,
2172 struct afs_net *net,
2173 struct afs_fid *fid,
2174 struct afs_file_status *status,
2175 struct afs_callback *callback,
2176 struct afs_volsync *volsync)
2177{
2178 struct afs_call *call;
2179 __be32 *bp;
2180
David Howells30062bd2018-10-20 00:57:58 +01002181 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
2182 return yfs_fs_fetch_status(fc, net, fid, status, callback, volsync);
2183
David Howells3b6492d2018-10-20 00:57:57 +01002184 _enter(",%x,{%llx:%llu},,",
David Howells5cf9dd52018-04-09 21:12:31 +01002185 key_serial(fc->key), fid->vid, fid->vnode);
2186
2187 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
2188 if (!call) {
2189 fc->ac.error = -ENOMEM;
2190 return -ENOMEM;
2191 }
2192
2193 call->key = fc->key;
David Howells36bb5f42018-10-20 00:57:58 +01002194 call->reply[0] = fid;
David Howells5cf9dd52018-04-09 21:12:31 +01002195 call->reply[1] = status;
2196 call->reply[2] = callback;
2197 call->reply[3] = volsync;
David Howells0c3a5ac2018-04-06 14:17:24 +01002198 call->expected_version = 1; /* vnode->status.data_version */
David Howells12d8e952018-10-20 00:57:58 +01002199 call->want_reply_time = true;
David Howells5cf9dd52018-04-09 21:12:31 +01002200
2201 /* marshall the parameters */
2202 bp = call->request;
2203 bp[0] = htonl(FSFETCHSTATUS);
2204 bp[1] = htonl(fid->vid);
2205 bp[2] = htonl(fid->vnode);
2206 bp[3] = htonl(fid->unique);
2207
2208 call->cb_break = fc->cb_break;
2209 afs_use_fs_server(call, fc->cbi);
2210 trace_afs_make_fs_call(call, fid);
David Howells0b9bf382019-04-25 14:26:50 +01002211 afs_make_call(&fc->ac, call, GFP_NOFS);
2212 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells5cf9dd52018-04-09 21:12:31 +01002213}
2214
2215/*
2216 * Deliver reply data to an FS.InlineBulkStatus call
2217 */
2218static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
2219{
2220 struct afs_file_status *statuses;
2221 struct afs_callback *callbacks;
2222 struct afs_vnode *vnode = call->reply[0];
2223 const __be32 *bp;
2224 u32 tmp;
2225 int ret;
2226
2227 _enter("{%u}", call->unmarshall);
2228
2229 switch (call->unmarshall) {
2230 case 0:
David Howells12bdcf32018-10-20 00:57:56 +01002231 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002232 call->unmarshall++;
2233
2234 /* Extract the file status count and array in two steps */
2235 case 1:
2236 _debug("extract status count");
David Howells12bdcf32018-10-20 00:57:56 +01002237 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002238 if (ret < 0)
2239 return ret;
2240
2241 tmp = ntohl(call->tmp);
2242 _debug("status count: %u/%u", tmp, call->count2);
2243 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002244 return afs_protocol_error(call, -EBADMSG,
2245 afs_eproto_ibulkst_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002246
2247 call->count = 0;
2248 call->unmarshall++;
2249 more_counts:
David Howells12bdcf32018-10-20 00:57:56 +01002250 afs_extract_to_buf(call, 21 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002251
2252 case 2:
2253 _debug("extract status array %u", call->count);
David Howells12bdcf32018-10-20 00:57:56 +01002254 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002255 if (ret < 0)
2256 return ret;
2257
2258 bp = call->buffer;
2259 statuses = call->reply[1];
David Howells160cb952018-10-20 00:57:56 +01002260 ret = afs_decode_status(call, &bp, &statuses[call->count],
2261 call->count == 0 ? vnode : NULL,
2262 NULL, NULL);
2263 if (ret < 0)
2264 return ret;
David Howells5cf9dd52018-04-09 21:12:31 +01002265
2266 call->count++;
2267 if (call->count < call->count2)
2268 goto more_counts;
2269
2270 call->count = 0;
2271 call->unmarshall++;
David Howells12bdcf32018-10-20 00:57:56 +01002272 afs_extract_to_tmp(call);
David Howells5cf9dd52018-04-09 21:12:31 +01002273
2274 /* Extract the callback count and array in two steps */
2275 case 3:
2276 _debug("extract CB count");
David Howells12bdcf32018-10-20 00:57:56 +01002277 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002278 if (ret < 0)
2279 return ret;
2280
2281 tmp = ntohl(call->tmp);
2282 _debug("CB count: %u", tmp);
2283 if (tmp != call->count2)
David Howells160cb952018-10-20 00:57:56 +01002284 return afs_protocol_error(call, -EBADMSG,
2285 afs_eproto_ibulkst_cb_count);
David Howells5cf9dd52018-04-09 21:12:31 +01002286 call->count = 0;
2287 call->unmarshall++;
2288 more_cbs:
David Howells12bdcf32018-10-20 00:57:56 +01002289 afs_extract_to_buf(call, 3 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002290
2291 case 4:
2292 _debug("extract CB array");
David Howells12bdcf32018-10-20 00:57:56 +01002293 ret = afs_extract_data(call, true);
David Howells5cf9dd52018-04-09 21:12:31 +01002294 if (ret < 0)
2295 return ret;
2296
2297 _debug("unmarshall CB array");
2298 bp = call->buffer;
2299 callbacks = call->reply[2];
2300 callbacks[call->count].version = ntohl(bp[0]);
David Howells12d8e952018-10-20 00:57:58 +01002301 callbacks[call->count].expires_at = xdr_decode_expiry(call, ntohl(bp[1]));
David Howells5cf9dd52018-04-09 21:12:31 +01002302 callbacks[call->count].type = ntohl(bp[2]);
2303 statuses = call->reply[1];
2304 if (call->count == 0 && vnode && statuses[0].abort_code == 0)
2305 xdr_decode_AFSCallBack(call, vnode, &bp);
2306 call->count++;
2307 if (call->count < call->count2)
2308 goto more_cbs;
2309
David Howells12bdcf32018-10-20 00:57:56 +01002310 afs_extract_to_buf(call, 6 * sizeof(__be32));
David Howells5cf9dd52018-04-09 21:12:31 +01002311 call->unmarshall++;
2312
2313 case 5:
David Howells12bdcf32018-10-20 00:57:56 +01002314 ret = afs_extract_data(call, false);
David Howells5cf9dd52018-04-09 21:12:31 +01002315 if (ret < 0)
2316 return ret;
2317
2318 bp = call->buffer;
David Howells30062bd2018-10-20 00:57:58 +01002319 xdr_decode_AFSVolSync(&bp, call->reply[3]);
David Howells5cf9dd52018-04-09 21:12:31 +01002320
David Howells5cf9dd52018-04-09 21:12:31 +01002321 call->unmarshall++;
2322
2323 case 6:
2324 break;
2325 }
2326
2327 _leave(" = 0 [done]");
2328 return 0;
2329}
2330
2331/*
2332 * FS.InlineBulkStatus operation type
2333 */
2334static const struct afs_call_type afs_RXFSInlineBulkStatus = {
2335 .name = "FS.InlineBulkStatus",
2336 .op = afs_FS_InlineBulkStatus,
2337 .deliver = afs_deliver_fs_inline_bulk_status,
2338 .destructor = afs_flat_call_destructor,
2339};
2340
2341/*
2342 * Fetch the status information for up to 50 files
2343 */
2344int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2345 struct afs_net *net,
2346 struct afs_fid *fids,
2347 struct afs_file_status *statuses,
2348 struct afs_callback *callbacks,
2349 unsigned int nr_fids,
2350 struct afs_volsync *volsync)
2351{
2352 struct afs_call *call;
2353 __be32 *bp;
2354 int i;
2355
David Howells30062bd2018-10-20 00:57:58 +01002356 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
2357 return yfs_fs_inline_bulk_status(fc, net, fids, statuses, callbacks,
2358 nr_fids, volsync);
2359
David Howells3b6492d2018-10-20 00:57:57 +01002360 _enter(",%x,{%llx:%llu},%u",
David Howells5cf9dd52018-04-09 21:12:31 +01002361 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2362
2363 call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus,
2364 (2 + nr_fids * 3) * 4,
2365 21 * 4);
2366 if (!call) {
2367 fc->ac.error = -ENOMEM;
2368 return -ENOMEM;
2369 }
2370
2371 call->key = fc->key;
2372 call->reply[0] = NULL; /* vnode for fid[0] */
2373 call->reply[1] = statuses;
2374 call->reply[2] = callbacks;
2375 call->reply[3] = volsync;
2376 call->count2 = nr_fids;
David Howells12d8e952018-10-20 00:57:58 +01002377 call->want_reply_time = true;
David Howells5cf9dd52018-04-09 21:12:31 +01002378
2379 /* marshall the parameters */
2380 bp = call->request;
2381 *bp++ = htonl(FSINLINEBULKSTATUS);
2382 *bp++ = htonl(nr_fids);
2383 for (i = 0; i < nr_fids; i++) {
2384 *bp++ = htonl(fids[i].vid);
2385 *bp++ = htonl(fids[i].vnode);
2386 *bp++ = htonl(fids[i].unique);
2387 }
2388
2389 call->cb_break = fc->cb_break;
2390 afs_use_fs_server(call, fc->cbi);
2391 trace_afs_make_fs_call(call, &fids[0]);
David Howells0b9bf382019-04-25 14:26:50 +01002392 afs_make_call(&fc->ac, call, GFP_NOFS);
2393 return afs_wait_for_call_to_complete(call, &fc->ac);
David Howells5cf9dd52018-04-09 21:12:31 +01002394}
David Howells260f0822019-04-25 14:26:52 +01002395
2396/*
2397 * deliver reply data to an FS.FetchACL
2398 */
2399static int afs_deliver_fs_fetch_acl(struct afs_call *call)
2400{
2401 struct afs_vnode *vnode = call->reply[1];
2402 struct afs_acl *acl;
2403 const __be32 *bp;
2404 unsigned int size;
2405 int ret;
2406
2407 _enter("{%u}", call->unmarshall);
2408
2409 switch (call->unmarshall) {
2410 case 0:
2411 afs_extract_to_tmp(call);
2412 call->unmarshall++;
2413
2414 /* extract the returned data length */
2415 case 1:
2416 ret = afs_extract_data(call, true);
2417 if (ret < 0)
2418 return ret;
2419
2420 size = call->count2 = ntohl(call->tmp);
2421 size = round_up(size, 4);
2422
2423 acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
2424 if (!acl)
2425 return -ENOMEM;
2426 call->reply[0] = acl;
2427 acl->size = call->count2;
2428 afs_extract_begin(call, acl->data, size);
2429 call->unmarshall++;
2430
2431 /* extract the returned data */
2432 case 2:
2433 ret = afs_extract_data(call, true);
2434 if (ret < 0)
2435 return ret;
2436
2437 afs_extract_to_buf(call, (21 + 6) * 4);
2438 call->unmarshall++;
2439
2440 /* extract the metadata */
2441 case 3:
2442 ret = afs_extract_data(call, false);
2443 if (ret < 0)
2444 return ret;
2445
2446 bp = call->buffer;
2447 ret = afs_decode_status(call, &bp, &vnode->status, vnode,
2448 &vnode->status.data_version, NULL);
2449 if (ret < 0)
2450 return ret;
2451 xdr_decode_AFSVolSync(&bp, call->reply[2]);
2452
2453 call->unmarshall++;
2454
2455 case 4:
2456 break;
2457 }
2458
2459 _leave(" = 0 [done]");
2460 return 0;
2461}
2462
2463static void afs_destroy_fs_fetch_acl(struct afs_call *call)
2464{
2465 kfree(call->reply[0]);
2466 afs_flat_call_destructor(call);
2467}
2468
2469/*
2470 * FS.FetchACL operation type
2471 */
2472static const struct afs_call_type afs_RXFSFetchACL = {
2473 .name = "FS.FetchACL",
2474 .op = afs_FS_FetchACL,
2475 .deliver = afs_deliver_fs_fetch_acl,
2476 .destructor = afs_destroy_fs_fetch_acl,
2477};
2478
2479/*
2480 * Fetch the ACL for a file.
2481 */
2482struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc)
2483{
2484 struct afs_vnode *vnode = fc->vnode;
2485 struct afs_call *call;
2486 struct afs_net *net = afs_v2net(vnode);
2487 __be32 *bp;
2488
2489 _enter(",%x,{%llx:%llu},,",
2490 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
2491
2492 call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4);
2493 if (!call) {
2494 fc->ac.error = -ENOMEM;
2495 return ERR_PTR(-ENOMEM);
2496 }
2497
2498 call->key = fc->key;
2499 call->reply[0] = NULL;
2500 call->reply[1] = vnode;
2501 call->reply[2] = NULL; /* volsync */
2502 call->ret_reply0 = true;
2503
2504 /* marshall the parameters */
2505 bp = call->request;
2506 bp[0] = htonl(FSFETCHACL);
2507 bp[1] = htonl(vnode->fid.vid);
2508 bp[2] = htonl(vnode->fid.vnode);
2509 bp[3] = htonl(vnode->fid.unique);
2510
2511 call->cb_break = fc->cb_break;
2512 afs_use_fs_server(call, fc->cbi);
2513 trace_afs_make_fs_call(call, &vnode->fid);
2514 afs_make_call(&fc->ac, call, GFP_KERNEL);
2515 return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
2516}
Joe Gorseb10494a2019-04-25 14:26:52 +01002517
2518/*
2519 * FS.StoreACL operation type
2520 */
2521static const struct afs_call_type afs_RXFSStoreACL = {
2522 .name = "FS.StoreACL",
2523 .op = afs_FS_StoreACL,
2524 .deliver = afs_deliver_fs_status_and_vol,
2525 .destructor = afs_flat_call_destructor,
2526};
2527
2528/*
2529 * Fetch the ACL for a file.
2530 */
2531int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl)
2532{
2533 struct afs_vnode *vnode = fc->vnode;
2534 struct afs_call *call;
2535 struct afs_net *net = afs_v2net(vnode);
2536 size_t size;
2537 __be32 *bp;
2538
2539 _enter(",%x,{%llx:%llu},,",
2540 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
2541
2542 size = round_up(acl->size, 4);
2543 call = afs_alloc_flat_call(net, &afs_RXFSStoreACL,
2544 5 * 4 + size, (21 + 6) * 4);
2545 if (!call) {
2546 fc->ac.error = -ENOMEM;
2547 return -ENOMEM;
2548 }
2549
2550 call->key = fc->key;
2551 call->reply[0] = vnode;
2552 call->reply[2] = NULL; /* volsync */
2553
2554 /* marshall the parameters */
2555 bp = call->request;
2556 bp[0] = htonl(FSSTOREACL);
2557 bp[1] = htonl(vnode->fid.vid);
2558 bp[2] = htonl(vnode->fid.vnode);
2559 bp[3] = htonl(vnode->fid.unique);
2560 bp[4] = htonl(acl->size);
2561 memcpy(&bp[5], acl->data, acl->size);
2562 if (acl->size != size)
2563 memset((void *)&bp[5] + acl->size, 0, size - acl->size);
2564
2565 trace_afs_make_fs_call(call, &vnode->fid);
2566 afs_make_call(&fc->ac, call, GFP_KERNEL);
2567 return afs_wait_for_call_to_complete(call, &fc->ac);
2568}