add upper-32-bits macro
[deliverable/linux.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>
13#include <linux/sched.h>
08e0e7c8 14#include <linux/circ_buf.h>
1da177e4 15#include "internal.h"
08e0e7c8 16#include "afs_fs.h"
1da177e4 17
260a9803
DH
18/*
19 * decode an AFSFid block
20 */
21static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
22{
23 const __be32 *bp = *_bp;
24
25 fid->vid = ntohl(*bp++);
26 fid->vnode = ntohl(*bp++);
27 fid->unique = ntohl(*bp++);
28 *_bp = bp;
29}
30
1da177e4 31/*
08e0e7c8 32 * decode an AFSFetchStatus block
1da177e4 33 */
08e0e7c8 34static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
260a9803 35 struct afs_file_status *status,
31143d5d
DH
36 struct afs_vnode *vnode,
37 afs_dataversion_t *store_version)
1da177e4 38{
31143d5d 39 afs_dataversion_t expected_version;
08e0e7c8
DH
40 const __be32 *bp = *_bp;
41 umode_t mode;
260a9803 42 u64 data_version, size;
08e0e7c8
DH
43 u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
44
45#define EXTRACT(DST) \
46 do { \
47 u32 x = ntohl(*bp++); \
48 changed |= DST - x; \
49 DST = x; \
50 } while (0)
51
260a9803
DH
52 status->if_version = ntohl(*bp++);
53 EXTRACT(status->type);
54 EXTRACT(status->nlink);
55 size = ntohl(*bp++);
08e0e7c8 56 data_version = ntohl(*bp++);
260a9803
DH
57 EXTRACT(status->author);
58 EXTRACT(status->owner);
59 EXTRACT(status->caller_access); /* call ticket dependent */
60 EXTRACT(status->anon_access);
61 EXTRACT(status->mode);
62 EXTRACT(status->parent.vnode);
63 EXTRACT(status->parent.unique);
08e0e7c8 64 bp++; /* seg size */
260a9803
DH
65 status->mtime_client = ntohl(*bp++);
66 status->mtime_server = ntohl(*bp++);
67 EXTRACT(status->group);
08e0e7c8
DH
68 bp++; /* sync counter */
69 data_version |= (u64) ntohl(*bp++) << 32;
260a9803
DH
70 bp++; /* lock count */
71 size |= (u64) ntohl(*bp++) << 32;
72 bp++; /* spare 4 */
08e0e7c8
DH
73 *_bp = bp;
74
260a9803
DH
75 if (size != status->size) {
76 status->size = size;
77 changed |= true;
08e0e7c8 78 }
260a9803 79 status->mode &= S_IALLUGO;
08e0e7c8
DH
80
81 _debug("vnode time %lx, %lx",
260a9803
DH
82 status->mtime_client, status->mtime_server);
83
84 if (vnode) {
85 status->parent.vid = vnode->fid.vid;
86 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
87 _debug("vnode changed");
88 i_size_write(&vnode->vfs_inode, size);
89 vnode->vfs_inode.i_uid = status->owner;
90 vnode->vfs_inode.i_gid = status->group;
91 vnode->vfs_inode.i_version = vnode->fid.unique;
92 vnode->vfs_inode.i_nlink = status->nlink;
93
94 mode = vnode->vfs_inode.i_mode;
95 mode &= ~S_IALLUGO;
96 mode |= status->mode;
97 barrier();
98 vnode->vfs_inode.i_mode = mode;
99 }
100
101 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server;
102 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
103 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
104 }
105
31143d5d
DH
106 expected_version = status->data_version;
107 if (store_version)
108 expected_version = *store_version;
109
110 if (expected_version != data_version) {
260a9803
DH
111 status->data_version = data_version;
112 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
113 _debug("vnode modified %llx on {%x:%u}",
ba3e0e1a
DM
114 (unsigned long long) data_version,
115 vnode->fid.vid, vnode->fid.vnode);
260a9803
DH
116 set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
117 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
118 }
31143d5d
DH
119 } else if (store_version) {
120 status->data_version = data_version;
1da177e4 121 }
ec26815a 122}
1da177e4 123
1da177e4 124/*
08e0e7c8 125 * decode an AFSCallBack block
1da177e4 126 */
08e0e7c8 127static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode)
1da177e4 128{
08e0e7c8 129 const __be32 *bp = *_bp;
1da177e4 130
08e0e7c8
DH
131 vnode->cb_version = ntohl(*bp++);
132 vnode->cb_expiry = ntohl(*bp++);
133 vnode->cb_type = ntohl(*bp++);
134 vnode->cb_expires = vnode->cb_expiry + get_seconds();
135 *_bp = bp;
ec26815a 136}
1da177e4 137
260a9803
DH
138static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
139 struct afs_callback *cb)
140{
141 const __be32 *bp = *_bp;
142
143 cb->version = ntohl(*bp++);
144 cb->expiry = ntohl(*bp++);
145 cb->type = ntohl(*bp++);
146 *_bp = bp;
147}
148
1da177e4 149/*
08e0e7c8 150 * decode an AFSVolSync block
1da177e4 151 */
08e0e7c8
DH
152static void xdr_decode_AFSVolSync(const __be32 **_bp,
153 struct afs_volsync *volsync)
1da177e4 154{
08e0e7c8 155 const __be32 *bp = *_bp;
1da177e4 156
08e0e7c8
DH
157 volsync->creation = ntohl(*bp++);
158 bp++; /* spare2 */
159 bp++; /* spare3 */
160 bp++; /* spare4 */
161 bp++; /* spare5 */
162 bp++; /* spare6 */
163 *_bp = bp;
164}
1da177e4 165
31143d5d
DH
166/*
167 * encode the requested attributes into an AFSStoreStatus block
168 */
169static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
170{
171 __be32 *bp = *_bp;
172 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
173
174 mask = 0;
175 if (attr->ia_valid & ATTR_MTIME) {
176 mask |= AFS_SET_MTIME;
177 mtime = attr->ia_mtime.tv_sec;
178 }
179
180 if (attr->ia_valid & ATTR_UID) {
181 mask |= AFS_SET_OWNER;
182 owner = attr->ia_uid;
183 }
184
185 if (attr->ia_valid & ATTR_GID) {
186 mask |= AFS_SET_GROUP;
187 group = attr->ia_gid;
188 }
189
190 if (attr->ia_valid & ATTR_MODE) {
191 mask |= AFS_SET_MODE;
192 mode = attr->ia_mode & S_IALLUGO;
193 }
194
195 *bp++ = htonl(mask);
196 *bp++ = htonl(mtime);
197 *bp++ = htonl(owner);
198 *bp++ = htonl(group);
199 *bp++ = htonl(mode);
200 *bp++ = 0; /* segment size */
201 *_bp = bp;
202}
203
08e0e7c8
DH
204/*
205 * deliver reply data to an FS.FetchStatus
206 */
207static int afs_deliver_fs_fetch_status(struct afs_call *call,
208 struct sk_buff *skb, bool last)
209{
260a9803 210 struct afs_vnode *vnode = call->reply;
08e0e7c8 211 const __be32 *bp;
1da177e4 212
08e0e7c8 213 _enter(",,%u", last);
1da177e4 214
08e0e7c8
DH
215 afs_transfer_reply(call, skb);
216 if (!last)
217 return 0;
1da177e4 218
08e0e7c8
DH
219 if (call->reply_size != call->reply_max)
220 return -EBADMSG;
1da177e4 221
08e0e7c8
DH
222 /* unmarshall the reply once we've received all of it */
223 bp = call->buffer;
31143d5d 224 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
260a9803 225 xdr_decode_AFSCallBack(&bp, vnode);
08e0e7c8
DH
226 if (call->reply2)
227 xdr_decode_AFSVolSync(&bp, call->reply2);
1da177e4 228
08e0e7c8
DH
229 _leave(" = 0 [done]");
230 return 0;
ec26815a 231}
08e0e7c8
DH
232
233/*
234 * FS.FetchStatus operation type
235 */
236static const struct afs_call_type afs_RXFSFetchStatus = {
00d3b7a4 237 .name = "FS.FetchStatus",
08e0e7c8
DH
238 .deliver = afs_deliver_fs_fetch_status,
239 .abort_to_error = afs_abort_to_error,
240 .destructor = afs_flat_call_destructor,
241};
1da177e4 242
1da177e4
LT
243/*
244 * fetch the status information for a file
245 */
08e0e7c8 246int afs_fs_fetch_file_status(struct afs_server *server,
00d3b7a4 247 struct key *key,
08e0e7c8
DH
248 struct afs_vnode *vnode,
249 struct afs_volsync *volsync,
250 const struct afs_wait_mode *wait_mode)
1da177e4 251{
08e0e7c8 252 struct afs_call *call;
1da177e4
LT
253 __be32 *bp;
254
416351f2 255 _enter(",%x,{%x:%u},,",
260a9803 256 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1da177e4 257
260a9803 258 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
08e0e7c8
DH
259 if (!call)
260 return -ENOMEM;
1da177e4 261
00d3b7a4 262 call->key = key;
08e0e7c8
DH
263 call->reply = vnode;
264 call->reply2 = volsync;
265 call->service_id = FS_SERVICE;
266 call->port = htons(AFS_FS_PORT);
1da177e4
LT
267
268 /* marshall the parameters */
08e0e7c8 269 bp = call->request;
1da177e4
LT
270 bp[0] = htonl(FSFETCHSTATUS);
271 bp[1] = htonl(vnode->fid.vid);
272 bp[2] = htonl(vnode->fid.vnode);
273 bp[3] = htonl(vnode->fid.unique);
274
08e0e7c8 275 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
ec26815a 276}
1da177e4 277
1da177e4 278/*
08e0e7c8 279 * deliver reply data to an FS.FetchData
1da177e4 280 */
08e0e7c8
DH
281static int afs_deliver_fs_fetch_data(struct afs_call *call,
282 struct sk_buff *skb, bool last)
1da177e4 283{
260a9803 284 struct afs_vnode *vnode = call->reply;
08e0e7c8
DH
285 const __be32 *bp;
286 struct page *page;
287 void *buffer;
1da177e4 288 int ret;
1da177e4 289
08e0e7c8
DH
290 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
291
292 switch (call->unmarshall) {
293 case 0:
294 call->offset = 0;
295 call->unmarshall++;
296
297 /* extract the returned data length */
298 case 1:
299 _debug("extract data length");
300 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
301 switch (ret) {
302 case 0: break;
303 case -EAGAIN: return 0;
304 default: return ret;
305 }
1da177e4 306
08e0e7c8
DH
307 call->count = ntohl(call->tmp);
308 _debug("DATA length: %u", call->count);
309 if (call->count > PAGE_SIZE)
310 return -EBADMSG;
311 call->offset = 0;
312 call->unmarshall++;
313
08e0e7c8
DH
314 /* extract the returned data */
315 case 2:
316 _debug("extract data");
416351f2
DH
317 if (call->count > 0) {
318 page = call->reply3;
319 buffer = kmap_atomic(page, KM_USER0);
320 ret = afs_extract_data(call, skb, last, buffer,
321 call->count);
322 kunmap_atomic(buffer, KM_USER0);
323 switch (ret) {
324 case 0: break;
325 case -EAGAIN: return 0;
326 default: return ret;
327 }
08e0e7c8 328 }
1da177e4 329
08e0e7c8
DH
330 call->offset = 0;
331 call->unmarshall++;
1da177e4 332
08e0e7c8
DH
333 /* extract the metadata */
334 case 3:
260a9803
DH
335 ret = afs_extract_data(call, skb, last, call->buffer,
336 (21 + 3 + 6) * 4);
08e0e7c8
DH
337 switch (ret) {
338 case 0: break;
339 case -EAGAIN: return 0;
340 default: return ret;
341 }
342
343 bp = call->buffer;
31143d5d 344 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
260a9803 345 xdr_decode_AFSCallBack(&bp, vnode);
08e0e7c8
DH
346 if (call->reply2)
347 xdr_decode_AFSVolSync(&bp, call->reply2);
348
349 call->offset = 0;
350 call->unmarshall++;
1da177e4 351
08e0e7c8
DH
352 case 4:
353 _debug("trailer");
354 if (skb->len != 0)
355 return -EBADMSG;
356 break;
1da177e4
LT
357 }
358
08e0e7c8
DH
359 if (!last)
360 return 0;
361
416351f2
DH
362 if (call->count < PAGE_SIZE) {
363 _debug("clear");
364 page = call->reply3;
365 buffer = kmap_atomic(page, KM_USER0);
366 memset(buffer + call->count, 0, PAGE_SIZE - call->count);
367 kunmap_atomic(buffer, KM_USER0);
368 }
369
08e0e7c8
DH
370 _leave(" = 0 [done]");
371 return 0;
ec26815a 372}
1da177e4 373
1da177e4 374/*
08e0e7c8 375 * FS.FetchData operation type
1da177e4 376 */
08e0e7c8 377static const struct afs_call_type afs_RXFSFetchData = {
00d3b7a4 378 .name = "FS.FetchData",
08e0e7c8
DH
379 .deliver = afs_deliver_fs_fetch_data,
380 .abort_to_error = afs_abort_to_error,
381 .destructor = afs_flat_call_destructor,
382};
383
384/*
385 * fetch data from a file
386 */
387int afs_fs_fetch_data(struct afs_server *server,
00d3b7a4 388 struct key *key,
08e0e7c8
DH
389 struct afs_vnode *vnode,
390 off_t offset, size_t length,
391 struct page *buffer,
08e0e7c8 392 const struct afs_wait_mode *wait_mode)
1da177e4 393{
08e0e7c8 394 struct afs_call *call;
1da177e4
LT
395 __be32 *bp;
396
08e0e7c8 397 _enter("");
1da177e4 398
260a9803 399 call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
08e0e7c8
DH
400 if (!call)
401 return -ENOMEM;
1da177e4 402
00d3b7a4 403 call->key = key;
08e0e7c8 404 call->reply = vnode;
260a9803 405 call->reply2 = NULL; /* volsync */
08e0e7c8
DH
406 call->reply3 = buffer;
407 call->service_id = FS_SERVICE;
408 call->port = htons(AFS_FS_PORT);
1da177e4
LT
409
410 /* marshall the parameters */
08e0e7c8
DH
411 bp = call->request;
412 bp[0] = htonl(FSFETCHDATA);
413 bp[1] = htonl(vnode->fid.vid);
414 bp[2] = htonl(vnode->fid.vnode);
415 bp[3] = htonl(vnode->fid.unique);
416 bp[4] = htonl(offset);
417 bp[5] = htonl(length);
1da177e4 418
08e0e7c8
DH
419 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
420}
1da177e4 421
08e0e7c8
DH
422/*
423 * deliver reply data to an FS.GiveUpCallBacks
424 */
425static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
426 struct sk_buff *skb, bool last)
427{
428 _enter(",{%u},%d", skb->len, last);
1da177e4 429
08e0e7c8
DH
430 if (skb->len > 0)
431 return -EBADMSG; /* shouldn't be any reply data */
432 return 0;
ec26815a 433}
1da177e4 434
1da177e4 435/*
08e0e7c8
DH
436 * FS.GiveUpCallBacks operation type
437 */
438static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
00d3b7a4 439 .name = "FS.GiveUpCallBacks",
08e0e7c8
DH
440 .deliver = afs_deliver_fs_give_up_callbacks,
441 .abort_to_error = afs_abort_to_error,
442 .destructor = afs_flat_call_destructor,
443};
444
445/*
446 * give up a set of callbacks
447 * - the callbacks are held in the server->cb_break ring
1da177e4 448 */
08e0e7c8
DH
449int afs_fs_give_up_callbacks(struct afs_server *server,
450 const struct afs_wait_mode *wait_mode)
1da177e4 451{
08e0e7c8
DH
452 struct afs_call *call;
453 size_t ncallbacks;
454 __be32 *bp, *tp;
455 int loop;
1da177e4 456
08e0e7c8
DH
457 ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail,
458 ARRAY_SIZE(server->cb_break));
1da177e4 459
08e0e7c8 460 _enter("{%zu},", ncallbacks);
1da177e4 461
08e0e7c8
DH
462 if (ncallbacks == 0)
463 return 0;
464 if (ncallbacks > AFSCBMAX)
465 ncallbacks = AFSCBMAX;
1da177e4 466
08e0e7c8 467 _debug("break %zu callbacks", ncallbacks);
1da177e4 468
08e0e7c8
DH
469 call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks,
470 12 + ncallbacks * 6 * 4, 0);
471 if (!call)
472 return -ENOMEM;
473
474 call->service_id = FS_SERVICE;
475 call->port = htons(AFS_FS_PORT);
1da177e4
LT
476
477 /* marshall the parameters */
08e0e7c8
DH
478 bp = call->request;
479 tp = bp + 2 + ncallbacks * 3;
480 *bp++ = htonl(FSGIVEUPCALLBACKS);
481 *bp++ = htonl(ncallbacks);
482 *tp++ = htonl(ncallbacks);
483
484 atomic_sub(ncallbacks, &server->cb_break_n);
485 for (loop = ncallbacks; loop > 0; loop--) {
486 struct afs_callback *cb =
487 &server->cb_break[server->cb_break_tail];
488
489 *bp++ = htonl(cb->fid.vid);
490 *bp++ = htonl(cb->fid.vnode);
491 *bp++ = htonl(cb->fid.unique);
492 *tp++ = htonl(cb->version);
493 *tp++ = htonl(cb->expiry);
494 *tp++ = htonl(cb->type);
495 smp_mb();
496 server->cb_break_tail =
497 (server->cb_break_tail + 1) &
498 (ARRAY_SIZE(server->cb_break) - 1);
1da177e4
LT
499 }
500
08e0e7c8
DH
501 ASSERT(ncallbacks > 0);
502 wake_up_nr(&server->cb_break_waitq, ncallbacks);
1da177e4 503
08e0e7c8 504 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
ec26815a 505}
260a9803
DH
506
507/*
508 * deliver reply data to an FS.CreateFile or an FS.MakeDir
509 */
510static int afs_deliver_fs_create_vnode(struct afs_call *call,
511 struct sk_buff *skb, bool last)
512{
513 struct afs_vnode *vnode = call->reply;
514 const __be32 *bp;
515
516 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
517
518 afs_transfer_reply(call, skb);
519 if (!last)
520 return 0;
521
522 if (call->reply_size != call->reply_max)
523 return -EBADMSG;
524
525 /* unmarshall the reply once we've received all of it */
526 bp = call->buffer;
527 xdr_decode_AFSFid(&bp, call->reply2);
31143d5d
DH
528 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
529 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
260a9803
DH
530 xdr_decode_AFSCallBack_raw(&bp, call->reply4);
531 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
532
533 _leave(" = 0 [done]");
534 return 0;
535}
536
537/*
538 * FS.CreateFile and FS.MakeDir operation type
539 */
540static const struct afs_call_type afs_RXFSCreateXXXX = {
541 .name = "FS.CreateXXXX",
542 .deliver = afs_deliver_fs_create_vnode,
543 .abort_to_error = afs_abort_to_error,
544 .destructor = afs_flat_call_destructor,
545};
546
547/*
548 * create a file or make a directory
549 */
550int afs_fs_create(struct afs_server *server,
551 struct key *key,
552 struct afs_vnode *vnode,
553 const char *name,
554 umode_t mode,
555 struct afs_fid *newfid,
556 struct afs_file_status *newstatus,
557 struct afs_callback *newcb,
558 const struct afs_wait_mode *wait_mode)
559{
560 struct afs_call *call;
561 size_t namesz, reqsz, padsz;
562 __be32 *bp;
563
564 _enter("");
565
566 namesz = strlen(name);
567 padsz = (4 - (namesz & 3)) & 3;
568 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
569
570 call = afs_alloc_flat_call(&afs_RXFSCreateXXXX, reqsz,
571 (3 + 21 + 21 + 3 + 6) * 4);
572 if (!call)
573 return -ENOMEM;
574
575 call->key = key;
576 call->reply = vnode;
577 call->reply2 = newfid;
578 call->reply3 = newstatus;
579 call->reply4 = newcb;
580 call->service_id = FS_SERVICE;
581 call->port = htons(AFS_FS_PORT);
582
583 /* marshall the parameters */
584 bp = call->request;
585 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
586 *bp++ = htonl(vnode->fid.vid);
587 *bp++ = htonl(vnode->fid.vnode);
588 *bp++ = htonl(vnode->fid.unique);
589 *bp++ = htonl(namesz);
590 memcpy(bp, name, namesz);
591 bp = (void *) bp + namesz;
592 if (padsz > 0) {
593 memset(bp, 0, padsz);
594 bp = (void *) bp + padsz;
595 }
596 *bp++ = htonl(AFS_SET_MODE);
597 *bp++ = 0; /* mtime */
598 *bp++ = 0; /* owner */
599 *bp++ = 0; /* group */
600 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
601 *bp++ = 0; /* segment size */
602
603 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
604}
605
606/*
607 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
608 */
609static int afs_deliver_fs_remove(struct afs_call *call,
610 struct sk_buff *skb, bool last)
611{
612 struct afs_vnode *vnode = call->reply;
613 const __be32 *bp;
614
615 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
616
617 afs_transfer_reply(call, skb);
618 if (!last)
619 return 0;
620
621 if (call->reply_size != call->reply_max)
622 return -EBADMSG;
623
624 /* unmarshall the reply once we've received all of it */
625 bp = call->buffer;
31143d5d 626 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
260a9803
DH
627 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
628
629 _leave(" = 0 [done]");
630 return 0;
631}
632
633/*
634 * FS.RemoveDir/FS.RemoveFile operation type
635 */
636static const struct afs_call_type afs_RXFSRemoveXXXX = {
637 .name = "FS.RemoveXXXX",
638 .deliver = afs_deliver_fs_remove,
639 .abort_to_error = afs_abort_to_error,
640 .destructor = afs_flat_call_destructor,
641};
642
643/*
644 * remove a file or directory
645 */
646int afs_fs_remove(struct afs_server *server,
647 struct key *key,
648 struct afs_vnode *vnode,
649 const char *name,
650 bool isdir,
651 const struct afs_wait_mode *wait_mode)
652{
653 struct afs_call *call;
654 size_t namesz, reqsz, padsz;
655 __be32 *bp;
656
657 _enter("");
658
659 namesz = strlen(name);
660 padsz = (4 - (namesz & 3)) & 3;
661 reqsz = (5 * 4) + namesz + padsz;
662
663 call = afs_alloc_flat_call(&afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
664 if (!call)
665 return -ENOMEM;
666
667 call->key = key;
668 call->reply = vnode;
669 call->service_id = FS_SERVICE;
670 call->port = htons(AFS_FS_PORT);
671
672 /* marshall the parameters */
673 bp = call->request;
674 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
675 *bp++ = htonl(vnode->fid.vid);
676 *bp++ = htonl(vnode->fid.vnode);
677 *bp++ = htonl(vnode->fid.unique);
678 *bp++ = htonl(namesz);
679 memcpy(bp, name, namesz);
680 bp = (void *) bp + namesz;
681 if (padsz > 0) {
682 memset(bp, 0, padsz);
683 bp = (void *) bp + padsz;
684 }
685
686 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
687}
688
689/*
690 * deliver reply data to an FS.Link
691 */
692static int afs_deliver_fs_link(struct afs_call *call,
693 struct sk_buff *skb, bool last)
694{
695 struct afs_vnode *dvnode = call->reply, *vnode = call->reply2;
696 const __be32 *bp;
697
698 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
699
700 afs_transfer_reply(call, skb);
701 if (!last)
702 return 0;
703
704 if (call->reply_size != call->reply_max)
705 return -EBADMSG;
706
707 /* unmarshall the reply once we've received all of it */
708 bp = call->buffer;
31143d5d
DH
709 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
710 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
260a9803
DH
711 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
712
713 _leave(" = 0 [done]");
714 return 0;
715}
716
717/*
718 * FS.Link operation type
719 */
720static const struct afs_call_type afs_RXFSLink = {
721 .name = "FS.Link",
722 .deliver = afs_deliver_fs_link,
723 .abort_to_error = afs_abort_to_error,
724 .destructor = afs_flat_call_destructor,
725};
726
727/*
728 * make a hard link
729 */
730int afs_fs_link(struct afs_server *server,
731 struct key *key,
732 struct afs_vnode *dvnode,
733 struct afs_vnode *vnode,
734 const char *name,
735 const struct afs_wait_mode *wait_mode)
736{
737 struct afs_call *call;
738 size_t namesz, reqsz, padsz;
739 __be32 *bp;
740
741 _enter("");
742
743 namesz = strlen(name);
744 padsz = (4 - (namesz & 3)) & 3;
745 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
746
747 call = afs_alloc_flat_call(&afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
748 if (!call)
749 return -ENOMEM;
750
751 call->key = key;
752 call->reply = dvnode;
753 call->reply2 = vnode;
754 call->service_id = FS_SERVICE;
755 call->port = htons(AFS_FS_PORT);
756
757 /* marshall the parameters */
758 bp = call->request;
759 *bp++ = htonl(FSLINK);
760 *bp++ = htonl(dvnode->fid.vid);
761 *bp++ = htonl(dvnode->fid.vnode);
762 *bp++ = htonl(dvnode->fid.unique);
763 *bp++ = htonl(namesz);
764 memcpy(bp, name, namesz);
765 bp = (void *) bp + namesz;
766 if (padsz > 0) {
767 memset(bp, 0, padsz);
768 bp = (void *) bp + padsz;
769 }
770 *bp++ = htonl(vnode->fid.vid);
771 *bp++ = htonl(vnode->fid.vnode);
772 *bp++ = htonl(vnode->fid.unique);
773
774 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
775}
776
777/*
778 * deliver reply data to an FS.Symlink
779 */
780static int afs_deliver_fs_symlink(struct afs_call *call,
781 struct sk_buff *skb, bool last)
782{
783 struct afs_vnode *vnode = call->reply;
784 const __be32 *bp;
785
786 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
787
788 afs_transfer_reply(call, skb);
789 if (!last)
790 return 0;
791
792 if (call->reply_size != call->reply_max)
793 return -EBADMSG;
794
795 /* unmarshall the reply once we've received all of it */
796 bp = call->buffer;
797 xdr_decode_AFSFid(&bp, call->reply2);
31143d5d
DH
798 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
799 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
260a9803
DH
800 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
801
802 _leave(" = 0 [done]");
803 return 0;
804}
805
806/*
807 * FS.Symlink operation type
808 */
809static const struct afs_call_type afs_RXFSSymlink = {
810 .name = "FS.Symlink",
811 .deliver = afs_deliver_fs_symlink,
812 .abort_to_error = afs_abort_to_error,
813 .destructor = afs_flat_call_destructor,
814};
815
816/*
817 * create a symbolic link
818 */
819int afs_fs_symlink(struct afs_server *server,
820 struct key *key,
821 struct afs_vnode *vnode,
822 const char *name,
823 const char *contents,
824 struct afs_fid *newfid,
825 struct afs_file_status *newstatus,
826 const struct afs_wait_mode *wait_mode)
827{
828 struct afs_call *call;
829 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
830 __be32 *bp;
831
832 _enter("");
833
834 namesz = strlen(name);
835 padsz = (4 - (namesz & 3)) & 3;
836
837 c_namesz = strlen(contents);
838 c_padsz = (4 - (c_namesz & 3)) & 3;
839
840 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
841
842 call = afs_alloc_flat_call(&afs_RXFSSymlink, reqsz,
843 (3 + 21 + 21 + 6) * 4);
844 if (!call)
845 return -ENOMEM;
846
847 call->key = key;
848 call->reply = vnode;
849 call->reply2 = newfid;
850 call->reply3 = newstatus;
851 call->service_id = FS_SERVICE;
852 call->port = htons(AFS_FS_PORT);
853
854 /* marshall the parameters */
855 bp = call->request;
856 *bp++ = htonl(FSSYMLINK);
857 *bp++ = htonl(vnode->fid.vid);
858 *bp++ = htonl(vnode->fid.vnode);
859 *bp++ = htonl(vnode->fid.unique);
860 *bp++ = htonl(namesz);
861 memcpy(bp, name, namesz);
862 bp = (void *) bp + namesz;
863 if (padsz > 0) {
864 memset(bp, 0, padsz);
865 bp = (void *) bp + padsz;
866 }
867 *bp++ = htonl(c_namesz);
868 memcpy(bp, contents, c_namesz);
869 bp = (void *) bp + c_namesz;
870 if (c_padsz > 0) {
871 memset(bp, 0, c_padsz);
872 bp = (void *) bp + c_padsz;
873 }
874 *bp++ = htonl(AFS_SET_MODE);
875 *bp++ = 0; /* mtime */
876 *bp++ = 0; /* owner */
877 *bp++ = 0; /* group */
878 *bp++ = htonl(S_IRWXUGO); /* unix mode */
879 *bp++ = 0; /* segment size */
880
881 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
882}
883
884/*
885 * deliver reply data to an FS.Rename
886 */
887static int afs_deliver_fs_rename(struct afs_call *call,
888 struct sk_buff *skb, bool last)
889{
890 struct afs_vnode *orig_dvnode = call->reply, *new_dvnode = call->reply2;
891 const __be32 *bp;
892
893 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
894
895 afs_transfer_reply(call, skb);
896 if (!last)
897 return 0;
898
899 if (call->reply_size != call->reply_max)
900 return -EBADMSG;
901
902 /* unmarshall the reply once we've received all of it */
903 bp = call->buffer;
31143d5d 904 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
260a9803 905 if (new_dvnode != orig_dvnode)
31143d5d
DH
906 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
907 NULL);
260a9803
DH
908 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
909
910 _leave(" = 0 [done]");
911 return 0;
912}
913
914/*
915 * FS.Rename operation type
916 */
917static const struct afs_call_type afs_RXFSRename = {
918 .name = "FS.Rename",
919 .deliver = afs_deliver_fs_rename,
920 .abort_to_error = afs_abort_to_error,
921 .destructor = afs_flat_call_destructor,
922};
923
924/*
925 * create a symbolic link
926 */
927int afs_fs_rename(struct afs_server *server,
928 struct key *key,
929 struct afs_vnode *orig_dvnode,
930 const char *orig_name,
931 struct afs_vnode *new_dvnode,
932 const char *new_name,
933 const struct afs_wait_mode *wait_mode)
934{
935 struct afs_call *call;
936 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
937 __be32 *bp;
938
939 _enter("");
940
941 o_namesz = strlen(orig_name);
942 o_padsz = (4 - (o_namesz & 3)) & 3;
943
944 n_namesz = strlen(new_name);
945 n_padsz = (4 - (n_namesz & 3)) & 3;
946
947 reqsz = (4 * 4) +
948 4 + o_namesz + o_padsz +
949 (3 * 4) +
950 4 + n_namesz + n_padsz;
951
952 call = afs_alloc_flat_call(&afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
953 if (!call)
954 return -ENOMEM;
955
956 call->key = key;
957 call->reply = orig_dvnode;
958 call->reply2 = new_dvnode;
959 call->service_id = FS_SERVICE;
960 call->port = htons(AFS_FS_PORT);
961
962 /* marshall the parameters */
963 bp = call->request;
964 *bp++ = htonl(FSRENAME);
965 *bp++ = htonl(orig_dvnode->fid.vid);
966 *bp++ = htonl(orig_dvnode->fid.vnode);
967 *bp++ = htonl(orig_dvnode->fid.unique);
968 *bp++ = htonl(o_namesz);
969 memcpy(bp, orig_name, o_namesz);
970 bp = (void *) bp + o_namesz;
971 if (o_padsz > 0) {
972 memset(bp, 0, o_padsz);
973 bp = (void *) bp + o_padsz;
974 }
975
976 *bp++ = htonl(new_dvnode->fid.vid);
977 *bp++ = htonl(new_dvnode->fid.vnode);
978 *bp++ = htonl(new_dvnode->fid.unique);
979 *bp++ = htonl(n_namesz);
980 memcpy(bp, new_name, n_namesz);
981 bp = (void *) bp + n_namesz;
982 if (n_padsz > 0) {
983 memset(bp, 0, n_padsz);
984 bp = (void *) bp + n_padsz;
985 }
986
987 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
988}
31143d5d
DH
989
990/*
991 * deliver reply data to an FS.StoreData
992 */
993static int afs_deliver_fs_store_data(struct afs_call *call,
994 struct sk_buff *skb, bool last)
995{
996 struct afs_vnode *vnode = call->reply;
997 const __be32 *bp;
998
999 _enter(",,%u", last);
1000
1001 afs_transfer_reply(call, skb);
1002 if (!last) {
1003 _leave(" = 0 [more]");
1004 return 0;
1005 }
1006
1007 if (call->reply_size != call->reply_max) {
1008 _leave(" = -EBADMSG [%u != %u]",
1009 call->reply_size, call->reply_max);
1010 return -EBADMSG;
1011 }
1012
1013 /* unmarshall the reply once we've received all of it */
1014 bp = call->buffer;
1015 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1016 &call->store_version);
1017 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1018
1019 afs_pages_written_back(vnode, call);
1020
1021 _leave(" = 0 [done]");
1022 return 0;
1023}
1024
1025/*
1026 * FS.StoreData operation type
1027 */
1028static const struct afs_call_type afs_RXFSStoreData = {
1029 .name = "FS.StoreData",
1030 .deliver = afs_deliver_fs_store_data,
1031 .abort_to_error = afs_abort_to_error,
1032 .destructor = afs_flat_call_destructor,
1033};
1034
1035/*
1036 * store a set of pages
1037 */
1038int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
1039 pgoff_t first, pgoff_t last,
1040 unsigned offset, unsigned to,
1041 const struct afs_wait_mode *wait_mode)
1042{
1043 struct afs_vnode *vnode = wb->vnode;
1044 struct afs_call *call;
1045 loff_t size, pos, i_size;
1046 __be32 *bp;
1047
1048 _enter(",%x,{%x:%u},,",
1049 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1050
1051 size = to - offset;
1052 if (first != last)
1053 size += (loff_t)(last - first) << PAGE_SHIFT;
1054 pos = (loff_t)first << PAGE_SHIFT;
1055 pos += offset;
1056
1057 i_size = i_size_read(&vnode->vfs_inode);
1058 if (pos + size > i_size)
1059 i_size = size + pos;
1060
1061 _debug("size %llx, at %llx, i_size %llx",
1062 (unsigned long long) size, (unsigned long long) pos,
1063 (unsigned long long) i_size);
1064
1065 BUG_ON(i_size > 0xffffffff); // TODO: use 64-bit store
1066
1067 call = afs_alloc_flat_call(&afs_RXFSStoreData,
1068 (4 + 6 + 3) * 4,
1069 (21 + 6) * 4);
1070 if (!call)
1071 return -ENOMEM;
1072
1073 call->wb = wb;
1074 call->key = wb->key;
1075 call->reply = vnode;
1076 call->service_id = FS_SERVICE;
1077 call->port = htons(AFS_FS_PORT);
1078 call->mapping = vnode->vfs_inode.i_mapping;
1079 call->first = first;
1080 call->last = last;
1081 call->first_offset = offset;
1082 call->last_to = to;
1083 call->send_pages = true;
1084 call->store_version = vnode->status.data_version + 1;
1085
1086 /* marshall the parameters */
1087 bp = call->request;
1088 *bp++ = htonl(FSSTOREDATA);
1089 *bp++ = htonl(vnode->fid.vid);
1090 *bp++ = htonl(vnode->fid.vnode);
1091 *bp++ = htonl(vnode->fid.unique);
1092
1093 *bp++ = 0; /* mask */
1094 *bp++ = 0; /* mtime */
1095 *bp++ = 0; /* owner */
1096 *bp++ = 0; /* group */
1097 *bp++ = 0; /* unix mode */
1098 *bp++ = 0; /* segment size */
1099
1100 *bp++ = htonl(pos);
1101 *bp++ = htonl(size);
1102 *bp++ = htonl(i_size);
1103
1104 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1105}
1106
1107/*
1108 * deliver reply data to an FS.StoreStatus
1109 */
1110static int afs_deliver_fs_store_status(struct afs_call *call,
1111 struct sk_buff *skb, bool last)
1112{
1113 afs_dataversion_t *store_version;
1114 struct afs_vnode *vnode = call->reply;
1115 const __be32 *bp;
1116
1117 _enter(",,%u", last);
1118
1119 afs_transfer_reply(call, skb);
1120 if (!last) {
1121 _leave(" = 0 [more]");
1122 return 0;
1123 }
1124
1125 if (call->reply_size != call->reply_max) {
1126 _leave(" = -EBADMSG [%u != %u]",
1127 call->reply_size, call->reply_max);
1128 return -EBADMSG;
1129 }
1130
1131 /* unmarshall the reply once we've received all of it */
1132 store_version = NULL;
1133 if (call->operation_ID == FSSTOREDATA)
1134 store_version = &call->store_version;
1135
1136 bp = call->buffer;
1137 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
1138 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1139
1140 _leave(" = 0 [done]");
1141 return 0;
1142}
1143
1144/*
1145 * FS.StoreStatus operation type
1146 */
1147static const struct afs_call_type afs_RXFSStoreStatus = {
1148 .name = "FS.StoreStatus",
1149 .deliver = afs_deliver_fs_store_status,
1150 .abort_to_error = afs_abort_to_error,
1151 .destructor = afs_flat_call_destructor,
1152};
1153
1154static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1155 .name = "FS.StoreData",
1156 .deliver = afs_deliver_fs_store_status,
1157 .abort_to_error = afs_abort_to_error,
1158 .destructor = afs_flat_call_destructor,
1159};
1160
1161/*
1162 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1163 * so as to alter the file size also
1164 */
1165static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
1166 struct afs_vnode *vnode, struct iattr *attr,
1167 const struct afs_wait_mode *wait_mode)
1168{
1169 struct afs_call *call;
1170 __be32 *bp;
1171
1172 _enter(",%x,{%x:%u},,",
1173 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1174
1175 ASSERT(attr->ia_valid & ATTR_SIZE);
1176 ASSERTCMP(attr->ia_size, <=, 0xffffffff); // TODO: use 64-bit store
1177
1178 call = afs_alloc_flat_call(&afs_RXFSStoreData_as_Status,
1179 (4 + 6 + 3) * 4,
1180 (21 + 6) * 4);
1181 if (!call)
1182 return -ENOMEM;
1183
1184 call->key = key;
1185 call->reply = vnode;
1186 call->service_id = FS_SERVICE;
1187 call->port = htons(AFS_FS_PORT);
1188 call->store_version = vnode->status.data_version + 1;
1189 call->operation_ID = FSSTOREDATA;
1190
1191 /* marshall the parameters */
1192 bp = call->request;
1193 *bp++ = htonl(FSSTOREDATA);
1194 *bp++ = htonl(vnode->fid.vid);
1195 *bp++ = htonl(vnode->fid.vnode);
1196 *bp++ = htonl(vnode->fid.unique);
1197
1198 xdr_encode_AFS_StoreStatus(&bp, attr);
1199
1200 *bp++ = 0; /* position of start of write */
1201 *bp++ = 0; /* size of write */
1202 *bp++ = htonl(attr->ia_size); /* new file length */
1203
1204 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1205}
1206
1207/*
1208 * set the attributes on a file, using FS.StoreData if there's a change in file
1209 * size, and FS.StoreStatus otherwise
1210 */
1211int afs_fs_setattr(struct afs_server *server, struct key *key,
1212 struct afs_vnode *vnode, struct iattr *attr,
1213 const struct afs_wait_mode *wait_mode)
1214{
1215 struct afs_call *call;
1216 __be32 *bp;
1217
1218 if (attr->ia_valid & ATTR_SIZE)
1219 return afs_fs_setattr_size(server, key, vnode, attr,
1220 wait_mode);
1221
1222 _enter(",%x,{%x:%u},,",
1223 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1224
1225 call = afs_alloc_flat_call(&afs_RXFSStoreStatus,
1226 (4 + 6) * 4,
1227 (21 + 6) * 4);
1228 if (!call)
1229 return -ENOMEM;
1230
1231 call->key = key;
1232 call->reply = vnode;
1233 call->service_id = FS_SERVICE;
1234 call->port = htons(AFS_FS_PORT);
1235 call->operation_ID = FSSTORESTATUS;
1236
1237 /* marshall the parameters */
1238 bp = call->request;
1239 *bp++ = htonl(FSSTORESTATUS);
1240 *bp++ = htonl(vnode->fid.vid);
1241 *bp++ = htonl(vnode->fid.vnode);
1242 *bp++ = htonl(vnode->fid.unique);
1243
1244 xdr_encode_AFS_StoreStatus(&bp, attr);
1245
1246 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1247}
This page took 0.360821 seconds and 5 git commands to generate.