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