blob: 5aa57929e8c23559c41b8a875f3ea2db43a364dc [file] [log] [blame]
David Howells30062bd2018-10-20 00:57:58 +01001/* YFS File Server client stubs
2 *
3 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
4 * 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 Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/slab.h>
14#include <linux/sched.h>
15#include <linux/circ_buf.h>
16#include <linux/iversion.h>
17#include "internal.h"
18#include "afs_fs.h"
19#include "xdr_fs.h"
20#include "protocol_yfs.h"
21
22static const struct afs_fid afs_zero_fid;
23
24static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
25{
26 call->cbi = afs_get_cb_interest(cbi);
27}
28
29#define xdr_size(x) (sizeof(*x) / sizeof(__be32))
30
31static void xdr_decode_YFSFid(const __be32 **_bp, struct afs_fid *fid)
32{
33 const struct yfs_xdr_YFSFid *x = (const void *)*_bp;
34
35 fid->vid = xdr_to_u64(x->volume);
36 fid->vnode = xdr_to_u64(x->vnode.lo);
37 fid->vnode_hi = ntohl(x->vnode.hi);
38 fid->unique = ntohl(x->vnode.unique);
39 *_bp += xdr_size(x);
40}
41
42static __be32 *xdr_encode_u32(__be32 *bp, u32 n)
43{
44 *bp++ = htonl(n);
45 return bp;
46}
47
48static __be32 *xdr_encode_u64(__be32 *bp, u64 n)
49{
50 struct yfs_xdr_u64 *x = (void *)bp;
51
52 *x = u64_to_xdr(n);
53 return bp + xdr_size(x);
54}
55
56static __be32 *xdr_encode_YFSFid(__be32 *bp, struct afs_fid *fid)
57{
58 struct yfs_xdr_YFSFid *x = (void *)bp;
59
60 x->volume = u64_to_xdr(fid->vid);
61 x->vnode.lo = u64_to_xdr(fid->vnode);
62 x->vnode.hi = htonl(fid->vnode_hi);
63 x->vnode.unique = htonl(fid->unique);
64 return bp + xdr_size(x);
65}
66
67static size_t xdr_strlen(unsigned int len)
68{
69 return sizeof(__be32) + round_up(len, sizeof(__be32));
70}
71
72static __be32 *xdr_encode_string(__be32 *bp, const char *p, unsigned int len)
73{
74 bp = xdr_encode_u32(bp, len);
75 bp = memcpy(bp, p, len);
76 if (len & 3) {
77 unsigned int pad = 4 - (len & 3);
78
79 memset((u8 *)bp + len, 0, pad);
80 len += pad;
81 }
82
83 return bp + len / sizeof(__be32);
84}
85
86static s64 linux_to_yfs_time(const struct timespec64 *t)
87{
88 /* Convert to 100ns intervals. */
89 return (u64)t->tv_sec * 10000000 + t->tv_nsec/100;
90}
91
92static __be32 *xdr_encode_YFSStoreStatus_mode(__be32 *bp, mode_t mode)
93{
94 struct yfs_xdr_YFSStoreStatus *x = (void *)bp;
95
96 x->mask = htonl(AFS_SET_MODE);
97 x->mode = htonl(mode & S_IALLUGO);
98 x->mtime_client = u64_to_xdr(0);
99 x->owner = u64_to_xdr(0);
100 x->group = u64_to_xdr(0);
101 return bp + xdr_size(x);
102}
103
104static __be32 *xdr_encode_YFSStoreStatus_mtime(__be32 *bp, const struct timespec64 *t)
105{
106 struct yfs_xdr_YFSStoreStatus *x = (void *)bp;
107 s64 mtime = linux_to_yfs_time(t);
108
109 x->mask = htonl(AFS_SET_MTIME);
110 x->mode = htonl(0);
111 x->mtime_client = u64_to_xdr(mtime);
112 x->owner = u64_to_xdr(0);
113 x->group = u64_to_xdr(0);
114 return bp + xdr_size(x);
115}
116
117/*
118 * Convert a signed 100ns-resolution 64-bit time into a timespec.
119 */
120static struct timespec64 yfs_time_to_linux(s64 t)
121{
122 struct timespec64 ts;
123 u64 abs_t;
124
125 /*
126 * Unfortunately can not use normal 64 bit division on 32 bit arch, but
127 * the alternative, do_div, does not work with negative numbers so have
128 * to special case them
129 */
130 if (t < 0) {
131 abs_t = -t;
132 ts.tv_nsec = (time64_t)(do_div(abs_t, 10000000) * 100);
133 ts.tv_nsec = -ts.tv_nsec;
134 ts.tv_sec = -abs_t;
135 } else {
136 abs_t = t;
137 ts.tv_nsec = (time64_t)do_div(abs_t, 10000000) * 100;
138 ts.tv_sec = abs_t;
139 }
140
141 return ts;
142}
143
144static struct timespec64 xdr_to_time(const struct yfs_xdr_u64 xdr)
145{
146 s64 t = xdr_to_u64(xdr);
147
148 return yfs_time_to_linux(t);
149}
150
151static void yfs_check_req(struct afs_call *call, __be32 *bp)
152{
153 size_t len = (void *)bp - call->request;
154
155 if (len > call->request_size)
156 pr_err("kAFS: %s: Request buffer overflow (%zu>%u)\n",
157 call->type->name, len, call->request_size);
158 else if (len < call->request_size)
159 pr_warning("kAFS: %s: Request buffer underflow (%zu<%u)\n",
160 call->type->name, len, call->request_size);
161}
162
163/*
164 * Dump a bad file status record.
165 */
166static void xdr_dump_bad(const __be32 *bp)
167{
168 __be32 x[4];
169 int i;
170
171 pr_notice("YFS XDR: Bad status record\n");
172 for (i = 0; i < 5 * 4 * 4; i += 16) {
173 memcpy(x, bp, 16);
174 bp += 4;
175 pr_notice("%03x: %08x %08x %08x %08x\n",
176 i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
177 }
178
179 memcpy(x, bp, 4);
180 pr_notice("0x50: %08x\n", ntohl(x[0]));
181}
182
183/*
184 * Decode a YFSFetchStatus block
185 */
186static int xdr_decode_YFSFetchStatus(struct afs_call *call,
187 const __be32 **_bp,
188 struct afs_file_status *status,
189 struct afs_vnode *vnode,
190 const afs_dataversion_t *expected_version,
191 struct afs_read *read_req)
192{
193 const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;
194 u32 type;
195 u8 flags = 0;
196
197 status->abort_code = ntohl(xdr->abort_code);
198 if (status->abort_code != 0) {
199 if (vnode && status->abort_code == VNOVNODE) {
200 set_bit(AFS_VNODE_DELETED, &vnode->flags);
201 status->nlink = 0;
202 __afs_break_callback(vnode);
203 }
204 return 0;
205 }
206
207 type = ntohl(xdr->type);
208 switch (type) {
209 case AFS_FTYPE_FILE:
210 case AFS_FTYPE_DIR:
211 case AFS_FTYPE_SYMLINK:
212 if (type != status->type &&
213 vnode &&
214 !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
215 pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n",
216 vnode->fid.vid,
217 vnode->fid.vnode,
218 vnode->fid.unique,
219 status->type, type);
220 goto bad;
221 }
222 status->type = type;
223 break;
224 default:
225 goto bad;
226 }
227
228#define EXTRACT_M4(FIELD) \
229 do { \
230 u32 x = ntohl(xdr->FIELD); \
231 if (status->FIELD != x) { \
232 flags |= AFS_VNODE_META_CHANGED; \
233 status->FIELD = x; \
234 } \
235 } while (0)
236
237#define EXTRACT_M8(FIELD) \
238 do { \
239 u64 x = xdr_to_u64(xdr->FIELD); \
240 if (status->FIELD != x) { \
241 flags |= AFS_VNODE_META_CHANGED; \
242 status->FIELD = x; \
243 } \
244 } while (0)
245
246#define EXTRACT_D8(FIELD) \
247 do { \
248 u64 x = xdr_to_u64(xdr->FIELD); \
249 if (status->FIELD != x) { \
250 flags |= AFS_VNODE_DATA_CHANGED; \
251 status->FIELD = x; \
252 } \
253 } while (0)
254
255 EXTRACT_M4(nlink);
256 EXTRACT_D8(size);
257 EXTRACT_D8(data_version);
258 EXTRACT_M8(author);
259 EXTRACT_M8(owner);
260 EXTRACT_M8(group);
261 EXTRACT_M4(mode);
262 EXTRACT_M4(caller_access); /* call ticket dependent */
263 EXTRACT_M4(anon_access);
264
265 status->mtime_client = xdr_to_time(xdr->mtime_client);
266 status->mtime_server = xdr_to_time(xdr->mtime_server);
267 status->lock_count = ntohl(xdr->lock_count);
268
269 if (read_req) {
270 read_req->data_version = status->data_version;
271 read_req->file_size = status->size;
272 }
273
274 *_bp += xdr_size(xdr);
275
276 if (vnode) {
277 if (test_bit(AFS_VNODE_UNSET, &vnode->flags))
278 flags |= AFS_VNODE_NOT_YET_SET;
279 afs_update_inode_from_status(vnode, status, expected_version,
280 flags);
281 }
282
283 return 0;
284
285bad:
286 xdr_dump_bad(*_bp);
287 return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
288}
289
290/*
291 * Decode the file status. We need to lock the target vnode if we're going to
292 * update its status so that stat() sees the attributes update atomically.
293 */
294static int yfs_decode_status(struct afs_call *call,
295 const __be32 **_bp,
296 struct afs_file_status *status,
297 struct afs_vnode *vnode,
298 const afs_dataversion_t *expected_version,
299 struct afs_read *read_req)
300{
301 int ret;
302
303 if (!vnode)
304 return xdr_decode_YFSFetchStatus(call, _bp, status, vnode,
305 expected_version, read_req);
306
307 write_seqlock(&vnode->cb_lock);
308 ret = xdr_decode_YFSFetchStatus(call, _bp, status, vnode,
309 expected_version, read_req);
310 write_sequnlock(&vnode->cb_lock);
311 return ret;
312}
313
314/*
315 * Decode a YFSCallBack block
316 */
317static void xdr_decode_YFSCallBack(struct afs_call *call,
318 struct afs_vnode *vnode,
319 const __be32 **_bp)
320{
321 struct yfs_xdr_YFSCallBack *xdr = (void *)*_bp;
322 struct afs_cb_interest *old, *cbi = call->cbi;
323 u64 cb_expiry;
324
325 write_seqlock(&vnode->cb_lock);
326
David Howells18ac6182018-10-20 00:57:59 +0100327 if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) {
David Howells30062bd2018-10-20 00:57:58 +0100328 cb_expiry = xdr_to_u64(xdr->expiration_time);
329 do_div(cb_expiry, 10 * 1000 * 1000);
330 vnode->cb_version = ntohl(xdr->version);
331 vnode->cb_type = ntohl(xdr->type);
332 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
333 old = vnode->cb_interest;
334 if (old != call->cbi) {
335 vnode->cb_interest = cbi;
336 cbi = old;
337 }
338 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
339 }
340
341 write_sequnlock(&vnode->cb_lock);
342 call->cbi = cbi;
343 *_bp += xdr_size(xdr);
344}
345
346static void xdr_decode_YFSCallBack_raw(const __be32 **_bp,
347 struct afs_callback *cb)
348{
349 struct yfs_xdr_YFSCallBack *x = (void *)*_bp;
350 u64 cb_expiry;
351
352 cb_expiry = xdr_to_u64(x->expiration_time);
353 do_div(cb_expiry, 10 * 1000 * 1000);
354 cb->version = ntohl(x->version);
355 cb->type = ntohl(x->type);
356 cb->expires_at = cb_expiry + ktime_get_real_seconds();
357
358 *_bp += xdr_size(x);
359}
360
361/*
362 * Decode a YFSVolSync block
363 */
364static void xdr_decode_YFSVolSync(const __be32 **_bp,
365 struct afs_volsync *volsync)
366{
367 struct yfs_xdr_YFSVolSync *x = (void *)*_bp;
368 u64 creation;
369
370 if (volsync) {
371 creation = xdr_to_u64(x->vol_creation_date);
372 do_div(creation, 10 * 1000 * 1000);
373 volsync->creation = creation;
374 }
375
376 *_bp += xdr_size(x);
377}
378
379/*
380 * Encode the requested attributes into a YFSStoreStatus block
381 */
382static __be32 *xdr_encode_YFS_StoreStatus(__be32 *bp, struct iattr *attr)
383{
384 struct yfs_xdr_YFSStoreStatus *x = (void *)bp;
385 s64 mtime = 0, owner = 0, group = 0;
386 u32 mask = 0, mode = 0;
387
388 mask = 0;
389 if (attr->ia_valid & ATTR_MTIME) {
390 mask |= AFS_SET_MTIME;
391 mtime = linux_to_yfs_time(&attr->ia_mtime);
392 }
393
394 if (attr->ia_valid & ATTR_UID) {
395 mask |= AFS_SET_OWNER;
396 owner = from_kuid(&init_user_ns, attr->ia_uid);
397 }
398
399 if (attr->ia_valid & ATTR_GID) {
400 mask |= AFS_SET_GROUP;
401 group = from_kgid(&init_user_ns, attr->ia_gid);
402 }
403
404 if (attr->ia_valid & ATTR_MODE) {
405 mask |= AFS_SET_MODE;
406 mode = attr->ia_mode & S_IALLUGO;
407 }
408
409 x->mask = htonl(mask);
410 x->mode = htonl(mode);
411 x->mtime_client = u64_to_xdr(mtime);
412 x->owner = u64_to_xdr(owner);
413 x->group = u64_to_xdr(group);
414 return bp + xdr_size(x);
415}
416
417/*
418 * Decode a YFSFetchVolumeStatus block.
419 */
420static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp,
421 struct afs_volume_status *vs)
422{
423 const struct yfs_xdr_YFSFetchVolumeStatus *x = (const void *)*_bp;
424 u32 flags;
425
426 vs->vid = xdr_to_u64(x->vid);
427 vs->parent_id = xdr_to_u64(x->parent_id);
428 flags = ntohl(x->flags);
429 vs->online = flags & yfs_FVSOnline;
430 vs->in_service = flags & yfs_FVSInservice;
431 vs->blessed = flags & yfs_FVSBlessed;
432 vs->needs_salvage = flags & yfs_FVSNeedsSalvage;
433 vs->type = ntohl(x->type);
434 vs->min_quota = 0;
435 vs->max_quota = xdr_to_u64(x->max_quota);
436 vs->blocks_in_use = xdr_to_u64(x->blocks_in_use);
437 vs->part_blocks_avail = xdr_to_u64(x->part_blocks_avail);
438 vs->part_max_blocks = xdr_to_u64(x->part_max_blocks);
439 vs->vol_copy_date = xdr_to_u64(x->vol_copy_date);
440 vs->vol_backup_date = xdr_to_u64(x->vol_backup_date);
441 *_bp += sizeof(*x) / sizeof(__be32);
442}
443
444/*
445 * deliver reply data to an FS.FetchStatus
446 */
447static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call)
448{
449 struct afs_vnode *vnode = call->reply[0];
450 const __be32 *bp;
451 int ret;
452
453 ret = afs_transfer_reply(call);
454 if (ret < 0)
455 return ret;
456
457 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
458
459 /* unmarshall the reply once we've received all of it */
460 bp = call->buffer;
461 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
462 &call->expected_version, NULL);
463 if (ret < 0)
464 return ret;
465 xdr_decode_YFSCallBack(call, vnode, &bp);
466 xdr_decode_YFSVolSync(&bp, call->reply[1]);
467
468 _leave(" = 0 [done]");
469 return 0;
470}
471
472/*
473 * YFS.FetchStatus operation type
474 */
475static const struct afs_call_type yfs_RXYFSFetchStatus_vnode = {
476 .name = "YFS.FetchStatus(vnode)",
477 .op = yfs_FS_FetchStatus,
478 .deliver = yfs_deliver_fs_fetch_status_vnode,
479 .destructor = afs_flat_call_destructor,
480};
481
482/*
483 * Fetch the status information for a file.
484 */
485int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync,
486 bool new_inode)
487{
488 struct afs_vnode *vnode = fc->vnode;
489 struct afs_call *call;
490 struct afs_net *net = afs_v2net(vnode);
491 __be32 *bp;
492
493 _enter(",%x,{%llx:%llu},,",
494 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
495
496 call = afs_alloc_flat_call(net, &yfs_RXYFSFetchStatus_vnode,
497 sizeof(__be32) * 2 +
498 sizeof(struct yfs_xdr_YFSFid),
499 sizeof(struct yfs_xdr_YFSFetchStatus) +
500 sizeof(struct yfs_xdr_YFSCallBack) +
501 sizeof(struct yfs_xdr_YFSVolSync));
502 if (!call) {
503 fc->ac.error = -ENOMEM;
504 return -ENOMEM;
505 }
506
507 call->key = fc->key;
508 call->reply[0] = vnode;
509 call->reply[1] = volsync;
510 call->expected_version = new_inode ? 1 : vnode->status.data_version;
511
512 /* marshall the parameters */
513 bp = call->request;
514 bp = xdr_encode_u32(bp, YFSFETCHSTATUS);
515 bp = xdr_encode_u32(bp, 0); /* RPC flags */
516 bp = xdr_encode_YFSFid(bp, &vnode->fid);
517 yfs_check_req(call, bp);
518
519 call->cb_break = fc->cb_break;
520 afs_use_fs_server(call, fc->cbi);
521 trace_afs_make_fs_call(call, &vnode->fid);
522 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
523}
524
525/*
526 * Deliver reply data to an YFS.FetchData64.
527 */
528static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
529{
530 struct afs_vnode *vnode = call->reply[0];
531 struct afs_read *req = call->reply[2];
532 const __be32 *bp;
533 unsigned int size;
534 int ret;
535
536 _enter("{%u,%zu/%llu}",
537 call->unmarshall, iov_iter_count(&call->iter), req->actual_len);
538
539 switch (call->unmarshall) {
540 case 0:
541 req->actual_len = 0;
542 req->index = 0;
543 req->offset = req->pos & (PAGE_SIZE - 1);
544 afs_extract_to_tmp64(call);
545 call->unmarshall++;
546
547 /* extract the returned data length */
548 case 1:
549 _debug("extract data length");
550 ret = afs_extract_data(call, true);
551 if (ret < 0)
552 return ret;
553
554 req->actual_len = be64_to_cpu(call->tmp64);
555 _debug("DATA length: %llu", req->actual_len);
556 req->remain = min(req->len, req->actual_len);
557 if (req->remain == 0)
558 goto no_more_data;
559
560 call->unmarshall++;
561
562 begin_page:
563 ASSERTCMP(req->index, <, req->nr_pages);
564 if (req->remain > PAGE_SIZE - req->offset)
565 size = PAGE_SIZE - req->offset;
566 else
567 size = req->remain;
568 call->bvec[0].bv_len = size;
569 call->bvec[0].bv_offset = req->offset;
570 call->bvec[0].bv_page = req->pages[req->index];
571 iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
572 ASSERTCMP(size, <=, PAGE_SIZE);
573
574 /* extract the returned data */
575 case 2:
576 _debug("extract data %zu/%llu",
577 iov_iter_count(&call->iter), req->remain);
578
579 ret = afs_extract_data(call, true);
580 if (ret < 0)
581 return ret;
582 req->remain -= call->bvec[0].bv_len;
583 req->offset += call->bvec[0].bv_len;
584 ASSERTCMP(req->offset, <=, PAGE_SIZE);
585 if (req->offset == PAGE_SIZE) {
586 req->offset = 0;
587 if (req->page_done)
588 req->page_done(call, req);
589 req->index++;
590 if (req->remain > 0)
591 goto begin_page;
592 }
593
594 ASSERTCMP(req->remain, ==, 0);
595 if (req->actual_len <= req->len)
596 goto no_more_data;
597
598 /* Discard any excess data the server gave us */
599 iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
600 call->unmarshall = 3;
601 case 3:
602 _debug("extract discard %zu/%llu",
603 iov_iter_count(&call->iter), req->actual_len - req->len);
604
605 ret = afs_extract_data(call, true);
606 if (ret < 0)
607 return ret;
608
609 no_more_data:
610 call->unmarshall = 4;
611 afs_extract_to_buf(call,
612 sizeof(struct yfs_xdr_YFSFetchStatus) +
613 sizeof(struct yfs_xdr_YFSCallBack) +
614 sizeof(struct yfs_xdr_YFSVolSync));
615
616 /* extract the metadata */
617 case 4:
618 ret = afs_extract_data(call, false);
619 if (ret < 0)
620 return ret;
621
622 bp = call->buffer;
623 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
624 &vnode->status.data_version, req);
625 if (ret < 0)
626 return ret;
627 xdr_decode_YFSCallBack(call, vnode, &bp);
628 xdr_decode_YFSVolSync(&bp, call->reply[1]);
629
630 call->unmarshall++;
631
632 case 5:
633 break;
634 }
635
636 for (; req->index < req->nr_pages; req->index++) {
637 if (req->offset < PAGE_SIZE)
638 zero_user_segment(req->pages[req->index],
639 req->offset, PAGE_SIZE);
640 if (req->page_done)
641 req->page_done(call, req);
642 req->offset = 0;
643 }
644
645 _leave(" = 0 [done]");
646 return 0;
647}
648
649static void yfs_fetch_data_destructor(struct afs_call *call)
650{
651 struct afs_read *req = call->reply[2];
652
653 afs_put_read(req);
654 afs_flat_call_destructor(call);
655}
656
657/*
658 * YFS.FetchData64 operation type
659 */
660static const struct afs_call_type yfs_RXYFSFetchData64 = {
661 .name = "YFS.FetchData64",
662 .op = yfs_FS_FetchData64,
663 .deliver = yfs_deliver_fs_fetch_data64,
664 .destructor = yfs_fetch_data_destructor,
665};
666
667/*
668 * Fetch data from a file.
669 */
670int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
671{
672 struct afs_vnode *vnode = fc->vnode;
673 struct afs_call *call;
674 struct afs_net *net = afs_v2net(vnode);
675 __be32 *bp;
676
677 _enter(",%x,{%llx:%llu},%llx,%llx",
678 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode,
679 req->pos, req->len);
680
681 call = afs_alloc_flat_call(net, &yfs_RXYFSFetchData64,
682 sizeof(__be32) * 2 +
683 sizeof(struct yfs_xdr_YFSFid) +
684 sizeof(struct yfs_xdr_u64) * 2,
685 sizeof(struct yfs_xdr_YFSFetchStatus) +
686 sizeof(struct yfs_xdr_YFSCallBack) +
687 sizeof(struct yfs_xdr_YFSVolSync));
688 if (!call)
689 return -ENOMEM;
690
691 call->key = fc->key;
692 call->reply[0] = vnode;
693 call->reply[1] = NULL; /* volsync */
694 call->reply[2] = req;
695 call->expected_version = vnode->status.data_version;
696 call->want_reply_time = true;
697
698 /* marshall the parameters */
699 bp = call->request;
700 bp = xdr_encode_u32(bp, YFSFETCHDATA64);
701 bp = xdr_encode_u32(bp, 0); /* RPC flags */
702 bp = xdr_encode_YFSFid(bp, &vnode->fid);
703 bp = xdr_encode_u64(bp, req->pos);
704 bp = xdr_encode_u64(bp, req->len);
705 yfs_check_req(call, bp);
706
707 refcount_inc(&req->usage);
708 call->cb_break = fc->cb_break;
709 afs_use_fs_server(call, fc->cbi);
710 trace_afs_make_fs_call(call, &vnode->fid);
711 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
712}
713
714/*
715 * Deliver reply data for YFS.CreateFile or YFS.MakeDir.
716 */
717static int yfs_deliver_fs_create_vnode(struct afs_call *call)
718{
719 struct afs_vnode *vnode = call->reply[0];
720 const __be32 *bp;
721 int ret;
722
723 _enter("{%u}", call->unmarshall);
724
725 ret = afs_transfer_reply(call);
726 if (ret < 0)
727 return ret;
728
729 /* unmarshall the reply once we've received all of it */
730 bp = call->buffer;
731 xdr_decode_YFSFid(&bp, call->reply[1]);
732 ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
733 if (ret < 0)
734 return ret;
735 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
736 &call->expected_version, NULL);
737 if (ret < 0)
738 return ret;
739 xdr_decode_YFSCallBack_raw(&bp, call->reply[3]);
740 xdr_decode_YFSVolSync(&bp, NULL);
741
742 _leave(" = 0 [done]");
743 return 0;
744}
745
746/*
747 * FS.CreateFile and FS.MakeDir operation type
748 */
749static const struct afs_call_type afs_RXFSCreateFile = {
750 .name = "YFS.CreateFile",
751 .op = yfs_FS_CreateFile,
752 .deliver = yfs_deliver_fs_create_vnode,
753 .destructor = afs_flat_call_destructor,
754};
755
756/*
757 * Create a file.
758 */
759int yfs_fs_create_file(struct afs_fs_cursor *fc,
760 const char *name,
761 umode_t mode,
762 u64 current_data_version,
763 struct afs_fid *newfid,
764 struct afs_file_status *newstatus,
765 struct afs_callback *newcb)
766{
767 struct afs_vnode *vnode = fc->vnode;
768 struct afs_call *call;
769 struct afs_net *net = afs_v2net(vnode);
770 size_t namesz, reqsz, rplsz;
771 __be32 *bp;
772
773 _enter("");
774
775 namesz = strlen(name);
776 reqsz = (sizeof(__be32) +
777 sizeof(__be32) +
778 sizeof(struct yfs_xdr_YFSFid) +
779 xdr_strlen(namesz) +
780 sizeof(struct yfs_xdr_YFSStoreStatus) +
781 sizeof(__be32));
782 rplsz = (sizeof(struct yfs_xdr_YFSFid) +
783 sizeof(struct yfs_xdr_YFSFetchStatus) +
784 sizeof(struct yfs_xdr_YFSFetchStatus) +
785 sizeof(struct yfs_xdr_YFSCallBack) +
786 sizeof(struct yfs_xdr_YFSVolSync));
787
788 call = afs_alloc_flat_call(net, &afs_RXFSCreateFile, reqsz, rplsz);
789 if (!call)
790 return -ENOMEM;
791
792 call->key = fc->key;
793 call->reply[0] = vnode;
794 call->reply[1] = newfid;
795 call->reply[2] = newstatus;
796 call->reply[3] = newcb;
797 call->expected_version = current_data_version + 1;
798
799 /* marshall the parameters */
800 bp = call->request;
801 bp = xdr_encode_u32(bp, YFSCREATEFILE);
802 bp = xdr_encode_u32(bp, 0); /* RPC flags */
803 bp = xdr_encode_YFSFid(bp, &vnode->fid);
804 bp = xdr_encode_string(bp, name, namesz);
805 bp = xdr_encode_YFSStoreStatus_mode(bp, mode);
Marc Dionne5edc22c2019-01-09 17:23:54 +0000806 bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */
David Howells30062bd2018-10-20 00:57:58 +0100807 yfs_check_req(call, bp);
808
809 afs_use_fs_server(call, fc->cbi);
810 trace_afs_make_fs_call(call, &vnode->fid);
811 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
812}
813
814static const struct afs_call_type yfs_RXFSMakeDir = {
815 .name = "YFS.MakeDir",
816 .op = yfs_FS_MakeDir,
817 .deliver = yfs_deliver_fs_create_vnode,
818 .destructor = afs_flat_call_destructor,
819};
820
821/*
822 * Make a directory.
823 */
824int yfs_fs_make_dir(struct afs_fs_cursor *fc,
825 const char *name,
826 umode_t mode,
827 u64 current_data_version,
828 struct afs_fid *newfid,
829 struct afs_file_status *newstatus,
830 struct afs_callback *newcb)
831{
832 struct afs_vnode *vnode = fc->vnode;
833 struct afs_call *call;
834 struct afs_net *net = afs_v2net(vnode);
835 size_t namesz, reqsz, rplsz;
836 __be32 *bp;
837
838 _enter("");
839
840 namesz = strlen(name);
841 reqsz = (sizeof(__be32) +
842 sizeof(struct yfs_xdr_RPCFlags) +
843 sizeof(struct yfs_xdr_YFSFid) +
844 xdr_strlen(namesz) +
845 sizeof(struct yfs_xdr_YFSStoreStatus));
846 rplsz = (sizeof(struct yfs_xdr_YFSFid) +
847 sizeof(struct yfs_xdr_YFSFetchStatus) +
848 sizeof(struct yfs_xdr_YFSFetchStatus) +
849 sizeof(struct yfs_xdr_YFSCallBack) +
850 sizeof(struct yfs_xdr_YFSVolSync));
851
852 call = afs_alloc_flat_call(net, &yfs_RXFSMakeDir, reqsz, rplsz);
853 if (!call)
854 return -ENOMEM;
855
856 call->key = fc->key;
857 call->reply[0] = vnode;
858 call->reply[1] = newfid;
859 call->reply[2] = newstatus;
860 call->reply[3] = newcb;
861 call->expected_version = current_data_version + 1;
862
863 /* marshall the parameters */
864 bp = call->request;
865 bp = xdr_encode_u32(bp, YFSMAKEDIR);
866 bp = xdr_encode_u32(bp, 0); /* RPC flags */
867 bp = xdr_encode_YFSFid(bp, &vnode->fid);
868 bp = xdr_encode_string(bp, name, namesz);
869 bp = xdr_encode_YFSStoreStatus_mode(bp, mode);
870 yfs_check_req(call, bp);
871
872 afs_use_fs_server(call, fc->cbi);
873 trace_afs_make_fs_call(call, &vnode->fid);
874 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
875}
876
877/*
878 * Deliver reply data to a YFS.RemoveFile2 operation.
879 */
880static int yfs_deliver_fs_remove_file2(struct afs_call *call)
881{
882 struct afs_vnode *dvnode = call->reply[0];
883 struct afs_vnode *vnode = call->reply[1];
884 struct afs_fid fid;
885 const __be32 *bp;
886 int ret;
887
888 _enter("{%u}", call->unmarshall);
889
890 ret = afs_transfer_reply(call);
891 if (ret < 0)
892 return ret;
893
894 /* unmarshall the reply once we've received all of it */
895 bp = call->buffer;
896 ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode,
897 &call->expected_version, NULL);
898 if (ret < 0)
899 return ret;
900
901 xdr_decode_YFSFid(&bp, &fid);
902 ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
903 if (ret < 0)
904 return ret;
905 /* Was deleted if vnode->status.abort_code == VNOVNODE. */
906
907 xdr_decode_YFSVolSync(&bp, NULL);
908 return 0;
909}
910
911/*
912 * YFS.RemoveFile2 operation type.
913 */
914static const struct afs_call_type yfs_RXYFSRemoveFile2 = {
915 .name = "YFS.RemoveFile2",
916 .op = yfs_FS_RemoveFile2,
917 .deliver = yfs_deliver_fs_remove_file2,
918 .destructor = afs_flat_call_destructor,
919};
920
921/*
922 * Remove a file and retrieve new file status.
923 */
924int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
925 const char *name, u64 current_data_version)
926{
927 struct afs_vnode *dvnode = fc->vnode;
928 struct afs_call *call;
929 struct afs_net *net = afs_v2net(dvnode);
930 size_t namesz;
931 __be32 *bp;
932
933 _enter("");
934
935 namesz = strlen(name);
936
937 call = afs_alloc_flat_call(net, &yfs_RXYFSRemoveFile2,
938 sizeof(__be32) +
939 sizeof(struct yfs_xdr_RPCFlags) +
940 sizeof(struct yfs_xdr_YFSFid) +
941 xdr_strlen(namesz),
942 sizeof(struct yfs_xdr_YFSFetchStatus) +
943 sizeof(struct yfs_xdr_YFSFid) +
944 sizeof(struct yfs_xdr_YFSFetchStatus) +
945 sizeof(struct yfs_xdr_YFSVolSync));
946 if (!call)
947 return -ENOMEM;
948
949 call->key = fc->key;
950 call->reply[0] = dvnode;
951 call->reply[1] = vnode;
952 call->expected_version = current_data_version + 1;
953
954 /* marshall the parameters */
955 bp = call->request;
956 bp = xdr_encode_u32(bp, YFSREMOVEFILE2);
957 bp = xdr_encode_u32(bp, 0); /* RPC flags */
958 bp = xdr_encode_YFSFid(bp, &dvnode->fid);
959 bp = xdr_encode_string(bp, name, namesz);
960 yfs_check_req(call, bp);
961
962 afs_use_fs_server(call, fc->cbi);
963 trace_afs_make_fs_call(call, &dvnode->fid);
964 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
965}
966
967/*
968 * Deliver reply data to a YFS.RemoveFile or YFS.RemoveDir operation.
969 */
970static int yfs_deliver_fs_remove(struct afs_call *call)
971{
972 struct afs_vnode *dvnode = call->reply[0];
973 const __be32 *bp;
974 int ret;
975
976 _enter("{%u}", call->unmarshall);
977
978 ret = afs_transfer_reply(call);
979 if (ret < 0)
980 return ret;
981
982 /* unmarshall the reply once we've received all of it */
983 bp = call->buffer;
984 ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode,
985 &call->expected_version, NULL);
986 if (ret < 0)
987 return ret;
988
989 xdr_decode_YFSVolSync(&bp, NULL);
990 return 0;
991}
992
993/*
994 * FS.RemoveDir and FS.RemoveFile operation types.
995 */
996static const struct afs_call_type yfs_RXYFSRemoveFile = {
997 .name = "YFS.RemoveFile",
998 .op = yfs_FS_RemoveFile,
999 .deliver = yfs_deliver_fs_remove,
1000 .destructor = afs_flat_call_destructor,
1001};
1002
1003static const struct afs_call_type yfs_RXYFSRemoveDir = {
1004 .name = "YFS.RemoveDir",
1005 .op = yfs_FS_RemoveDir,
1006 .deliver = yfs_deliver_fs_remove,
1007 .destructor = afs_flat_call_destructor,
1008};
1009
1010/*
1011 * remove a file or directory
1012 */
1013int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
1014 const char *name, bool isdir, u64 current_data_version)
1015{
1016 struct afs_vnode *dvnode = fc->vnode;
1017 struct afs_call *call;
1018 struct afs_net *net = afs_v2net(dvnode);
1019 size_t namesz;
1020 __be32 *bp;
1021
1022 _enter("");
1023
1024 namesz = strlen(name);
1025 call = afs_alloc_flat_call(
1026 net, isdir ? &yfs_RXYFSRemoveDir : &yfs_RXYFSRemoveFile,
1027 sizeof(__be32) +
1028 sizeof(struct yfs_xdr_RPCFlags) +
1029 sizeof(struct yfs_xdr_YFSFid) +
1030 xdr_strlen(namesz),
1031 sizeof(struct yfs_xdr_YFSFetchStatus) +
1032 sizeof(struct yfs_xdr_YFSVolSync));
1033 if (!call)
1034 return -ENOMEM;
1035
1036 call->key = fc->key;
1037 call->reply[0] = dvnode;
1038 call->reply[1] = vnode;
1039 call->expected_version = current_data_version + 1;
1040
1041 /* marshall the parameters */
1042 bp = call->request;
1043 bp = xdr_encode_u32(bp, isdir ? YFSREMOVEDIR : YFSREMOVEFILE);
1044 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1045 bp = xdr_encode_YFSFid(bp, &dvnode->fid);
1046 bp = xdr_encode_string(bp, name, namesz);
1047 yfs_check_req(call, bp);
1048
1049 afs_use_fs_server(call, fc->cbi);
1050 trace_afs_make_fs_call(call, &dvnode->fid);
1051 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1052}
1053
1054/*
1055 * Deliver reply data to a YFS.Link operation.
1056 */
1057static int yfs_deliver_fs_link(struct afs_call *call)
1058{
1059 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
1060 const __be32 *bp;
1061 int ret;
1062
1063 _enter("{%u}", call->unmarshall);
1064
1065 ret = afs_transfer_reply(call);
1066 if (ret < 0)
1067 return ret;
1068
1069 /* unmarshall the reply once we've received all of it */
1070 bp = call->buffer;
1071 ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
1072 if (ret < 0)
1073 return ret;
1074 ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode,
1075 &call->expected_version, NULL);
1076 if (ret < 0)
1077 return ret;
1078 xdr_decode_YFSVolSync(&bp, NULL);
1079 _leave(" = 0 [done]");
1080 return 0;
1081}
1082
1083/*
1084 * YFS.Link operation type.
1085 */
1086static const struct afs_call_type yfs_RXYFSLink = {
1087 .name = "YFS.Link",
1088 .op = yfs_FS_Link,
1089 .deliver = yfs_deliver_fs_link,
1090 .destructor = afs_flat_call_destructor,
1091};
1092
1093/*
1094 * Make a hard link.
1095 */
1096int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
1097 const char *name, u64 current_data_version)
1098{
1099 struct afs_vnode *dvnode = fc->vnode;
1100 struct afs_call *call;
1101 struct afs_net *net = afs_v2net(vnode);
1102 size_t namesz;
1103 __be32 *bp;
1104
1105 _enter("");
1106
1107 namesz = strlen(name);
1108 call = afs_alloc_flat_call(net, &yfs_RXYFSLink,
1109 sizeof(__be32) +
1110 sizeof(struct yfs_xdr_RPCFlags) +
1111 sizeof(struct yfs_xdr_YFSFid) +
1112 xdr_strlen(namesz) +
1113 sizeof(struct yfs_xdr_YFSFid),
1114 sizeof(struct yfs_xdr_YFSFetchStatus) +
1115 sizeof(struct yfs_xdr_YFSFetchStatus) +
1116 sizeof(struct yfs_xdr_YFSVolSync));
1117 if (!call)
1118 return -ENOMEM;
1119
1120 call->key = fc->key;
1121 call->reply[0] = dvnode;
1122 call->reply[1] = vnode;
1123 call->expected_version = current_data_version + 1;
1124
1125 /* marshall the parameters */
1126 bp = call->request;
1127 bp = xdr_encode_u32(bp, YFSLINK);
1128 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1129 bp = xdr_encode_YFSFid(bp, &dvnode->fid);
1130 bp = xdr_encode_string(bp, name, namesz);
1131 bp = xdr_encode_YFSFid(bp, &vnode->fid);
1132 yfs_check_req(call, bp);
1133
1134 afs_use_fs_server(call, fc->cbi);
1135 trace_afs_make_fs_call(call, &vnode->fid);
1136 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1137}
1138
1139/*
1140 * Deliver reply data to a YFS.Symlink operation.
1141 */
1142static int yfs_deliver_fs_symlink(struct afs_call *call)
1143{
1144 struct afs_vnode *vnode = call->reply[0];
1145 const __be32 *bp;
1146 int ret;
1147
1148 _enter("{%u}", call->unmarshall);
1149
1150 ret = afs_transfer_reply(call);
1151 if (ret < 0)
1152 return ret;
1153
1154 /* unmarshall the reply once we've received all of it */
1155 bp = call->buffer;
1156 xdr_decode_YFSFid(&bp, call->reply[1]);
1157 ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
1158 if (ret < 0)
1159 return ret;
1160 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
1161 &call->expected_version, NULL);
1162 if (ret < 0)
1163 return ret;
1164 xdr_decode_YFSVolSync(&bp, NULL);
1165
1166 _leave(" = 0 [done]");
1167 return 0;
1168}
1169
1170/*
1171 * YFS.Symlink operation type
1172 */
1173static const struct afs_call_type yfs_RXYFSSymlink = {
1174 .name = "YFS.Symlink",
1175 .op = yfs_FS_Symlink,
1176 .deliver = yfs_deliver_fs_symlink,
1177 .destructor = afs_flat_call_destructor,
1178};
1179
1180/*
1181 * Create a symbolic link.
1182 */
1183int yfs_fs_symlink(struct afs_fs_cursor *fc,
1184 const char *name,
1185 const char *contents,
1186 u64 current_data_version,
1187 struct afs_fid *newfid,
1188 struct afs_file_status *newstatus)
1189{
1190 struct afs_vnode *dvnode = fc->vnode;
1191 struct afs_call *call;
1192 struct afs_net *net = afs_v2net(dvnode);
1193 size_t namesz, contents_sz;
1194 __be32 *bp;
1195
1196 _enter("");
1197
1198 namesz = strlen(name);
1199 contents_sz = strlen(contents);
1200 call = afs_alloc_flat_call(net, &yfs_RXYFSSymlink,
1201 sizeof(__be32) +
1202 sizeof(struct yfs_xdr_RPCFlags) +
1203 sizeof(struct yfs_xdr_YFSFid) +
1204 xdr_strlen(namesz) +
1205 xdr_strlen(contents_sz) +
1206 sizeof(struct yfs_xdr_YFSStoreStatus),
1207 sizeof(struct yfs_xdr_YFSFid) +
1208 sizeof(struct yfs_xdr_YFSFetchStatus) +
1209 sizeof(struct yfs_xdr_YFSFetchStatus) +
1210 sizeof(struct yfs_xdr_YFSVolSync));
1211 if (!call)
1212 return -ENOMEM;
1213
1214 call->key = fc->key;
1215 call->reply[0] = dvnode;
1216 call->reply[1] = newfid;
1217 call->reply[2] = newstatus;
1218 call->expected_version = current_data_version + 1;
1219
1220 /* marshall the parameters */
1221 bp = call->request;
1222 bp = xdr_encode_u32(bp, YFSSYMLINK);
1223 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1224 bp = xdr_encode_YFSFid(bp, &dvnode->fid);
1225 bp = xdr_encode_string(bp, name, namesz);
1226 bp = xdr_encode_string(bp, contents, contents_sz);
1227 bp = xdr_encode_YFSStoreStatus_mode(bp, S_IRWXUGO);
1228 yfs_check_req(call, bp);
1229
1230 afs_use_fs_server(call, fc->cbi);
1231 trace_afs_make_fs_call(call, &dvnode->fid);
1232 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1233}
1234
1235/*
1236 * Deliver reply data to a YFS.Rename operation.
1237 */
1238static int yfs_deliver_fs_rename(struct afs_call *call)
1239{
1240 struct afs_vnode *orig_dvnode = call->reply[0];
1241 struct afs_vnode *new_dvnode = call->reply[1];
1242 const __be32 *bp;
1243 int ret;
1244
1245 _enter("{%u}", call->unmarshall);
1246
1247 ret = afs_transfer_reply(call);
1248 if (ret < 0)
1249 return ret;
1250
1251 /* unmarshall the reply once we've received all of it */
1252 bp = call->buffer;
1253 ret = yfs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
1254 &call->expected_version, NULL);
1255 if (ret < 0)
1256 return ret;
1257 if (new_dvnode != orig_dvnode) {
1258 ret = yfs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
1259 &call->expected_version_2, NULL);
1260 if (ret < 0)
1261 return ret;
1262 }
1263
1264 xdr_decode_YFSVolSync(&bp, NULL);
1265 _leave(" = 0 [done]");
1266 return 0;
1267}
1268
1269/*
1270 * YFS.Rename operation type
1271 */
1272static const struct afs_call_type yfs_RXYFSRename = {
1273 .name = "FS.Rename",
1274 .op = yfs_FS_Rename,
1275 .deliver = yfs_deliver_fs_rename,
1276 .destructor = afs_flat_call_destructor,
1277};
1278
1279/*
1280 * Rename a file or directory.
1281 */
1282int yfs_fs_rename(struct afs_fs_cursor *fc,
1283 const char *orig_name,
1284 struct afs_vnode *new_dvnode,
1285 const char *new_name,
1286 u64 current_orig_data_version,
1287 u64 current_new_data_version)
1288{
1289 struct afs_vnode *orig_dvnode = fc->vnode;
1290 struct afs_call *call;
1291 struct afs_net *net = afs_v2net(orig_dvnode);
1292 size_t o_namesz, n_namesz;
1293 __be32 *bp;
1294
1295 _enter("");
1296
1297 o_namesz = strlen(orig_name);
1298 n_namesz = strlen(new_name);
1299 call = afs_alloc_flat_call(net, &yfs_RXYFSRename,
1300 sizeof(__be32) +
1301 sizeof(struct yfs_xdr_RPCFlags) +
1302 sizeof(struct yfs_xdr_YFSFid) +
1303 xdr_strlen(o_namesz) +
1304 sizeof(struct yfs_xdr_YFSFid) +
1305 xdr_strlen(n_namesz),
1306 sizeof(struct yfs_xdr_YFSFetchStatus) +
1307 sizeof(struct yfs_xdr_YFSFetchStatus) +
1308 sizeof(struct yfs_xdr_YFSVolSync));
1309 if (!call)
1310 return -ENOMEM;
1311
1312 call->key = fc->key;
1313 call->reply[0] = orig_dvnode;
1314 call->reply[1] = new_dvnode;
1315 call->expected_version = current_orig_data_version + 1;
1316 call->expected_version_2 = current_new_data_version + 1;
1317
1318 /* marshall the parameters */
1319 bp = call->request;
1320 bp = xdr_encode_u32(bp, YFSRENAME);
1321 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1322 bp = xdr_encode_YFSFid(bp, &orig_dvnode->fid);
1323 bp = xdr_encode_string(bp, orig_name, o_namesz);
1324 bp = xdr_encode_YFSFid(bp, &new_dvnode->fid);
1325 bp = xdr_encode_string(bp, new_name, n_namesz);
1326 yfs_check_req(call, bp);
1327
1328 afs_use_fs_server(call, fc->cbi);
1329 trace_afs_make_fs_call(call, &orig_dvnode->fid);
1330 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1331}
1332
1333/*
1334 * Deliver reply data to a YFS.StoreData64 operation.
1335 */
1336static int yfs_deliver_fs_store_data(struct afs_call *call)
1337{
1338 struct afs_vnode *vnode = call->reply[0];
1339 const __be32 *bp;
1340 int ret;
1341
1342 _enter("");
1343
1344 ret = afs_transfer_reply(call);
1345 if (ret < 0)
1346 return ret;
1347
1348 /* unmarshall the reply once we've received all of it */
1349 bp = call->buffer;
1350 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
1351 &call->expected_version, NULL);
1352 if (ret < 0)
1353 return ret;
1354 xdr_decode_YFSVolSync(&bp, NULL);
1355
1356 afs_pages_written_back(vnode, call);
1357
1358 _leave(" = 0 [done]");
1359 return 0;
1360}
1361
1362/*
1363 * YFS.StoreData64 operation type.
1364 */
1365static const struct afs_call_type yfs_RXYFSStoreData64 = {
1366 .name = "YFS.StoreData64",
1367 .op = yfs_FS_StoreData64,
1368 .deliver = yfs_deliver_fs_store_data,
1369 .destructor = afs_flat_call_destructor,
1370};
1371
1372/*
1373 * Store a set of pages to a large file.
1374 */
1375int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
1376 pgoff_t first, pgoff_t last,
1377 unsigned offset, unsigned to)
1378{
1379 struct afs_vnode *vnode = fc->vnode;
1380 struct afs_call *call;
1381 struct afs_net *net = afs_v2net(vnode);
1382 loff_t size, pos, i_size;
1383 __be32 *bp;
1384
1385 _enter(",%x,{%llx:%llu},,",
1386 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
1387
1388 size = (loff_t)to - (loff_t)offset;
1389 if (first != last)
1390 size += (loff_t)(last - first) << PAGE_SHIFT;
1391 pos = (loff_t)first << PAGE_SHIFT;
1392 pos += offset;
1393
1394 i_size = i_size_read(&vnode->vfs_inode);
1395 if (pos + size > i_size)
1396 i_size = size + pos;
1397
1398 _debug("size %llx, at %llx, i_size %llx",
1399 (unsigned long long)size, (unsigned long long)pos,
1400 (unsigned long long)i_size);
1401
1402 call = afs_alloc_flat_call(net, &yfs_RXYFSStoreData64,
1403 sizeof(__be32) +
1404 sizeof(__be32) +
1405 sizeof(struct yfs_xdr_YFSFid) +
1406 sizeof(struct yfs_xdr_YFSStoreStatus) +
1407 sizeof(struct yfs_xdr_u64) * 3,
1408 sizeof(struct yfs_xdr_YFSFetchStatus) +
1409 sizeof(struct yfs_xdr_YFSVolSync));
1410 if (!call)
1411 return -ENOMEM;
1412
1413 call->key = fc->key;
1414 call->mapping = mapping;
1415 call->reply[0] = vnode;
1416 call->first = first;
1417 call->last = last;
1418 call->first_offset = offset;
1419 call->last_to = to;
1420 call->send_pages = true;
1421 call->expected_version = vnode->status.data_version + 1;
1422
1423 /* marshall the parameters */
1424 bp = call->request;
1425 bp = xdr_encode_u32(bp, YFSSTOREDATA64);
1426 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1427 bp = xdr_encode_YFSFid(bp, &vnode->fid);
1428 bp = xdr_encode_YFSStoreStatus_mtime(bp, &vnode->vfs_inode.i_mtime);
1429 bp = xdr_encode_u64(bp, pos);
1430 bp = xdr_encode_u64(bp, size);
1431 bp = xdr_encode_u64(bp, i_size);
1432 yfs_check_req(call, bp);
1433
1434 afs_use_fs_server(call, fc->cbi);
1435 trace_afs_make_fs_call(call, &vnode->fid);
1436 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1437}
1438
1439/*
1440 * deliver reply data to an FS.StoreStatus
1441 */
1442static int yfs_deliver_fs_store_status(struct afs_call *call)
1443{
1444 struct afs_vnode *vnode = call->reply[0];
1445 const __be32 *bp;
1446 int ret;
1447
1448 _enter("");
1449
1450 ret = afs_transfer_reply(call);
1451 if (ret < 0)
1452 return ret;
1453
1454 /* unmarshall the reply once we've received all of it */
1455 bp = call->buffer;
1456 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
1457 &call->expected_version, NULL);
1458 if (ret < 0)
1459 return ret;
1460 xdr_decode_YFSVolSync(&bp, NULL);
1461
1462 _leave(" = 0 [done]");
1463 return 0;
1464}
1465
1466/*
1467 * YFS.StoreStatus operation type
1468 */
1469static const struct afs_call_type yfs_RXYFSStoreStatus = {
1470 .name = "YFS.StoreStatus",
1471 .op = yfs_FS_StoreStatus,
1472 .deliver = yfs_deliver_fs_store_status,
1473 .destructor = afs_flat_call_destructor,
1474};
1475
1476static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = {
1477 .name = "YFS.StoreData64",
1478 .op = yfs_FS_StoreData64,
1479 .deliver = yfs_deliver_fs_store_status,
1480 .destructor = afs_flat_call_destructor,
1481};
1482
1483/*
1484 * Set the attributes on a file, using YFS.StoreData64 rather than
1485 * YFS.StoreStatus so as to alter the file size also.
1486 */
1487static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
1488{
1489 struct afs_vnode *vnode = fc->vnode;
1490 struct afs_call *call;
1491 struct afs_net *net = afs_v2net(vnode);
1492 __be32 *bp;
1493
1494 _enter(",%x,{%llx:%llu},,",
1495 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
1496
1497 call = afs_alloc_flat_call(net, &yfs_RXYFSStoreData64_as_Status,
1498 sizeof(__be32) * 2 +
1499 sizeof(struct yfs_xdr_YFSFid) +
1500 sizeof(struct yfs_xdr_YFSStoreStatus) +
1501 sizeof(struct yfs_xdr_u64) * 3,
1502 sizeof(struct yfs_xdr_YFSFetchStatus) +
1503 sizeof(struct yfs_xdr_YFSVolSync));
1504 if (!call)
1505 return -ENOMEM;
1506
1507 call->key = fc->key;
1508 call->reply[0] = vnode;
1509 call->expected_version = vnode->status.data_version + 1;
1510
1511 /* marshall the parameters */
1512 bp = call->request;
1513 bp = xdr_encode_u32(bp, YFSSTOREDATA64);
1514 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1515 bp = xdr_encode_YFSFid(bp, &vnode->fid);
1516 bp = xdr_encode_YFS_StoreStatus(bp, attr);
1517 bp = xdr_encode_u64(bp, 0); /* position of start of write */
1518 bp = xdr_encode_u64(bp, 0); /* size of write */
1519 bp = xdr_encode_u64(bp, attr->ia_size); /* new file length */
1520 yfs_check_req(call, bp);
1521
1522 afs_use_fs_server(call, fc->cbi);
1523 trace_afs_make_fs_call(call, &vnode->fid);
1524 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1525}
1526
1527/*
1528 * Set the attributes on a file, using YFS.StoreData64 if there's a change in
1529 * file size, and YFS.StoreStatus otherwise.
1530 */
1531int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
1532{
1533 struct afs_vnode *vnode = fc->vnode;
1534 struct afs_call *call;
1535 struct afs_net *net = afs_v2net(vnode);
1536 __be32 *bp;
1537
1538 if (attr->ia_valid & ATTR_SIZE)
1539 return yfs_fs_setattr_size(fc, attr);
1540
1541 _enter(",%x,{%llx:%llu},,",
1542 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
1543
1544 call = afs_alloc_flat_call(net, &yfs_RXYFSStoreStatus,
1545 sizeof(__be32) * 2 +
1546 sizeof(struct yfs_xdr_YFSFid) +
1547 sizeof(struct yfs_xdr_YFSStoreStatus),
1548 sizeof(struct yfs_xdr_YFSFetchStatus) +
1549 sizeof(struct yfs_xdr_YFSVolSync));
1550 if (!call)
1551 return -ENOMEM;
1552
1553 call->key = fc->key;
1554 call->reply[0] = vnode;
1555 call->expected_version = vnode->status.data_version;
1556
1557 /* marshall the parameters */
1558 bp = call->request;
1559 bp = xdr_encode_u32(bp, YFSSTORESTATUS);
1560 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1561 bp = xdr_encode_YFSFid(bp, &vnode->fid);
1562 bp = xdr_encode_YFS_StoreStatus(bp, attr);
1563 yfs_check_req(call, bp);
1564
1565 afs_use_fs_server(call, fc->cbi);
1566 trace_afs_make_fs_call(call, &vnode->fid);
1567 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1568}
1569
1570/*
1571 * Deliver reply data to a YFS.GetVolumeStatus operation.
1572 */
1573static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
1574{
1575 const __be32 *bp;
1576 char *p;
1577 u32 size;
1578 int ret;
1579
1580 _enter("{%u}", call->unmarshall);
1581
1582 switch (call->unmarshall) {
1583 case 0:
1584 call->unmarshall++;
1585 afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus));
1586
1587 /* extract the returned status record */
1588 case 1:
1589 _debug("extract status");
1590 ret = afs_extract_data(call, true);
1591 if (ret < 0)
1592 return ret;
1593
1594 bp = call->buffer;
1595 xdr_decode_YFSFetchVolumeStatus(&bp, call->reply[1]);
1596 call->unmarshall++;
1597 afs_extract_to_tmp(call);
1598
1599 /* extract the volume name length */
1600 case 2:
1601 ret = afs_extract_data(call, true);
1602 if (ret < 0)
1603 return ret;
1604
1605 call->count = ntohl(call->tmp);
1606 _debug("volname length: %u", call->count);
1607 if (call->count >= AFSNAMEMAX)
1608 return afs_protocol_error(call, -EBADMSG,
1609 afs_eproto_volname_len);
1610 size = (call->count + 3) & ~3; /* It's padded */
1611 afs_extract_begin(call, call->reply[2], size);
1612 call->unmarshall++;
1613
1614 /* extract the volume name */
1615 case 3:
1616 _debug("extract volname");
1617 ret = afs_extract_data(call, true);
1618 if (ret < 0)
1619 return ret;
1620
1621 p = call->reply[2];
1622 p[call->count] = 0;
1623 _debug("volname '%s'", p);
1624 afs_extract_to_tmp(call);
1625 call->unmarshall++;
1626
1627 /* extract the offline message length */
1628 case 4:
1629 ret = afs_extract_data(call, true);
1630 if (ret < 0)
1631 return ret;
1632
1633 call->count = ntohl(call->tmp);
1634 _debug("offline msg length: %u", call->count);
1635 if (call->count >= AFSNAMEMAX)
1636 return afs_protocol_error(call, -EBADMSG,
1637 afs_eproto_offline_msg_len);
1638 size = (call->count + 3) & ~3; /* It's padded */
1639 afs_extract_begin(call, call->reply[2], size);
1640 call->unmarshall++;
1641
1642 /* extract the offline message */
1643 case 5:
1644 _debug("extract offline");
1645 ret = afs_extract_data(call, true);
1646 if (ret < 0)
1647 return ret;
1648
1649 p = call->reply[2];
1650 p[call->count] = 0;
1651 _debug("offline '%s'", p);
1652
1653 afs_extract_to_tmp(call);
1654 call->unmarshall++;
1655
1656 /* extract the message of the day length */
1657 case 6:
1658 ret = afs_extract_data(call, true);
1659 if (ret < 0)
1660 return ret;
1661
1662 call->count = ntohl(call->tmp);
1663 _debug("motd length: %u", call->count);
1664 if (call->count >= AFSNAMEMAX)
1665 return afs_protocol_error(call, -EBADMSG,
1666 afs_eproto_motd_len);
1667 size = (call->count + 3) & ~3; /* It's padded */
1668 afs_extract_begin(call, call->reply[2], size);
1669 call->unmarshall++;
1670
1671 /* extract the message of the day */
1672 case 7:
1673 _debug("extract motd");
1674 ret = afs_extract_data(call, false);
1675 if (ret < 0)
1676 return ret;
1677
1678 p = call->reply[2];
1679 p[call->count] = 0;
1680 _debug("motd '%s'", p);
1681
1682 call->unmarshall++;
1683
1684 case 8:
1685 break;
1686 }
1687
1688 _leave(" = 0 [done]");
1689 return 0;
1690}
1691
1692/*
1693 * Destroy a YFS.GetVolumeStatus call.
1694 */
1695static void yfs_get_volume_status_call_destructor(struct afs_call *call)
1696{
1697 kfree(call->reply[2]);
1698 call->reply[2] = NULL;
1699 afs_flat_call_destructor(call);
1700}
1701
1702/*
1703 * YFS.GetVolumeStatus operation type
1704 */
1705static const struct afs_call_type yfs_RXYFSGetVolumeStatus = {
1706 .name = "YFS.GetVolumeStatus",
1707 .op = yfs_FS_GetVolumeStatus,
1708 .deliver = yfs_deliver_fs_get_volume_status,
1709 .destructor = yfs_get_volume_status_call_destructor,
1710};
1711
1712/*
1713 * fetch the status of a volume
1714 */
1715int yfs_fs_get_volume_status(struct afs_fs_cursor *fc,
1716 struct afs_volume_status *vs)
1717{
1718 struct afs_vnode *vnode = fc->vnode;
1719 struct afs_call *call;
1720 struct afs_net *net = afs_v2net(vnode);
1721 __be32 *bp;
1722 void *tmpbuf;
1723
1724 _enter("");
1725
1726 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1727 if (!tmpbuf)
1728 return -ENOMEM;
1729
1730 call = afs_alloc_flat_call(net, &yfs_RXYFSGetVolumeStatus,
1731 sizeof(__be32) * 2 +
1732 sizeof(struct yfs_xdr_u64),
1733 sizeof(struct yfs_xdr_YFSFetchVolumeStatus) +
1734 sizeof(__be32));
1735 if (!call) {
1736 kfree(tmpbuf);
1737 return -ENOMEM;
1738 }
1739
1740 call->key = fc->key;
1741 call->reply[0] = vnode;
1742 call->reply[1] = vs;
1743 call->reply[2] = tmpbuf;
1744
1745 /* marshall the parameters */
1746 bp = call->request;
1747 bp = xdr_encode_u32(bp, YFSGETVOLUMESTATUS);
1748 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1749 bp = xdr_encode_u64(bp, vnode->fid.vid);
1750 yfs_check_req(call, bp);
1751
1752 afs_use_fs_server(call, fc->cbi);
1753 trace_afs_make_fs_call(call, &vnode->fid);
1754 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1755}
1756
1757/*
1758 * Deliver reply data to an YFS.SetLock, YFS.ExtendLock or YFS.ReleaseLock
1759 */
1760static int yfs_deliver_fs_xxxx_lock(struct afs_call *call)
1761{
1762 struct afs_vnode *vnode = call->reply[0];
1763 const __be32 *bp;
1764 int ret;
1765
1766 _enter("{%u}", call->unmarshall);
1767
1768 ret = afs_transfer_reply(call);
1769 if (ret < 0)
1770 return ret;
1771
1772 /* unmarshall the reply once we've received all of it */
1773 bp = call->buffer;
1774 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
1775 &call->expected_version, NULL);
1776 if (ret < 0)
1777 return ret;
1778 xdr_decode_YFSVolSync(&bp, NULL);
1779
1780 _leave(" = 0 [done]");
1781 return 0;
1782}
1783
1784/*
1785 * YFS.SetLock operation type
1786 */
1787static const struct afs_call_type yfs_RXYFSSetLock = {
1788 .name = "YFS.SetLock",
1789 .op = yfs_FS_SetLock,
1790 .deliver = yfs_deliver_fs_xxxx_lock,
1791 .destructor = afs_flat_call_destructor,
1792};
1793
1794/*
1795 * YFS.ExtendLock operation type
1796 */
1797static const struct afs_call_type yfs_RXYFSExtendLock = {
1798 .name = "YFS.ExtendLock",
1799 .op = yfs_FS_ExtendLock,
1800 .deliver = yfs_deliver_fs_xxxx_lock,
1801 .destructor = afs_flat_call_destructor,
1802};
1803
1804/*
1805 * YFS.ReleaseLock operation type
1806 */
1807static const struct afs_call_type yfs_RXYFSReleaseLock = {
1808 .name = "YFS.ReleaseLock",
1809 .op = yfs_FS_ReleaseLock,
1810 .deliver = yfs_deliver_fs_xxxx_lock,
1811 .destructor = afs_flat_call_destructor,
1812};
1813
1814/*
1815 * Set a lock on a file
1816 */
1817int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
1818{
1819 struct afs_vnode *vnode = fc->vnode;
1820 struct afs_call *call;
1821 struct afs_net *net = afs_v2net(vnode);
1822 __be32 *bp;
1823
1824 _enter("");
1825
1826 call = afs_alloc_flat_call(net, &yfs_RXYFSSetLock,
1827 sizeof(__be32) * 2 +
1828 sizeof(struct yfs_xdr_YFSFid) +
1829 sizeof(__be32),
1830 sizeof(struct yfs_xdr_YFSFetchStatus) +
1831 sizeof(struct yfs_xdr_YFSVolSync));
1832 if (!call)
1833 return -ENOMEM;
1834
1835 call->key = fc->key;
1836 call->reply[0] = vnode;
1837
1838 /* marshall the parameters */
1839 bp = call->request;
1840 bp = xdr_encode_u32(bp, YFSSETLOCK);
1841 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1842 bp = xdr_encode_YFSFid(bp, &vnode->fid);
1843 bp = xdr_encode_u32(bp, type);
1844 yfs_check_req(call, bp);
1845
1846 afs_use_fs_server(call, fc->cbi);
1847 trace_afs_make_fs_call(call, &vnode->fid);
1848 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1849}
1850
1851/*
1852 * extend a lock on a file
1853 */
1854int yfs_fs_extend_lock(struct afs_fs_cursor *fc)
1855{
1856 struct afs_vnode *vnode = fc->vnode;
1857 struct afs_call *call;
1858 struct afs_net *net = afs_v2net(vnode);
1859 __be32 *bp;
1860
1861 _enter("");
1862
1863 call = afs_alloc_flat_call(net, &yfs_RXYFSExtendLock,
1864 sizeof(__be32) * 2 +
1865 sizeof(struct yfs_xdr_YFSFid),
1866 sizeof(struct yfs_xdr_YFSFetchStatus) +
1867 sizeof(struct yfs_xdr_YFSVolSync));
1868 if (!call)
1869 return -ENOMEM;
1870
1871 call->key = fc->key;
1872 call->reply[0] = vnode;
1873
1874 /* marshall the parameters */
1875 bp = call->request;
1876 bp = xdr_encode_u32(bp, YFSEXTENDLOCK);
1877 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1878 bp = xdr_encode_YFSFid(bp, &vnode->fid);
1879 yfs_check_req(call, bp);
1880
1881 afs_use_fs_server(call, fc->cbi);
1882 trace_afs_make_fs_call(call, &vnode->fid);
1883 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1884}
1885
1886/*
1887 * release a lock on a file
1888 */
1889int yfs_fs_release_lock(struct afs_fs_cursor *fc)
1890{
1891 struct afs_vnode *vnode = fc->vnode;
1892 struct afs_call *call;
1893 struct afs_net *net = afs_v2net(vnode);
1894 __be32 *bp;
1895
1896 _enter("");
1897
1898 call = afs_alloc_flat_call(net, &yfs_RXYFSReleaseLock,
1899 sizeof(__be32) * 2 +
1900 sizeof(struct yfs_xdr_YFSFid),
1901 sizeof(struct yfs_xdr_YFSFetchStatus) +
1902 sizeof(struct yfs_xdr_YFSVolSync));
1903 if (!call)
1904 return -ENOMEM;
1905
1906 call->key = fc->key;
1907 call->reply[0] = vnode;
1908
1909 /* marshall the parameters */
1910 bp = call->request;
1911 bp = xdr_encode_u32(bp, YFSRELEASELOCK);
1912 bp = xdr_encode_u32(bp, 0); /* RPC flags */
1913 bp = xdr_encode_YFSFid(bp, &vnode->fid);
1914 yfs_check_req(call, bp);
1915
1916 afs_use_fs_server(call, fc->cbi);
1917 trace_afs_make_fs_call(call, &vnode->fid);
1918 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
1919}
1920
1921/*
1922 * Deliver reply data to an FS.FetchStatus with no vnode.
1923 */
1924static int yfs_deliver_fs_fetch_status(struct afs_call *call)
1925{
1926 struct afs_file_status *status = call->reply[1];
1927 struct afs_callback *callback = call->reply[2];
1928 struct afs_volsync *volsync = call->reply[3];
1929 struct afs_vnode *vnode = call->reply[0];
1930 const __be32 *bp;
1931 int ret;
1932
1933 ret = afs_transfer_reply(call);
1934 if (ret < 0)
1935 return ret;
1936
1937 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
1938
1939 /* unmarshall the reply once we've received all of it */
1940 bp = call->buffer;
1941 ret = yfs_decode_status(call, &bp, status, vnode,
1942 &call->expected_version, NULL);
1943 if (ret < 0)
1944 return ret;
1945 xdr_decode_YFSCallBack_raw(&bp, callback);
1946 xdr_decode_YFSVolSync(&bp, volsync);
1947
1948 _leave(" = 0 [done]");
1949 return 0;
1950}
1951
1952/*
1953 * YFS.FetchStatus operation type
1954 */
1955static const struct afs_call_type yfs_RXYFSFetchStatus = {
1956 .name = "YFS.FetchStatus",
1957 .op = yfs_FS_FetchStatus,
1958 .deliver = yfs_deliver_fs_fetch_status,
1959 .destructor = afs_flat_call_destructor,
1960};
1961
1962/*
1963 * Fetch the status information for a fid without needing a vnode handle.
1964 */
1965int yfs_fs_fetch_status(struct afs_fs_cursor *fc,
1966 struct afs_net *net,
1967 struct afs_fid *fid,
1968 struct afs_file_status *status,
1969 struct afs_callback *callback,
1970 struct afs_volsync *volsync)
1971{
1972 struct afs_call *call;
1973 __be32 *bp;
1974
1975 _enter(",%x,{%llx:%llu},,",
1976 key_serial(fc->key), fid->vid, fid->vnode);
1977
1978 call = afs_alloc_flat_call(net, &yfs_RXYFSFetchStatus,
1979 sizeof(__be32) * 2 +
1980 sizeof(struct yfs_xdr_YFSFid),
1981 sizeof(struct yfs_xdr_YFSFetchStatus) +
1982 sizeof(struct yfs_xdr_YFSCallBack) +
1983 sizeof(struct yfs_xdr_YFSVolSync));
1984 if (!call) {
1985 fc->ac.error = -ENOMEM;
1986 return -ENOMEM;
1987 }
1988
1989 call->key = fc->key;
1990 call->reply[0] = NULL; /* vnode for fid[0] */
1991 call->reply[1] = status;
1992 call->reply[2] = callback;
1993 call->reply[3] = volsync;
1994 call->expected_version = 1; /* vnode->status.data_version */
1995
1996 /* marshall the parameters */
1997 bp = call->request;
1998 bp = xdr_encode_u32(bp, YFSFETCHSTATUS);
1999 bp = xdr_encode_u32(bp, 0); /* RPC flags */
2000 bp = xdr_encode_YFSFid(bp, fid);
2001 yfs_check_req(call, bp);
2002
2003 call->cb_break = fc->cb_break;
2004 afs_use_fs_server(call, fc->cbi);
2005 trace_afs_make_fs_call(call, fid);
2006 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2007}
2008
2009/*
2010 * Deliver reply data to an YFS.InlineBulkStatus call
2011 */
2012static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
2013{
2014 struct afs_file_status *statuses;
2015 struct afs_callback *callbacks;
2016 struct afs_vnode *vnode = call->reply[0];
2017 const __be32 *bp;
2018 u32 tmp;
2019 int ret;
2020
2021 _enter("{%u}", call->unmarshall);
2022
2023 switch (call->unmarshall) {
2024 case 0:
2025 afs_extract_to_tmp(call);
2026 call->unmarshall++;
2027
2028 /* Extract the file status count and array in two steps */
2029 case 1:
2030 _debug("extract status count");
2031 ret = afs_extract_data(call, true);
2032 if (ret < 0)
2033 return ret;
2034
2035 tmp = ntohl(call->tmp);
2036 _debug("status count: %u/%u", tmp, call->count2);
2037 if (tmp != call->count2)
2038 return afs_protocol_error(call, -EBADMSG,
2039 afs_eproto_ibulkst_count);
2040
2041 call->count = 0;
2042 call->unmarshall++;
2043 more_counts:
2044 afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus));
2045
2046 case 2:
2047 _debug("extract status array %u", call->count);
2048 ret = afs_extract_data(call, true);
2049 if (ret < 0)
2050 return ret;
2051
2052 bp = call->buffer;
2053 statuses = call->reply[1];
2054 ret = yfs_decode_status(call, &bp, &statuses[call->count],
2055 call->count == 0 ? vnode : NULL,
2056 NULL, NULL);
2057 if (ret < 0)
2058 return ret;
2059
2060 call->count++;
2061 if (call->count < call->count2)
2062 goto more_counts;
2063
2064 call->count = 0;
2065 call->unmarshall++;
2066 afs_extract_to_tmp(call);
2067
2068 /* Extract the callback count and array in two steps */
2069 case 3:
2070 _debug("extract CB count");
2071 ret = afs_extract_data(call, true);
2072 if (ret < 0)
2073 return ret;
2074
2075 tmp = ntohl(call->tmp);
2076 _debug("CB count: %u", tmp);
2077 if (tmp != call->count2)
2078 return afs_protocol_error(call, -EBADMSG,
2079 afs_eproto_ibulkst_cb_count);
2080 call->count = 0;
2081 call->unmarshall++;
2082 more_cbs:
2083 afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack));
2084
2085 case 4:
2086 _debug("extract CB array");
2087 ret = afs_extract_data(call, true);
2088 if (ret < 0)
2089 return ret;
2090
2091 _debug("unmarshall CB array");
2092 bp = call->buffer;
2093 callbacks = call->reply[2];
2094 xdr_decode_YFSCallBack_raw(&bp, &callbacks[call->count]);
2095 statuses = call->reply[1];
2096 if (call->count == 0 && vnode && statuses[0].abort_code == 0) {
2097 bp = call->buffer;
2098 xdr_decode_YFSCallBack(call, vnode, &bp);
2099 }
2100 call->count++;
2101 if (call->count < call->count2)
2102 goto more_cbs;
2103
2104 afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync));
2105 call->unmarshall++;
2106
2107 case 5:
2108 ret = afs_extract_data(call, false);
2109 if (ret < 0)
2110 return ret;
2111
2112 bp = call->buffer;
2113 xdr_decode_YFSVolSync(&bp, call->reply[3]);
2114
2115 call->unmarshall++;
2116
2117 case 6:
2118 break;
2119 }
2120
2121 _leave(" = 0 [done]");
2122 return 0;
2123}
2124
2125/*
2126 * FS.InlineBulkStatus operation type
2127 */
2128static const struct afs_call_type yfs_RXYFSInlineBulkStatus = {
2129 .name = "YFS.InlineBulkStatus",
2130 .op = yfs_FS_InlineBulkStatus,
2131 .deliver = yfs_deliver_fs_inline_bulk_status,
2132 .destructor = afs_flat_call_destructor,
2133};
2134
2135/*
2136 * Fetch the status information for up to 1024 files
2137 */
2138int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2139 struct afs_net *net,
2140 struct afs_fid *fids,
2141 struct afs_file_status *statuses,
2142 struct afs_callback *callbacks,
2143 unsigned int nr_fids,
2144 struct afs_volsync *volsync)
2145{
2146 struct afs_call *call;
2147 __be32 *bp;
2148 int i;
2149
2150 _enter(",%x,{%llx:%llu},%u",
2151 key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);
2152
2153 call = afs_alloc_flat_call(net, &yfs_RXYFSInlineBulkStatus,
2154 sizeof(__be32) +
2155 sizeof(__be32) +
2156 sizeof(__be32) +
2157 sizeof(struct yfs_xdr_YFSFid) * nr_fids,
2158 sizeof(struct yfs_xdr_YFSFetchStatus));
2159 if (!call) {
2160 fc->ac.error = -ENOMEM;
2161 return -ENOMEM;
2162 }
2163
2164 call->key = fc->key;
2165 call->reply[0] = NULL; /* vnode for fid[0] */
2166 call->reply[1] = statuses;
2167 call->reply[2] = callbacks;
2168 call->reply[3] = volsync;
2169 call->count2 = nr_fids;
2170
2171 /* marshall the parameters */
2172 bp = call->request;
2173 bp = xdr_encode_u32(bp, YFSINLINEBULKSTATUS);
2174 bp = xdr_encode_u32(bp, 0); /* RPCFlags */
2175 bp = xdr_encode_u32(bp, nr_fids);
2176 for (i = 0; i < nr_fids; i++)
2177 bp = xdr_encode_YFSFid(bp, &fids[i]);
2178 yfs_check_req(call, bp);
2179
2180 call->cb_break = fc->cb_break;
2181 afs_use_fs_server(call, fc->cbi);
2182 trace_afs_make_fs_call(call, &fids[0]);
2183 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
2184}