]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/afs/fsclient.c
afs: Overhaul volume and server record caching and fileserver rotation
[mirror_ubuntu-bionic-kernel.git] / fs / afs / fsclient.c
CommitLineData
08e0e7c8 1/* AFS File Server client stubs
1da177e4 2 *
08e0e7c8 3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
1da177e4
LT
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 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>
5a0e3ad6 13#include <linux/slab.h>
1da177e4 14#include <linux/sched.h>
08e0e7c8 15#include <linux/circ_buf.h>
1da177e4 16#include "internal.h"
08e0e7c8 17#include "afs_fs.h"
1da177e4 18
6db3ac3c
DH
19/*
20 * We need somewhere to discard into in case the server helpfully returns more
21 * than we asked for in FS.FetchData{,64}.
22 */
23static u8 afs_discard_buffer[64];
24
d2ddc776 25static inline void afs_use_fs_server(struct afs_call *call, struct afs_cb_interest *cbi)
c435ee34 26{
d2ddc776 27 call->cbi = afs_get_cb_interest(cbi);
c435ee34
DH
28}
29
260a9803
DH
30/*
31 * decode an AFSFid block
32 */
33static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
34{
35 const __be32 *bp = *_bp;
36
37 fid->vid = ntohl(*bp++);
38 fid->vnode = ntohl(*bp++);
39 fid->unique = ntohl(*bp++);
40 *_bp = bp;
41}
42
1da177e4 43/*
08e0e7c8 44 * decode an AFSFetchStatus block
1da177e4 45 */
08e0e7c8 46static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
260a9803 47 struct afs_file_status *status,
31143d5d
DH
48 struct afs_vnode *vnode,
49 afs_dataversion_t *store_version)
1da177e4 50{
31143d5d 51 afs_dataversion_t expected_version;
08e0e7c8
DH
52 const __be32 *bp = *_bp;
53 umode_t mode;
260a9803 54 u64 data_version, size;
c435ee34 55 bool changed = false;
a0a5386a
EB
56 kuid_t owner;
57 kgid_t group;
08e0e7c8 58
d2ddc776
DH
59 if (vnode)
60 write_seqlock(&vnode->cb_lock);
c435ee34 61
08e0e7c8
DH
62#define EXTRACT(DST) \
63 do { \
64 u32 x = ntohl(*bp++); \
c435ee34
DH
65 if (DST != x) \
66 changed |= true; \
08e0e7c8
DH
67 DST = x; \
68 } while (0)
69
260a9803
DH
70 status->if_version = ntohl(*bp++);
71 EXTRACT(status->type);
72 EXTRACT(status->nlink);
73 size = ntohl(*bp++);
08e0e7c8 74 data_version = ntohl(*bp++);
260a9803 75 EXTRACT(status->author);
a0a5386a
EB
76 owner = make_kuid(&init_user_ns, ntohl(*bp++));
77 changed |= !uid_eq(owner, status->owner);
78 status->owner = owner;
260a9803
DH
79 EXTRACT(status->caller_access); /* call ticket dependent */
80 EXTRACT(status->anon_access);
81 EXTRACT(status->mode);
be080a6f
DH
82 bp++; /* parent.vnode */
83 bp++; /* parent.unique */
08e0e7c8 84 bp++; /* seg size */
260a9803
DH
85 status->mtime_client = ntohl(*bp++);
86 status->mtime_server = ntohl(*bp++);
a0a5386a
EB
87 group = make_kgid(&init_user_ns, ntohl(*bp++));
88 changed |= !gid_eq(group, status->group);
89 status->group = group;
08e0e7c8
DH
90 bp++; /* sync counter */
91 data_version |= (u64) ntohl(*bp++) << 32;
e8d6c554 92 EXTRACT(status->lock_count);
260a9803
DH
93 size |= (u64) ntohl(*bp++) << 32;
94 bp++; /* spare 4 */
08e0e7c8
DH
95 *_bp = bp;
96
260a9803
DH
97 if (size != status->size) {
98 status->size = size;
99 changed |= true;
08e0e7c8 100 }
260a9803 101 status->mode &= S_IALLUGO;
08e0e7c8
DH
102
103 _debug("vnode time %lx, %lx",
260a9803
DH
104 status->mtime_client, status->mtime_server);
105
106 if (vnode) {
260a9803
DH
107 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
108 _debug("vnode changed");
109 i_size_write(&vnode->vfs_inode, size);
110 vnode->vfs_inode.i_uid = status->owner;
111 vnode->vfs_inode.i_gid = status->group;
d6e43f75 112 vnode->vfs_inode.i_generation = vnode->fid.unique;
bfe86848 113 set_nlink(&vnode->vfs_inode, status->nlink);
260a9803
DH
114
115 mode = vnode->vfs_inode.i_mode;
116 mode &= ~S_IALLUGO;
117 mode |= status->mode;
118 barrier();
119 vnode->vfs_inode.i_mode = mode;
120 }
121
ab94f5d0 122 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
260a9803
DH
123 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
124 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
d6e43f75 125 vnode->vfs_inode.i_version = data_version;
260a9803
DH
126 }
127
31143d5d
DH
128 expected_version = status->data_version;
129 if (store_version)
130 expected_version = *store_version;
131
132 if (expected_version != data_version) {
260a9803
DH
133 status->data_version = data_version;
134 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
135 _debug("vnode modified %llx on {%x:%u}",
ba3e0e1a
DM
136 (unsigned long long) data_version,
137 vnode->fid.vid, vnode->fid.vnode);
c435ee34 138 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
260a9803
DH
139 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
140 }
31143d5d
DH
141 } else if (store_version) {
142 status->data_version = data_version;
1da177e4 143 }
c435ee34 144
d2ddc776
DH
145 if (vnode)
146 write_sequnlock(&vnode->cb_lock);
ec26815a 147}
1da177e4 148
1da177e4 149/*
08e0e7c8 150 * decode an AFSCallBack block
1da177e4 151 */
c435ee34
DH
152static void xdr_decode_AFSCallBack(struct afs_call *call,
153 struct afs_vnode *vnode,
154 const __be32 **_bp)
1da177e4 155{
d2ddc776 156 struct afs_cb_interest *old, *cbi = call->cbi;
08e0e7c8 157 const __be32 *bp = *_bp;
c435ee34
DH
158 u32 cb_expiry;
159
160 write_seqlock(&vnode->cb_lock);
161
d2ddc776 162 if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) {
c435ee34
DH
163 vnode->cb_version = ntohl(*bp++);
164 cb_expiry = ntohl(*bp++);
165 vnode->cb_type = ntohl(*bp++);
166 vnode->cb_expires_at = cb_expiry + ktime_get_real_seconds();
d2ddc776
DH
167 old = vnode->cb_interest;
168 if (old != call->cbi) {
169 vnode->cb_interest = cbi;
170 cbi = old;
171 }
c435ee34
DH
172 set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
173 } else {
174 bp += 3;
175 }
1da177e4 176
c435ee34 177 write_sequnlock(&vnode->cb_lock);
d2ddc776 178 call->cbi = cbi;
08e0e7c8 179 *_bp = bp;
ec26815a 180}
1da177e4 181
260a9803
DH
182static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
183 struct afs_callback *cb)
184{
185 const __be32 *bp = *_bp;
186
187 cb->version = ntohl(*bp++);
188 cb->expiry = ntohl(*bp++);
189 cb->type = ntohl(*bp++);
190 *_bp = bp;
191}
192
1da177e4 193/*
08e0e7c8 194 * decode an AFSVolSync block
1da177e4 195 */
08e0e7c8
DH
196static void xdr_decode_AFSVolSync(const __be32 **_bp,
197 struct afs_volsync *volsync)
1da177e4 198{
08e0e7c8 199 const __be32 *bp = *_bp;
1da177e4 200
08e0e7c8
DH
201 volsync->creation = ntohl(*bp++);
202 bp++; /* spare2 */
203 bp++; /* spare3 */
204 bp++; /* spare4 */
205 bp++; /* spare5 */
206 bp++; /* spare6 */
207 *_bp = bp;
208}
1da177e4 209
31143d5d
DH
210/*
211 * encode the requested attributes into an AFSStoreStatus block
212 */
213static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
214{
215 __be32 *bp = *_bp;
216 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
217
218 mask = 0;
219 if (attr->ia_valid & ATTR_MTIME) {
220 mask |= AFS_SET_MTIME;
221 mtime = attr->ia_mtime.tv_sec;
222 }
223
224 if (attr->ia_valid & ATTR_UID) {
225 mask |= AFS_SET_OWNER;
a0a5386a 226 owner = from_kuid(&init_user_ns, attr->ia_uid);
31143d5d
DH
227 }
228
229 if (attr->ia_valid & ATTR_GID) {
230 mask |= AFS_SET_GROUP;
a0a5386a 231 group = from_kgid(&init_user_ns, attr->ia_gid);
31143d5d
DH
232 }
233
234 if (attr->ia_valid & ATTR_MODE) {
235 mask |= AFS_SET_MODE;
236 mode = attr->ia_mode & S_IALLUGO;
237 }
238
239 *bp++ = htonl(mask);
240 *bp++ = htonl(mtime);
241 *bp++ = htonl(owner);
242 *bp++ = htonl(group);
243 *bp++ = htonl(mode);
244 *bp++ = 0; /* segment size */
245 *_bp = bp;
246}
247
45222b9e
DH
248/*
249 * decode an AFSFetchVolumeStatus block
250 */
251static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
252 struct afs_volume_status *vs)
253{
254 const __be32 *bp = *_bp;
255
256 vs->vid = ntohl(*bp++);
257 vs->parent_id = ntohl(*bp++);
258 vs->online = ntohl(*bp++);
259 vs->in_service = ntohl(*bp++);
260 vs->blessed = ntohl(*bp++);
261 vs->needs_salvage = ntohl(*bp++);
262 vs->type = ntohl(*bp++);
263 vs->min_quota = ntohl(*bp++);
264 vs->max_quota = ntohl(*bp++);
265 vs->blocks_in_use = ntohl(*bp++);
266 vs->part_blocks_avail = ntohl(*bp++);
267 vs->part_max_blocks = ntohl(*bp++);
268 *_bp = bp;
269}
270
08e0e7c8
DH
271/*
272 * deliver reply data to an FS.FetchStatus
273 */
d001648e 274static int afs_deliver_fs_fetch_status(struct afs_call *call)
08e0e7c8 275{
97e3043a 276 struct afs_vnode *vnode = call->reply[0];
08e0e7c8 277 const __be32 *bp;
372ee163 278 int ret;
1da177e4 279
d001648e 280 ret = afs_transfer_reply(call);
372ee163
DH
281 if (ret < 0)
282 return ret;
1da177e4 283
c435ee34
DH
284 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
285
08e0e7c8
DH
286 /* unmarshall the reply once we've received all of it */
287 bp = call->buffer;
31143d5d 288 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
c435ee34 289 xdr_decode_AFSCallBack(call, vnode, &bp);
97e3043a
DH
290 if (call->reply[1])
291 xdr_decode_AFSVolSync(&bp, call->reply[1]);
1da177e4 292
08e0e7c8
DH
293 _leave(" = 0 [done]");
294 return 0;
ec26815a 295}
08e0e7c8
DH
296
297/*
298 * FS.FetchStatus operation type
299 */
300static const struct afs_call_type afs_RXFSFetchStatus = {
00d3b7a4 301 .name = "FS.FetchStatus",
08e0e7c8 302 .deliver = afs_deliver_fs_fetch_status,
08e0e7c8
DH
303 .destructor = afs_flat_call_destructor,
304};
1da177e4 305
1da177e4
LT
306/*
307 * fetch the status information for a file
308 */
d2ddc776 309int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync)
1da177e4 310{
d2ddc776 311 struct afs_vnode *vnode = fc->vnode;
08e0e7c8 312 struct afs_call *call;
f044c884 313 struct afs_net *net = afs_v2net(vnode);
1da177e4
LT
314 __be32 *bp;
315
416351f2 316 _enter(",%x,{%x:%u},,",
d2ddc776 317 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
1da177e4 318
f044c884 319 call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
d2ddc776
DH
320 if (!call) {
321 fc->ac.error = -ENOMEM;
08e0e7c8 322 return -ENOMEM;
d2ddc776 323 }
1da177e4 324
d2ddc776 325 call->key = fc->key;
97e3043a
DH
326 call->reply[0] = vnode;
327 call->reply[1] = volsync;
1da177e4
LT
328
329 /* marshall the parameters */
08e0e7c8 330 bp = call->request;
1da177e4
LT
331 bp[0] = htonl(FSFETCHSTATUS);
332 bp[1] = htonl(vnode->fid.vid);
333 bp[2] = htonl(vnode->fid.vnode);
334 bp[3] = htonl(vnode->fid.unique);
335
d2ddc776
DH
336 call->cb_break = fc->cb_break;
337 afs_use_fs_server(call, fc->cbi);
338 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
ec26815a 339}
1da177e4 340
1da177e4 341/*
08e0e7c8 342 * deliver reply data to an FS.FetchData
1da177e4 343 */
d001648e 344static int afs_deliver_fs_fetch_data(struct afs_call *call)
1da177e4 345{
97e3043a
DH
346 struct afs_vnode *vnode = call->reply[0];
347 struct afs_read *req = call->reply[2];
08e0e7c8 348 const __be32 *bp;
196ee9cd 349 unsigned int size;
08e0e7c8 350 void *buffer;
1da177e4 351 int ret;
1da177e4 352
6a0e3999 353 _enter("{%u,%zu/%u;%llu/%llu}",
196ee9cd
DH
354 call->unmarshall, call->offset, call->count,
355 req->remain, req->actual_len);
08e0e7c8
DH
356
357 switch (call->unmarshall) {
358 case 0:
196ee9cd 359 req->actual_len = 0;
08e0e7c8
DH
360 call->offset = 0;
361 call->unmarshall++;
b9b1f8d5
DH
362 if (call->operation_ID != FSFETCHDATA64) {
363 call->unmarshall++;
364 goto no_msw;
365 }
08e0e7c8 366
b9b1f8d5
DH
367 /* extract the upper part of the returned data length of an
368 * FSFETCHDATA64 op (which should always be 0 using this
369 * client) */
08e0e7c8 370 case 1:
b9b1f8d5 371 _debug("extract data length (MSW)");
d001648e 372 ret = afs_extract_data(call, &call->tmp, 4, true);
372ee163
DH
373 if (ret < 0)
374 return ret;
b9b1f8d5 375
196ee9cd
DH
376 req->actual_len = ntohl(call->tmp);
377 req->actual_len <<= 32;
b9b1f8d5
DH
378 call->offset = 0;
379 call->unmarshall++;
380
381 no_msw:
382 /* extract the returned data length */
383 case 2:
08e0e7c8 384 _debug("extract data length");
d001648e 385 ret = afs_extract_data(call, &call->tmp, 4, true);
372ee163
DH
386 if (ret < 0)
387 return ret;
1da177e4 388
196ee9cd
DH
389 req->actual_len |= ntohl(call->tmp);
390 _debug("DATA length: %llu", req->actual_len);
196ee9cd
DH
391
392 req->remain = req->actual_len;
393 call->offset = req->pos & (PAGE_SIZE - 1);
394 req->index = 0;
395 if (req->actual_len == 0)
396 goto no_more_data;
08e0e7c8
DH
397 call->unmarshall++;
398
196ee9cd 399 begin_page:
6db3ac3c 400 ASSERTCMP(req->index, <, req->nr_pages);
196ee9cd
DH
401 if (req->remain > PAGE_SIZE - call->offset)
402 size = PAGE_SIZE - call->offset;
403 else
404 size = req->remain;
405 call->count = call->offset + size;
406 ASSERTCMP(call->count, <=, PAGE_SIZE);
407 req->remain -= size;
408
08e0e7c8 409 /* extract the returned data */
b9b1f8d5 410 case 3:
6a0e3999 411 _debug("extract data %llu/%llu %zu/%u",
196ee9cd
DH
412 req->remain, req->actual_len, call->offset, call->count);
413
414 buffer = kmap(req->pages[req->index]);
415 ret = afs_extract_data(call, buffer, call->count, true);
416 kunmap(req->pages[req->index]);
417 if (ret < 0)
418 return ret;
419 if (call->offset == PAGE_SIZE) {
420 if (req->page_done)
421 req->page_done(call, req);
29f06985 422 req->index++;
196ee9cd 423 if (req->remain > 0) {
196ee9cd 424 call->offset = 0;
e8e581a8
DH
425 if (req->index >= req->nr_pages) {
426 call->unmarshall = 4;
6db3ac3c 427 goto begin_discard;
e8e581a8 428 }
196ee9cd
DH
429 goto begin_page;
430 }
08e0e7c8 431 }
6db3ac3c
DH
432 goto no_more_data;
433
434 /* Discard any excess data the server gave us */
435 begin_discard:
436 case 4:
6a0e3999 437 size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
6db3ac3c 438 call->count = size;
6a0e3999 439 _debug("extract discard %llu/%llu %zu/%u",
6db3ac3c
DH
440 req->remain, req->actual_len, call->offset, call->count);
441
442 call->offset = 0;
443 ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
444 req->remain -= call->offset;
445 if (ret < 0)
446 return ret;
447 if (req->remain > 0)
448 goto begin_discard;
1da177e4 449
196ee9cd 450 no_more_data:
08e0e7c8 451 call->offset = 0;
6db3ac3c 452 call->unmarshall = 5;
1da177e4 453
08e0e7c8 454 /* extract the metadata */
6db3ac3c 455 case 5:
d001648e
DH
456 ret = afs_extract_data(call, call->buffer,
457 (21 + 3 + 6) * 4, false);
372ee163
DH
458 if (ret < 0)
459 return ret;
08e0e7c8
DH
460
461 bp = call->buffer;
31143d5d 462 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
c435ee34 463 xdr_decode_AFSCallBack(call, vnode, &bp);
97e3043a
DH
464 if (call->reply[1])
465 xdr_decode_AFSVolSync(&bp, call->reply[1]);
08e0e7c8
DH
466
467 call->offset = 0;
468 call->unmarshall++;
1da177e4 469
6db3ac3c 470 case 6:
08e0e7c8 471 break;
1da177e4
LT
472 }
473
6db3ac3c
DH
474 for (; req->index < req->nr_pages; req->index++) {
475 if (call->count < PAGE_SIZE)
476 zero_user_segment(req->pages[req->index],
477 call->count, PAGE_SIZE);
196ee9cd
DH
478 if (req->page_done)
479 req->page_done(call, req);
6db3ac3c 480 call->count = 0;
416351f2
DH
481 }
482
08e0e7c8
DH
483 _leave(" = 0 [done]");
484 return 0;
ec26815a 485}
1da177e4 486
196ee9cd
DH
487static void afs_fetch_data_destructor(struct afs_call *call)
488{
97e3043a 489 struct afs_read *req = call->reply[2];
196ee9cd
DH
490
491 afs_put_read(req);
492 afs_flat_call_destructor(call);
493}
494
1da177e4 495/*
08e0e7c8 496 * FS.FetchData operation type
1da177e4 497 */
08e0e7c8 498static const struct afs_call_type afs_RXFSFetchData = {
00d3b7a4 499 .name = "FS.FetchData",
08e0e7c8 500 .deliver = afs_deliver_fs_fetch_data,
196ee9cd 501 .destructor = afs_fetch_data_destructor,
08e0e7c8
DH
502};
503
b9b1f8d5
DH
504static const struct afs_call_type afs_RXFSFetchData64 = {
505 .name = "FS.FetchData64",
506 .deliver = afs_deliver_fs_fetch_data,
196ee9cd 507 .destructor = afs_fetch_data_destructor,
b9b1f8d5
DH
508};
509
510/*
511 * fetch data from a very large file
512 */
d2ddc776 513static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
b9b1f8d5 514{
d2ddc776 515 struct afs_vnode *vnode = fc->vnode;
b9b1f8d5 516 struct afs_call *call;
f044c884 517 struct afs_net *net = afs_v2net(vnode);
b9b1f8d5
DH
518 __be32 *bp;
519
520 _enter("");
521
f044c884 522 call = afs_alloc_flat_call(net, &afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
b9b1f8d5
DH
523 if (!call)
524 return -ENOMEM;
525
d2ddc776 526 call->key = fc->key;
97e3043a
DH
527 call->reply[0] = vnode;
528 call->reply[1] = NULL; /* volsync */
529 call->reply[2] = req;
b9b1f8d5
DH
530 call->operation_ID = FSFETCHDATA64;
531
532 /* marshall the parameters */
533 bp = call->request;
534 bp[0] = htonl(FSFETCHDATA64);
535 bp[1] = htonl(vnode->fid.vid);
536 bp[2] = htonl(vnode->fid.vnode);
537 bp[3] = htonl(vnode->fid.unique);
196ee9cd
DH
538 bp[4] = htonl(upper_32_bits(req->pos));
539 bp[5] = htonl(lower_32_bits(req->pos));
b9b1f8d5 540 bp[6] = 0;
196ee9cd 541 bp[7] = htonl(lower_32_bits(req->len));
b9b1f8d5 542
196ee9cd 543 atomic_inc(&req->usage);
d2ddc776
DH
544 call->cb_break = fc->cb_break;
545 afs_use_fs_server(call, fc->cbi);
546 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
b9b1f8d5
DH
547}
548
08e0e7c8
DH
549/*
550 * fetch data from a file
551 */
d2ddc776 552int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
1da177e4 553{
d2ddc776 554 struct afs_vnode *vnode = fc->vnode;
08e0e7c8 555 struct afs_call *call;
f044c884 556 struct afs_net *net = afs_v2net(vnode);
1da177e4
LT
557 __be32 *bp;
558
196ee9cd
DH
559 if (upper_32_bits(req->pos) ||
560 upper_32_bits(req->len) ||
561 upper_32_bits(req->pos + req->len))
d2ddc776 562 return afs_fs_fetch_data64(fc, req);
b9b1f8d5 563
08e0e7c8 564 _enter("");
1da177e4 565
f044c884 566 call = afs_alloc_flat_call(net, &afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
08e0e7c8
DH
567 if (!call)
568 return -ENOMEM;
1da177e4 569
d2ddc776 570 call->key = fc->key;
97e3043a
DH
571 call->reply[0] = vnode;
572 call->reply[1] = NULL; /* volsync */
573 call->reply[2] = req;
b9b1f8d5 574 call->operation_ID = FSFETCHDATA;
1da177e4
LT
575
576 /* marshall the parameters */
08e0e7c8
DH
577 bp = call->request;
578 bp[0] = htonl(FSFETCHDATA);
579 bp[1] = htonl(vnode->fid.vid);
580 bp[2] = htonl(vnode->fid.vnode);
581 bp[3] = htonl(vnode->fid.unique);
196ee9cd
DH
582 bp[4] = htonl(lower_32_bits(req->pos));
583 bp[5] = htonl(lower_32_bits(req->len));
1da177e4 584
196ee9cd 585 atomic_inc(&req->usage);
d2ddc776
DH
586 call->cb_break = fc->cb_break;
587 afs_use_fs_server(call, fc->cbi);
588 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
ec26815a 589}
260a9803
DH
590
591/*
592 * deliver reply data to an FS.CreateFile or an FS.MakeDir
593 */
d001648e 594static int afs_deliver_fs_create_vnode(struct afs_call *call)
260a9803 595{
97e3043a 596 struct afs_vnode *vnode = call->reply[0];
260a9803 597 const __be32 *bp;
372ee163 598 int ret;
260a9803 599
d001648e 600 _enter("{%u}", call->unmarshall);
260a9803 601
d001648e 602 ret = afs_transfer_reply(call);
372ee163
DH
603 if (ret < 0)
604 return ret;
260a9803
DH
605
606 /* unmarshall the reply once we've received all of it */
607 bp = call->buffer;
97e3043a
DH
608 xdr_decode_AFSFid(&bp, call->reply[1]);
609 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
31143d5d 610 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
97e3043a
DH
611 xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
612 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
260a9803
DH
613
614 _leave(" = 0 [done]");
615 return 0;
616}
617
618/*
619 * FS.CreateFile and FS.MakeDir operation type
620 */
621static const struct afs_call_type afs_RXFSCreateXXXX = {
622 .name = "FS.CreateXXXX",
623 .deliver = afs_deliver_fs_create_vnode,
260a9803
DH
624 .destructor = afs_flat_call_destructor,
625};
626
627/*
628 * create a file or make a directory
629 */
8b2a464c 630int afs_fs_create(struct afs_fs_cursor *fc,
260a9803
DH
631 const char *name,
632 umode_t mode,
633 struct afs_fid *newfid,
634 struct afs_file_status *newstatus,
d2ddc776 635 struct afs_callback *newcb)
260a9803 636{
d2ddc776 637 struct afs_vnode *vnode = fc->vnode;
260a9803 638 struct afs_call *call;
f044c884 639 struct afs_net *net = afs_v2net(vnode);
260a9803
DH
640 size_t namesz, reqsz, padsz;
641 __be32 *bp;
642
643 _enter("");
644
645 namesz = strlen(name);
646 padsz = (4 - (namesz & 3)) & 3;
647 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
648
f044c884 649 call = afs_alloc_flat_call(net, &afs_RXFSCreateXXXX, reqsz,
260a9803
DH
650 (3 + 21 + 21 + 3 + 6) * 4);
651 if (!call)
652 return -ENOMEM;
653
d2ddc776 654 call->key = fc->key;
97e3043a
DH
655 call->reply[0] = vnode;
656 call->reply[1] = newfid;
657 call->reply[2] = newstatus;
658 call->reply[3] = newcb;
260a9803
DH
659
660 /* marshall the parameters */
661 bp = call->request;
662 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
663 *bp++ = htonl(vnode->fid.vid);
664 *bp++ = htonl(vnode->fid.vnode);
665 *bp++ = htonl(vnode->fid.unique);
666 *bp++ = htonl(namesz);
667 memcpy(bp, name, namesz);
668 bp = (void *) bp + namesz;
669 if (padsz > 0) {
670 memset(bp, 0, padsz);
671 bp = (void *) bp + padsz;
672 }
ab94f5d0
MD
673 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
674 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
260a9803
DH
675 *bp++ = 0; /* owner */
676 *bp++ = 0; /* group */
677 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
678 *bp++ = 0; /* segment size */
679
d2ddc776
DH
680 afs_use_fs_server(call, fc->cbi);
681 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
260a9803
DH
682}
683
684/*
685 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
686 */
d001648e 687static int afs_deliver_fs_remove(struct afs_call *call)
260a9803 688{
97e3043a 689 struct afs_vnode *vnode = call->reply[0];
260a9803 690 const __be32 *bp;
372ee163 691 int ret;
260a9803 692
d001648e 693 _enter("{%u}", call->unmarshall);
260a9803 694
d001648e 695 ret = afs_transfer_reply(call);
372ee163
DH
696 if (ret < 0)
697 return ret;
260a9803
DH
698
699 /* unmarshall the reply once we've received all of it */
700 bp = call->buffer;
31143d5d 701 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
97e3043a 702 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
260a9803
DH
703
704 _leave(" = 0 [done]");
705 return 0;
706}
707
708/*
709 * FS.RemoveDir/FS.RemoveFile operation type
710 */
711static const struct afs_call_type afs_RXFSRemoveXXXX = {
712 .name = "FS.RemoveXXXX",
713 .deliver = afs_deliver_fs_remove,
260a9803
DH
714 .destructor = afs_flat_call_destructor,
715};
716
717/*
718 * remove a file or directory
719 */
d2ddc776 720int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir)
260a9803 721{
d2ddc776 722 struct afs_vnode *vnode = fc->vnode;
260a9803 723 struct afs_call *call;
f044c884 724 struct afs_net *net = afs_v2net(vnode);
260a9803
DH
725 size_t namesz, reqsz, padsz;
726 __be32 *bp;
727
728 _enter("");
729
730 namesz = strlen(name);
731 padsz = (4 - (namesz & 3)) & 3;
732 reqsz = (5 * 4) + namesz + padsz;
733
f044c884 734 call = afs_alloc_flat_call(net, &afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
260a9803
DH
735 if (!call)
736 return -ENOMEM;
737
d2ddc776 738 call->key = fc->key;
97e3043a 739 call->reply[0] = vnode;
260a9803
DH
740
741 /* marshall the parameters */
742 bp = call->request;
743 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
744 *bp++ = htonl(vnode->fid.vid);
745 *bp++ = htonl(vnode->fid.vnode);
746 *bp++ = htonl(vnode->fid.unique);
747 *bp++ = htonl(namesz);
748 memcpy(bp, name, namesz);
749 bp = (void *) bp + namesz;
750 if (padsz > 0) {
751 memset(bp, 0, padsz);
752 bp = (void *) bp + padsz;
753 }
754
d2ddc776
DH
755 afs_use_fs_server(call, fc->cbi);
756 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
260a9803
DH
757}
758
759/*
760 * deliver reply data to an FS.Link
761 */
d001648e 762static int afs_deliver_fs_link(struct afs_call *call)
260a9803 763{
97e3043a 764 struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
260a9803 765 const __be32 *bp;
372ee163 766 int ret;
260a9803 767
d001648e 768 _enter("{%u}", call->unmarshall);
260a9803 769
d001648e 770 ret = afs_transfer_reply(call);
372ee163
DH
771 if (ret < 0)
772 return ret;
260a9803
DH
773
774 /* unmarshall the reply once we've received all of it */
775 bp = call->buffer;
31143d5d
DH
776 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
777 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
97e3043a 778 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
260a9803
DH
779
780 _leave(" = 0 [done]");
781 return 0;
782}
783
784/*
785 * FS.Link operation type
786 */
787static const struct afs_call_type afs_RXFSLink = {
788 .name = "FS.Link",
789 .deliver = afs_deliver_fs_link,
260a9803
DH
790 .destructor = afs_flat_call_destructor,
791};
792
793/*
794 * make a hard link
795 */
d2ddc776
DH
796int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
797 const char *name)
260a9803 798{
d2ddc776 799 struct afs_vnode *dvnode = fc->vnode;
260a9803 800 struct afs_call *call;
f044c884 801 struct afs_net *net = afs_v2net(vnode);
260a9803
DH
802 size_t namesz, reqsz, padsz;
803 __be32 *bp;
804
805 _enter("");
806
807 namesz = strlen(name);
808 padsz = (4 - (namesz & 3)) & 3;
809 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
810
f044c884 811 call = afs_alloc_flat_call(net, &afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
260a9803
DH
812 if (!call)
813 return -ENOMEM;
814
d2ddc776 815 call->key = fc->key;
97e3043a
DH
816 call->reply[0] = dvnode;
817 call->reply[1] = vnode;
260a9803
DH
818
819 /* marshall the parameters */
820 bp = call->request;
821 *bp++ = htonl(FSLINK);
822 *bp++ = htonl(dvnode->fid.vid);
823 *bp++ = htonl(dvnode->fid.vnode);
824 *bp++ = htonl(dvnode->fid.unique);
825 *bp++ = htonl(namesz);
826 memcpy(bp, name, namesz);
827 bp = (void *) bp + namesz;
828 if (padsz > 0) {
829 memset(bp, 0, padsz);
830 bp = (void *) bp + padsz;
831 }
832 *bp++ = htonl(vnode->fid.vid);
833 *bp++ = htonl(vnode->fid.vnode);
834 *bp++ = htonl(vnode->fid.unique);
835
d2ddc776
DH
836 afs_use_fs_server(call, fc->cbi);
837 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
260a9803
DH
838}
839
840/*
841 * deliver reply data to an FS.Symlink
842 */
d001648e 843static int afs_deliver_fs_symlink(struct afs_call *call)
260a9803 844{
97e3043a 845 struct afs_vnode *vnode = call->reply[0];
260a9803 846 const __be32 *bp;
372ee163 847 int ret;
260a9803 848
d001648e 849 _enter("{%u}", call->unmarshall);
260a9803 850
d001648e 851 ret = afs_transfer_reply(call);
372ee163
DH
852 if (ret < 0)
853 return ret;
260a9803
DH
854
855 /* unmarshall the reply once we've received all of it */
856 bp = call->buffer;
97e3043a
DH
857 xdr_decode_AFSFid(&bp, call->reply[1]);
858 xdr_decode_AFSFetchStatus(&bp, call->reply[2], NULL, NULL);
31143d5d 859 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
97e3043a 860 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
260a9803
DH
861
862 _leave(" = 0 [done]");
863 return 0;
864}
865
866/*
867 * FS.Symlink operation type
868 */
869static const struct afs_call_type afs_RXFSSymlink = {
870 .name = "FS.Symlink",
871 .deliver = afs_deliver_fs_symlink,
260a9803
DH
872 .destructor = afs_flat_call_destructor,
873};
874
875/*
876 * create a symbolic link
877 */
8b2a464c 878int afs_fs_symlink(struct afs_fs_cursor *fc,
260a9803
DH
879 const char *name,
880 const char *contents,
881 struct afs_fid *newfid,
d2ddc776 882 struct afs_file_status *newstatus)
260a9803 883{
d2ddc776 884 struct afs_vnode *vnode = fc->vnode;
260a9803 885 struct afs_call *call;
f044c884 886 struct afs_net *net = afs_v2net(vnode);
260a9803
DH
887 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
888 __be32 *bp;
889
890 _enter("");
891
892 namesz = strlen(name);
893 padsz = (4 - (namesz & 3)) & 3;
894
895 c_namesz = strlen(contents);
896 c_padsz = (4 - (c_namesz & 3)) & 3;
897
898 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
899
f044c884 900 call = afs_alloc_flat_call(net, &afs_RXFSSymlink, reqsz,
260a9803
DH
901 (3 + 21 + 21 + 6) * 4);
902 if (!call)
903 return -ENOMEM;
904
d2ddc776 905 call->key = fc->key;
97e3043a
DH
906 call->reply[0] = vnode;
907 call->reply[1] = newfid;
908 call->reply[2] = newstatus;
260a9803
DH
909
910 /* marshall the parameters */
911 bp = call->request;
912 *bp++ = htonl(FSSYMLINK);
913 *bp++ = htonl(vnode->fid.vid);
914 *bp++ = htonl(vnode->fid.vnode);
915 *bp++ = htonl(vnode->fid.unique);
916 *bp++ = htonl(namesz);
917 memcpy(bp, name, namesz);
918 bp = (void *) bp + namesz;
919 if (padsz > 0) {
920 memset(bp, 0, padsz);
921 bp = (void *) bp + padsz;
922 }
923 *bp++ = htonl(c_namesz);
924 memcpy(bp, contents, c_namesz);
925 bp = (void *) bp + c_namesz;
926 if (c_padsz > 0) {
927 memset(bp, 0, c_padsz);
928 bp = (void *) bp + c_padsz;
929 }
ab94f5d0
MD
930 *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
931 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
260a9803
DH
932 *bp++ = 0; /* owner */
933 *bp++ = 0; /* group */
934 *bp++ = htonl(S_IRWXUGO); /* unix mode */
935 *bp++ = 0; /* segment size */
936
d2ddc776
DH
937 afs_use_fs_server(call, fc->cbi);
938 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
260a9803
DH
939}
940
941/*
942 * deliver reply data to an FS.Rename
943 */
d001648e 944static int afs_deliver_fs_rename(struct afs_call *call)
260a9803 945{
97e3043a 946 struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
260a9803 947 const __be32 *bp;
372ee163 948 int ret;
260a9803 949
d001648e 950 _enter("{%u}", call->unmarshall);
260a9803 951
d001648e 952 ret = afs_transfer_reply(call);
372ee163
DH
953 if (ret < 0)
954 return ret;
260a9803
DH
955
956 /* unmarshall the reply once we've received all of it */
957 bp = call->buffer;
31143d5d 958 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
260a9803 959 if (new_dvnode != orig_dvnode)
31143d5d
DH
960 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
961 NULL);
97e3043a 962 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
260a9803
DH
963
964 _leave(" = 0 [done]");
965 return 0;
966}
967
968/*
969 * FS.Rename operation type
970 */
971static const struct afs_call_type afs_RXFSRename = {
972 .name = "FS.Rename",
973 .deliver = afs_deliver_fs_rename,
260a9803
DH
974 .destructor = afs_flat_call_destructor,
975};
976
977/*
978 * create a symbolic link
979 */
8b2a464c 980int afs_fs_rename(struct afs_fs_cursor *fc,
260a9803
DH
981 const char *orig_name,
982 struct afs_vnode *new_dvnode,
d2ddc776 983 const char *new_name)
260a9803 984{
d2ddc776 985 struct afs_vnode *orig_dvnode = fc->vnode;
260a9803 986 struct afs_call *call;
f044c884 987 struct afs_net *net = afs_v2net(orig_dvnode);
260a9803
DH
988 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
989 __be32 *bp;
990
991 _enter("");
992
993 o_namesz = strlen(orig_name);
994 o_padsz = (4 - (o_namesz & 3)) & 3;
995
996 n_namesz = strlen(new_name);
997 n_padsz = (4 - (n_namesz & 3)) & 3;
998
999 reqsz = (4 * 4) +
1000 4 + o_namesz + o_padsz +
1001 (3 * 4) +
1002 4 + n_namesz + n_padsz;
1003
f044c884 1004 call = afs_alloc_flat_call(net, &afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
260a9803
DH
1005 if (!call)
1006 return -ENOMEM;
1007
d2ddc776 1008 call->key = fc->key;
97e3043a
DH
1009 call->reply[0] = orig_dvnode;
1010 call->reply[1] = new_dvnode;
260a9803
DH
1011
1012 /* marshall the parameters */
1013 bp = call->request;
1014 *bp++ = htonl(FSRENAME);
1015 *bp++ = htonl(orig_dvnode->fid.vid);
1016 *bp++ = htonl(orig_dvnode->fid.vnode);
1017 *bp++ = htonl(orig_dvnode->fid.unique);
1018 *bp++ = htonl(o_namesz);
1019 memcpy(bp, orig_name, o_namesz);
1020 bp = (void *) bp + o_namesz;
1021 if (o_padsz > 0) {
1022 memset(bp, 0, o_padsz);
1023 bp = (void *) bp + o_padsz;
1024 }
1025
1026 *bp++ = htonl(new_dvnode->fid.vid);
1027 *bp++ = htonl(new_dvnode->fid.vnode);
1028 *bp++ = htonl(new_dvnode->fid.unique);
1029 *bp++ = htonl(n_namesz);
1030 memcpy(bp, new_name, n_namesz);
1031 bp = (void *) bp + n_namesz;
1032 if (n_padsz > 0) {
1033 memset(bp, 0, n_padsz);
1034 bp = (void *) bp + n_padsz;
1035 }
1036
d2ddc776
DH
1037 afs_use_fs_server(call, fc->cbi);
1038 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
260a9803 1039}
31143d5d
DH
1040
1041/*
1042 * deliver reply data to an FS.StoreData
1043 */
d001648e 1044static int afs_deliver_fs_store_data(struct afs_call *call)
31143d5d 1045{
97e3043a 1046 struct afs_vnode *vnode = call->reply[0];
31143d5d 1047 const __be32 *bp;
372ee163 1048 int ret;
31143d5d 1049
d001648e 1050 _enter("");
31143d5d 1051
d001648e 1052 ret = afs_transfer_reply(call);
372ee163
DH
1053 if (ret < 0)
1054 return ret;
31143d5d
DH
1055
1056 /* unmarshall the reply once we've received all of it */
1057 bp = call->buffer;
1058 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1059 &call->store_version);
97e3043a 1060 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
31143d5d
DH
1061
1062 afs_pages_written_back(vnode, call);
1063
1064 _leave(" = 0 [done]");
1065 return 0;
1066}
1067
1068/*
1069 * FS.StoreData operation type
1070 */
1071static const struct afs_call_type afs_RXFSStoreData = {
1072 .name = "FS.StoreData",
1073 .deliver = afs_deliver_fs_store_data,
31143d5d
DH
1074 .destructor = afs_flat_call_destructor,
1075};
1076
b9b1f8d5
DH
1077static const struct afs_call_type afs_RXFSStoreData64 = {
1078 .name = "FS.StoreData64",
1079 .deliver = afs_deliver_fs_store_data,
b9b1f8d5
DH
1080 .destructor = afs_flat_call_destructor,
1081};
1082
1083/*
1084 * store a set of pages to a very large file
1085 */
8b2a464c 1086static int afs_fs_store_data64(struct afs_fs_cursor *fc,
b9b1f8d5
DH
1087 struct afs_writeback *wb,
1088 pgoff_t first, pgoff_t last,
1089 unsigned offset, unsigned to,
d2ddc776 1090 loff_t size, loff_t pos, loff_t i_size)
b9b1f8d5
DH
1091{
1092 struct afs_vnode *vnode = wb->vnode;
1093 struct afs_call *call;
f044c884 1094 struct afs_net *net = afs_v2net(vnode);
b9b1f8d5
DH
1095 __be32 *bp;
1096
1097 _enter(",%x,{%x:%u},,",
1098 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1099
f044c884 1100 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
b9b1f8d5
DH
1101 (4 + 6 + 3 * 2) * 4,
1102 (21 + 6) * 4);
1103 if (!call)
1104 return -ENOMEM;
1105
1106 call->wb = wb;
1107 call->key = wb->key;
97e3043a 1108 call->reply[0] = vnode;
b9b1f8d5
DH
1109 call->mapping = vnode->vfs_inode.i_mapping;
1110 call->first = first;
1111 call->last = last;
1112 call->first_offset = offset;
1113 call->last_to = to;
1114 call->send_pages = true;
1115 call->store_version = vnode->status.data_version + 1;
1116
1117 /* marshall the parameters */
1118 bp = call->request;
1119 *bp++ = htonl(FSSTOREDATA64);
1120 *bp++ = htonl(vnode->fid.vid);
1121 *bp++ = htonl(vnode->fid.vnode);
1122 *bp++ = htonl(vnode->fid.unique);
1123
ab94f5d0
MD
1124 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1125 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
b9b1f8d5
DH
1126 *bp++ = 0; /* owner */
1127 *bp++ = 0; /* group */
1128 *bp++ = 0; /* unix mode */
1129 *bp++ = 0; /* segment size */
1130
1131 *bp++ = htonl(pos >> 32);
1132 *bp++ = htonl((u32) pos);
1133 *bp++ = htonl(size >> 32);
1134 *bp++ = htonl((u32) size);
1135 *bp++ = htonl(i_size >> 32);
1136 *bp++ = htonl((u32) i_size);
1137
d2ddc776 1138 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
b9b1f8d5
DH
1139}
1140
31143d5d
DH
1141/*
1142 * store a set of pages
1143 */
8b2a464c 1144int afs_fs_store_data(struct afs_fs_cursor *fc, struct afs_writeback *wb,
31143d5d 1145 pgoff_t first, pgoff_t last,
d2ddc776 1146 unsigned offset, unsigned to)
31143d5d
DH
1147{
1148 struct afs_vnode *vnode = wb->vnode;
1149 struct afs_call *call;
f044c884 1150 struct afs_net *net = afs_v2net(vnode);
31143d5d
DH
1151 loff_t size, pos, i_size;
1152 __be32 *bp;
1153
1154 _enter(",%x,{%x:%u},,",
1155 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1156
146a1192 1157 size = (loff_t)to - (loff_t)offset;
31143d5d
DH
1158 if (first != last)
1159 size += (loff_t)(last - first) << PAGE_SHIFT;
1160 pos = (loff_t)first << PAGE_SHIFT;
1161 pos += offset;
1162
1163 i_size = i_size_read(&vnode->vfs_inode);
1164 if (pos + size > i_size)
1165 i_size = size + pos;
1166
1167 _debug("size %llx, at %llx, i_size %llx",
1168 (unsigned long long) size, (unsigned long long) pos,
1169 (unsigned long long) i_size);
1170
b9b1f8d5 1171 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
8b2a464c 1172 return afs_fs_store_data64(fc, wb, first, last, offset, to,
d2ddc776 1173 size, pos, i_size);
31143d5d 1174
f044c884 1175 call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
31143d5d
DH
1176 (4 + 6 + 3) * 4,
1177 (21 + 6) * 4);
1178 if (!call)
1179 return -ENOMEM;
1180
1181 call->wb = wb;
1182 call->key = wb->key;
97e3043a 1183 call->reply[0] = vnode;
31143d5d
DH
1184 call->mapping = vnode->vfs_inode.i_mapping;
1185 call->first = first;
1186 call->last = last;
1187 call->first_offset = offset;
1188 call->last_to = to;
1189 call->send_pages = true;
1190 call->store_version = vnode->status.data_version + 1;
1191
1192 /* marshall the parameters */
1193 bp = call->request;
1194 *bp++ = htonl(FSSTOREDATA);
1195 *bp++ = htonl(vnode->fid.vid);
1196 *bp++ = htonl(vnode->fid.vnode);
1197 *bp++ = htonl(vnode->fid.unique);
1198
ab94f5d0
MD
1199 *bp++ = htonl(AFS_SET_MTIME); /* mask */
1200 *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
31143d5d
DH
1201 *bp++ = 0; /* owner */
1202 *bp++ = 0; /* group */
1203 *bp++ = 0; /* unix mode */
1204 *bp++ = 0; /* segment size */
1205
1206 *bp++ = htonl(pos);
1207 *bp++ = htonl(size);
1208 *bp++ = htonl(i_size);
1209
d2ddc776
DH
1210 afs_use_fs_server(call, fc->cbi);
1211 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
31143d5d
DH
1212}
1213
1214/*
1215 * deliver reply data to an FS.StoreStatus
1216 */
d001648e 1217static int afs_deliver_fs_store_status(struct afs_call *call)
31143d5d
DH
1218{
1219 afs_dataversion_t *store_version;
97e3043a 1220 struct afs_vnode *vnode = call->reply[0];
31143d5d 1221 const __be32 *bp;
372ee163 1222 int ret;
31143d5d 1223
d001648e 1224 _enter("");
31143d5d 1225
d001648e 1226 ret = afs_transfer_reply(call);
372ee163
DH
1227 if (ret < 0)
1228 return ret;
31143d5d
DH
1229
1230 /* unmarshall the reply once we've received all of it */
1231 store_version = NULL;
1232 if (call->operation_ID == FSSTOREDATA)
1233 store_version = &call->store_version;
1234
1235 bp = call->buffer;
1236 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
97e3043a 1237 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
31143d5d
DH
1238
1239 _leave(" = 0 [done]");
1240 return 0;
1241}
1242
1243/*
1244 * FS.StoreStatus operation type
1245 */
1246static const struct afs_call_type afs_RXFSStoreStatus = {
1247 .name = "FS.StoreStatus",
1248 .deliver = afs_deliver_fs_store_status,
31143d5d
DH
1249 .destructor = afs_flat_call_destructor,
1250};
1251
1252static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1253 .name = "FS.StoreData",
1254 .deliver = afs_deliver_fs_store_status,
31143d5d
DH
1255 .destructor = afs_flat_call_destructor,
1256};
1257
b9b1f8d5
DH
1258static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1259 .name = "FS.StoreData64",
1260 .deliver = afs_deliver_fs_store_status,
b9b1f8d5
DH
1261 .destructor = afs_flat_call_destructor,
1262};
1263
1264/*
1265 * set the attributes on a very large file, using FS.StoreData rather than
1266 * FS.StoreStatus so as to alter the file size also
1267 */
d2ddc776 1268static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
b9b1f8d5 1269{
d2ddc776 1270 struct afs_vnode *vnode = fc->vnode;
b9b1f8d5 1271 struct afs_call *call;
f044c884 1272 struct afs_net *net = afs_v2net(vnode);
b9b1f8d5
DH
1273 __be32 *bp;
1274
1275 _enter(",%x,{%x:%u},,",
d2ddc776 1276 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
b9b1f8d5
DH
1277
1278 ASSERT(attr->ia_valid & ATTR_SIZE);
1279
f044c884 1280 call = afs_alloc_flat_call(net, &afs_RXFSStoreData64_as_Status,
b9b1f8d5
DH
1281 (4 + 6 + 3 * 2) * 4,
1282 (21 + 6) * 4);
1283 if (!call)
1284 return -ENOMEM;
1285
d2ddc776 1286 call->key = fc->key;
97e3043a 1287 call->reply[0] = vnode;
b9b1f8d5
DH
1288 call->store_version = vnode->status.data_version + 1;
1289 call->operation_ID = FSSTOREDATA;
1290
1291 /* marshall the parameters */
1292 bp = call->request;
1293 *bp++ = htonl(FSSTOREDATA64);
1294 *bp++ = htonl(vnode->fid.vid);
1295 *bp++ = htonl(vnode->fid.vnode);
1296 *bp++ = htonl(vnode->fid.unique);
1297
1298 xdr_encode_AFS_StoreStatus(&bp, attr);
1299
1300 *bp++ = 0; /* position of start of write */
1301 *bp++ = 0;
1302 *bp++ = 0; /* size of write */
1303 *bp++ = 0;
1304 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1305 *bp++ = htonl((u32) attr->ia_size);
1306
d2ddc776
DH
1307 afs_use_fs_server(call, fc->cbi);
1308 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
b9b1f8d5
DH
1309}
1310
31143d5d
DH
1311/*
1312 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1313 * so as to alter the file size also
1314 */
d2ddc776 1315static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
31143d5d 1316{
d2ddc776 1317 struct afs_vnode *vnode = fc->vnode;
31143d5d 1318 struct afs_call *call;
f044c884 1319 struct afs_net *net = afs_v2net(vnode);
31143d5d
DH
1320 __be32 *bp;
1321
1322 _enter(",%x,{%x:%u},,",
d2ddc776 1323 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
31143d5d
DH
1324
1325 ASSERT(attr->ia_valid & ATTR_SIZE);
b9b1f8d5 1326 if (attr->ia_size >> 32)
d2ddc776 1327 return afs_fs_setattr_size64(fc, attr);
31143d5d 1328
f044c884 1329 call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
31143d5d
DH
1330 (4 + 6 + 3) * 4,
1331 (21 + 6) * 4);
1332 if (!call)
1333 return -ENOMEM;
1334
d2ddc776 1335 call->key = fc->key;
97e3043a 1336 call->reply[0] = vnode;
31143d5d
DH
1337 call->store_version = vnode->status.data_version + 1;
1338 call->operation_ID = FSSTOREDATA;
1339
1340 /* marshall the parameters */
1341 bp = call->request;
1342 *bp++ = htonl(FSSTOREDATA);
1343 *bp++ = htonl(vnode->fid.vid);
1344 *bp++ = htonl(vnode->fid.vnode);
1345 *bp++ = htonl(vnode->fid.unique);
1346
1347 xdr_encode_AFS_StoreStatus(&bp, attr);
1348
1349 *bp++ = 0; /* position of start of write */
1350 *bp++ = 0; /* size of write */
1351 *bp++ = htonl(attr->ia_size); /* new file length */
1352
d2ddc776
DH
1353 afs_use_fs_server(call, fc->cbi);
1354 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
31143d5d
DH
1355}
1356
1357/*
1358 * set the attributes on a file, using FS.StoreData if there's a change in file
1359 * size, and FS.StoreStatus otherwise
1360 */
d2ddc776 1361int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
31143d5d 1362{
d2ddc776 1363 struct afs_vnode *vnode = fc->vnode;
31143d5d 1364 struct afs_call *call;
f044c884 1365 struct afs_net *net = afs_v2net(vnode);
31143d5d
DH
1366 __be32 *bp;
1367
1368 if (attr->ia_valid & ATTR_SIZE)
d2ddc776 1369 return afs_fs_setattr_size(fc, attr);
31143d5d
DH
1370
1371 _enter(",%x,{%x:%u},,",
d2ddc776 1372 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
31143d5d 1373
f044c884 1374 call = afs_alloc_flat_call(net, &afs_RXFSStoreStatus,
31143d5d
DH
1375 (4 + 6) * 4,
1376 (21 + 6) * 4);
1377 if (!call)
1378 return -ENOMEM;
1379
d2ddc776 1380 call->key = fc->key;
97e3043a 1381 call->reply[0] = vnode;
31143d5d
DH
1382 call->operation_ID = FSSTORESTATUS;
1383
1384 /* marshall the parameters */
1385 bp = call->request;
1386 *bp++ = htonl(FSSTORESTATUS);
1387 *bp++ = htonl(vnode->fid.vid);
1388 *bp++ = htonl(vnode->fid.vnode);
1389 *bp++ = htonl(vnode->fid.unique);
1390
1391 xdr_encode_AFS_StoreStatus(&bp, attr);
1392
d2ddc776
DH
1393 afs_use_fs_server(call, fc->cbi);
1394 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
31143d5d 1395}
45222b9e
DH
1396
1397/*
1398 * deliver reply data to an FS.GetVolumeStatus
1399 */
d001648e 1400static int afs_deliver_fs_get_volume_status(struct afs_call *call)
45222b9e
DH
1401{
1402 const __be32 *bp;
1403 char *p;
1404 int ret;
1405
d001648e 1406 _enter("{%u}", call->unmarshall);
45222b9e
DH
1407
1408 switch (call->unmarshall) {
1409 case 0:
1410 call->offset = 0;
1411 call->unmarshall++;
1412
1413 /* extract the returned status record */
1414 case 1:
1415 _debug("extract status");
d001648e
DH
1416 ret = afs_extract_data(call, call->buffer,
1417 12 * 4, true);
372ee163
DH
1418 if (ret < 0)
1419 return ret;
45222b9e
DH
1420
1421 bp = call->buffer;
97e3043a 1422 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
45222b9e
DH
1423 call->offset = 0;
1424 call->unmarshall++;
1425
1426 /* extract the volume name length */
1427 case 2:
d001648e 1428 ret = afs_extract_data(call, &call->tmp, 4, true);
372ee163
DH
1429 if (ret < 0)
1430 return ret;
45222b9e
DH
1431
1432 call->count = ntohl(call->tmp);
1433 _debug("volname length: %u", call->count);
1434 if (call->count >= AFSNAMEMAX)
1435 return -EBADMSG;
1436 call->offset = 0;
1437 call->unmarshall++;
1438
1439 /* extract the volume name */
1440 case 3:
1441 _debug("extract volname");
1442 if (call->count > 0) {
97e3043a 1443 ret = afs_extract_data(call, call->reply[2],
d001648e 1444 call->count, true);
372ee163
DH
1445 if (ret < 0)
1446 return ret;
45222b9e
DH
1447 }
1448
97e3043a 1449 p = call->reply[2];
45222b9e
DH
1450 p[call->count] = 0;
1451 _debug("volname '%s'", p);
1452
1453 call->offset = 0;
1454 call->unmarshall++;
1455
1456 /* extract the volume name padding */
1457 if ((call->count & 3) == 0) {
1458 call->unmarshall++;
1459 goto no_volname_padding;
1460 }
1461 call->count = 4 - (call->count & 3);
1462
1463 case 4:
d001648e
DH
1464 ret = afs_extract_data(call, call->buffer,
1465 call->count, true);
372ee163
DH
1466 if (ret < 0)
1467 return ret;
45222b9e
DH
1468
1469 call->offset = 0;
1470 call->unmarshall++;
1471 no_volname_padding:
1472
1473 /* extract the offline message length */
1474 case 5:
d001648e 1475 ret = afs_extract_data(call, &call->tmp, 4, true);
372ee163
DH
1476 if (ret < 0)
1477 return ret;
45222b9e
DH
1478
1479 call->count = ntohl(call->tmp);
1480 _debug("offline msg length: %u", call->count);
1481 if (call->count >= AFSNAMEMAX)
1482 return -EBADMSG;
1483 call->offset = 0;
1484 call->unmarshall++;
1485
1486 /* extract the offline message */
1487 case 6:
1488 _debug("extract offline");
1489 if (call->count > 0) {
97e3043a 1490 ret = afs_extract_data(call, call->reply[2],
d001648e 1491 call->count, true);
372ee163
DH
1492 if (ret < 0)
1493 return ret;
45222b9e
DH
1494 }
1495
97e3043a 1496 p = call->reply[2];
45222b9e
DH
1497 p[call->count] = 0;
1498 _debug("offline '%s'", p);
1499
1500 call->offset = 0;
1501 call->unmarshall++;
1502
1503 /* extract the offline message padding */
1504 if ((call->count & 3) == 0) {
1505 call->unmarshall++;
1506 goto no_offline_padding;
1507 }
1508 call->count = 4 - (call->count & 3);
1509
1510 case 7:
d001648e
DH
1511 ret = afs_extract_data(call, call->buffer,
1512 call->count, true);
372ee163
DH
1513 if (ret < 0)
1514 return ret;
45222b9e
DH
1515
1516 call->offset = 0;
1517 call->unmarshall++;
1518 no_offline_padding:
1519
1520 /* extract the message of the day length */
1521 case 8:
d001648e 1522 ret = afs_extract_data(call, &call->tmp, 4, true);
372ee163
DH
1523 if (ret < 0)
1524 return ret;
45222b9e
DH
1525
1526 call->count = ntohl(call->tmp);
1527 _debug("motd length: %u", call->count);
1528 if (call->count >= AFSNAMEMAX)
1529 return -EBADMSG;
1530 call->offset = 0;
1531 call->unmarshall++;
1532
1533 /* extract the message of the day */
1534 case 9:
1535 _debug("extract motd");
1536 if (call->count > 0) {
97e3043a 1537 ret = afs_extract_data(call, call->reply[2],
d001648e 1538 call->count, true);
372ee163
DH
1539 if (ret < 0)
1540 return ret;
45222b9e
DH
1541 }
1542
97e3043a 1543 p = call->reply[2];
45222b9e
DH
1544 p[call->count] = 0;
1545 _debug("motd '%s'", p);
1546
1547 call->offset = 0;
1548 call->unmarshall++;
1549
1550 /* extract the message of the day padding */
d001648e 1551 call->count = (4 - (call->count & 3)) & 3;
45222b9e
DH
1552
1553 case 10:
d001648e
DH
1554 ret = afs_extract_data(call, call->buffer,
1555 call->count, false);
372ee163
DH
1556 if (ret < 0)
1557 return ret;
45222b9e
DH
1558
1559 call->offset = 0;
1560 call->unmarshall++;
45222b9e 1561 case 11:
45222b9e
DH
1562 break;
1563 }
1564
45222b9e
DH
1565 _leave(" = 0 [done]");
1566 return 0;
1567}
1568
1569/*
1570 * destroy an FS.GetVolumeStatus call
1571 */
1572static void afs_get_volume_status_call_destructor(struct afs_call *call)
1573{
97e3043a
DH
1574 kfree(call->reply[2]);
1575 call->reply[2] = NULL;
45222b9e
DH
1576 afs_flat_call_destructor(call);
1577}
1578
1579/*
1580 * FS.GetVolumeStatus operation type
1581 */
1582static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1583 .name = "FS.GetVolumeStatus",
1584 .deliver = afs_deliver_fs_get_volume_status,
45222b9e
DH
1585 .destructor = afs_get_volume_status_call_destructor,
1586};
1587
1588/*
1589 * fetch the status of a volume
1590 */
8b2a464c 1591int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
d2ddc776 1592 struct afs_volume_status *vs)
45222b9e 1593{
d2ddc776 1594 struct afs_vnode *vnode = fc->vnode;
45222b9e 1595 struct afs_call *call;
f044c884 1596 struct afs_net *net = afs_v2net(vnode);
45222b9e
DH
1597 __be32 *bp;
1598 void *tmpbuf;
1599
1600 _enter("");
1601
1602 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1603 if (!tmpbuf)
1604 return -ENOMEM;
1605
f044c884 1606 call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
45222b9e
DH
1607 if (!call) {
1608 kfree(tmpbuf);
1609 return -ENOMEM;
1610 }
1611
d2ddc776 1612 call->key = fc->key;
97e3043a
DH
1613 call->reply[0] = vnode;
1614 call->reply[1] = vs;
1615 call->reply[2] = tmpbuf;
45222b9e
DH
1616
1617 /* marshall the parameters */
1618 bp = call->request;
1619 bp[0] = htonl(FSGETVOLUMESTATUS);
1620 bp[1] = htonl(vnode->fid.vid);
1621
d2ddc776
DH
1622 afs_use_fs_server(call, fc->cbi);
1623 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
45222b9e 1624}
e8d6c554
DH
1625
1626/*
1627 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1628 */
d001648e 1629static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
e8d6c554
DH
1630{
1631 const __be32 *bp;
372ee163 1632 int ret;
e8d6c554 1633
d001648e 1634 _enter("{%u}", call->unmarshall);
e8d6c554 1635
d001648e 1636 ret = afs_transfer_reply(call);
372ee163
DH
1637 if (ret < 0)
1638 return ret;
e8d6c554
DH
1639
1640 /* unmarshall the reply once we've received all of it */
1641 bp = call->buffer;
97e3043a 1642 /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
e8d6c554
DH
1643
1644 _leave(" = 0 [done]");
1645 return 0;
1646}
1647
1648/*
1649 * FS.SetLock operation type
1650 */
1651static const struct afs_call_type afs_RXFSSetLock = {
1652 .name = "FS.SetLock",
1653 .deliver = afs_deliver_fs_xxxx_lock,
e8d6c554
DH
1654 .destructor = afs_flat_call_destructor,
1655};
1656
1657/*
1658 * FS.ExtendLock operation type
1659 */
1660static const struct afs_call_type afs_RXFSExtendLock = {
1661 .name = "FS.ExtendLock",
1662 .deliver = afs_deliver_fs_xxxx_lock,
e8d6c554
DH
1663 .destructor = afs_flat_call_destructor,
1664};
1665
1666/*
1667 * FS.ReleaseLock operation type
1668 */
1669static const struct afs_call_type afs_RXFSReleaseLock = {
1670 .name = "FS.ReleaseLock",
1671 .deliver = afs_deliver_fs_xxxx_lock,
e8d6c554
DH
1672 .destructor = afs_flat_call_destructor,
1673};
1674
1675/*
d2ddc776 1676 * Set a lock on a file
e8d6c554 1677 */
d2ddc776 1678int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
e8d6c554 1679{
d2ddc776 1680 struct afs_vnode *vnode = fc->vnode;
e8d6c554 1681 struct afs_call *call;
f044c884 1682 struct afs_net *net = afs_v2net(vnode);
e8d6c554
DH
1683 __be32 *bp;
1684
1685 _enter("");
1686
f044c884 1687 call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
e8d6c554
DH
1688 if (!call)
1689 return -ENOMEM;
1690
d2ddc776 1691 call->key = fc->key;
97e3043a 1692 call->reply[0] = vnode;
e8d6c554
DH
1693
1694 /* marshall the parameters */
1695 bp = call->request;
1696 *bp++ = htonl(FSSETLOCK);
1697 *bp++ = htonl(vnode->fid.vid);
1698 *bp++ = htonl(vnode->fid.vnode);
1699 *bp++ = htonl(vnode->fid.unique);
1700 *bp++ = htonl(type);
1701
d2ddc776
DH
1702 afs_use_fs_server(call, fc->cbi);
1703 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
e8d6c554
DH
1704}
1705
1706/*
1707 * extend a lock on a file
1708 */
d2ddc776 1709int afs_fs_extend_lock(struct afs_fs_cursor *fc)
e8d6c554 1710{
d2ddc776 1711 struct afs_vnode *vnode = fc->vnode;
e8d6c554 1712 struct afs_call *call;
f044c884 1713 struct afs_net *net = afs_v2net(vnode);
e8d6c554
DH
1714 __be32 *bp;
1715
1716 _enter("");
1717
f044c884 1718 call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
e8d6c554
DH
1719 if (!call)
1720 return -ENOMEM;
1721
d2ddc776 1722 call->key = fc->key;
97e3043a 1723 call->reply[0] = vnode;
e8d6c554
DH
1724
1725 /* marshall the parameters */
1726 bp = call->request;
1727 *bp++ = htonl(FSEXTENDLOCK);
1728 *bp++ = htonl(vnode->fid.vid);
1729 *bp++ = htonl(vnode->fid.vnode);
1730 *bp++ = htonl(vnode->fid.unique);
1731
d2ddc776
DH
1732 afs_use_fs_server(call, fc->cbi);
1733 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
e8d6c554
DH
1734}
1735
1736/*
1737 * release a lock on a file
1738 */
d2ddc776 1739int afs_fs_release_lock(struct afs_fs_cursor *fc)
e8d6c554 1740{
d2ddc776 1741 struct afs_vnode *vnode = fc->vnode;
e8d6c554 1742 struct afs_call *call;
f044c884 1743 struct afs_net *net = afs_v2net(vnode);
e8d6c554
DH
1744 __be32 *bp;
1745
1746 _enter("");
1747
f044c884 1748 call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
e8d6c554
DH
1749 if (!call)
1750 return -ENOMEM;
1751
d2ddc776 1752 call->key = fc->key;
97e3043a 1753 call->reply[0] = vnode;
e8d6c554
DH
1754
1755 /* marshall the parameters */
1756 bp = call->request;
1757 *bp++ = htonl(FSRELEASELOCK);
1758 *bp++ = htonl(vnode->fid.vid);
1759 *bp++ = htonl(vnode->fid.vnode);
1760 *bp++ = htonl(vnode->fid.unique);
1761
d2ddc776
DH
1762 afs_use_fs_server(call, fc->cbi);
1763 return afs_make_call(&fc->ac, call, GFP_NOFS, false);
c435ee34
DH
1764}
1765
1766/*
1767 * Deliver reply data to an FS.GiveUpAllCallBacks operation.
1768 */
1769static int afs_deliver_fs_give_up_all_callbacks(struct afs_call *call)
1770{
1771 return afs_transfer_reply(call);
1772}
1773
1774/*
1775 * FS.GiveUpAllCallBacks operation type
1776 */
1777static const struct afs_call_type afs_RXFSGiveUpAllCallBacks = {
1778 .name = "FS.GiveUpAllCallBacks",
1779 .deliver = afs_deliver_fs_give_up_all_callbacks,
1780 .destructor = afs_flat_call_destructor,
1781};
1782
1783/*
1784 * Flush all the callbacks we have on a server.
1785 */
d2ddc776
DH
1786int afs_fs_give_up_all_callbacks(struct afs_net *net,
1787 struct afs_server *server,
8b2a464c 1788 struct afs_addr_cursor *ac,
d2ddc776 1789 struct key *key)
c435ee34
DH
1790{
1791 struct afs_call *call;
1792 __be32 *bp;
1793
1794 _enter("");
1795
d2ddc776 1796 call = afs_alloc_flat_call(net, &afs_RXFSGiveUpAllCallBacks, 1 * 4, 0);
c435ee34
DH
1797 if (!call)
1798 return -ENOMEM;
1799
1800 call->key = key;
1801
1802 /* marshall the parameters */
1803 bp = call->request;
1804 *bp++ = htonl(FSGIVEUPALLCALLBACKS);
1805
1806 /* Can't take a ref on server */
d2ddc776
DH
1807 return afs_make_call(ac, call, GFP_NOFS, false);
1808}
1809
1810/*
1811 * Deliver reply data to an FS.GetCapabilities operation.
1812 */
1813static int afs_deliver_fs_get_capabilities(struct afs_call *call)
1814{
1815 u32 count;
1816 int ret;
1817
1818 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count);
1819
1820again:
1821 switch (call->unmarshall) {
1822 case 0:
1823 call->offset = 0;
1824 call->unmarshall++;
1825
1826 /* Extract the capabilities word count */
1827 case 1:
1828 ret = afs_extract_data(call, &call->tmp,
1829 1 * sizeof(__be32),
1830 true);
1831 if (ret < 0)
1832 return ret;
1833
1834 count = ntohl(call->tmp);
1835
1836 call->count = count;
1837 call->count2 = count;
1838 call->offset = 0;
1839 call->unmarshall++;
1840
1841 /* Extract capabilities words */
1842 case 2:
1843 count = min(call->count, 16U);
1844 ret = afs_extract_data(call, call->buffer,
1845 count * sizeof(__be32),
1846 call->count > 16);
1847 if (ret < 0)
1848 return ret;
1849
1850 /* TODO: Examine capabilities */
1851
1852 call->count -= count;
1853 if (call->count > 0)
1854 goto again;
1855 call->offset = 0;
1856 call->unmarshall++;
1857 break;
1858 }
1859
1860 _leave(" = 0 [done]");
1861 return 0;
1862}
1863
1864/*
1865 * FS.GetCapabilities operation type
1866 */
1867static const struct afs_call_type afs_RXFSGetCapabilities = {
1868 .name = "FS.GetCapabilities",
1869 .deliver = afs_deliver_fs_get_capabilities,
1870 .destructor = afs_flat_call_destructor,
1871};
1872
1873/*
1874 * Probe a fileserver for the capabilities that it supports. This can
1875 * return up to 196 words.
1876 */
1877int afs_fs_get_capabilities(struct afs_net *net,
1878 struct afs_server *server,
1879 struct afs_addr_cursor *ac,
1880 struct key *key)
1881{
1882 struct afs_call *call;
1883 __be32 *bp;
1884
1885 _enter("");
1886
1887 call = afs_alloc_flat_call(net, &afs_RXFSGetCapabilities, 1 * 4, 16 * 4);
1888 if (!call)
1889 return -ENOMEM;
1890
1891 call->key = key;
1892
1893 /* marshall the parameters */
1894 bp = call->request;
1895 *bp++ = htonl(FSGETCAPABILITIES);
1896
1897 /* Can't take a ref on server */
1898 return afs_make_call(ac, call, GFP_NOFS, false);
e8d6c554 1899}