aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/fsclient.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/afs/fsclient.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r--fs/afs/fsclient.c837
1 files changed, 837 insertions, 0 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
new file mode 100644
index 000000000000..61bc371532ab
--- /dev/null
+++ b/fs/afs/fsclient.c
@@ -0,0 +1,837 @@
1/* fsclient.c: AFS File Server client stubs
2 *
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public 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>
14#include <rxrpc/rxrpc.h>
15#include <rxrpc/transport.h>
16#include <rxrpc/connection.h>
17#include <rxrpc/call.h>
18#include "fsclient.h"
19#include "cmservice.h"
20#include "vnode.h"
21#include "server.h"
22#include "errors.h"
23#include "internal.h"
24
25#define FSFETCHSTATUS 132 /* AFS Fetch file status */
26#define FSFETCHDATA 130 /* AFS Fetch file data */
27#define FSGIVEUPCALLBACKS 147 /* AFS Discard callback promises */
28#define FSGETVOLUMEINFO 148 /* AFS Get root volume information */
29#define FSGETROOTVOLUME 151 /* AFS Get root volume name */
30#define FSLOOKUP 161 /* AFS lookup file in directory */
31
32/*****************************************************************************/
33/*
34 * map afs abort codes to/from Linux error codes
35 * - called with call->lock held
36 */
37static void afs_rxfs_aemap(struct rxrpc_call *call)
38{
39 switch (call->app_err_state) {
40 case RXRPC_ESTATE_LOCAL_ABORT:
41 call->app_abort_code = -call->app_errno;
42 break;
43 case RXRPC_ESTATE_PEER_ABORT:
44 call->app_errno = afs_abort_to_error(call->app_abort_code);
45 break;
46 default:
47 break;
48 }
49} /* end afs_rxfs_aemap() */
50
51/*****************************************************************************/
52/*
53 * get the root volume name from a fileserver
54 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
55 */
56#if 0
57int afs_rxfs_get_root_volume(struct afs_server *server,
58 char *buf, size_t *buflen)
59{
60 struct rxrpc_connection *conn;
61 struct rxrpc_call *call;
62 struct kvec piov[2];
63 size_t sent;
64 int ret;
65 u32 param[1];
66
67 DECLARE_WAITQUEUE(myself, current);
68
69 kenter("%p,%p,%u",server, buf, *buflen);
70
71 /* get hold of the fileserver connection */
72 ret = afs_server_get_fsconn(server, &conn);
73 if (ret < 0)
74 goto out;
75
76 /* create a call through that connection */
77 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
78 if (ret < 0) {
79 printk("kAFS: Unable to create call: %d\n", ret);
80 goto out_put_conn;
81 }
82 call->app_opcode = FSGETROOTVOLUME;
83
84 /* we want to get event notifications from the call */
85 add_wait_queue(&call->waitq, &myself);
86
87 /* marshall the parameters */
88 param[0] = htonl(FSGETROOTVOLUME);
89
90 piov[0].iov_len = sizeof(param);
91 piov[0].iov_base = param;
92
93 /* send the parameters to the server */
94 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
95 0, &sent);
96 if (ret < 0)
97 goto abort;
98
99 /* wait for the reply to completely arrive */
100 for (;;) {
101 set_current_state(TASK_INTERRUPTIBLE);
102 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
103 signal_pending(current))
104 break;
105 schedule();
106 }
107 set_current_state(TASK_RUNNING);
108
109 ret = -EINTR;
110 if (signal_pending(current))
111 goto abort;
112
113 switch (call->app_call_state) {
114 case RXRPC_CSTATE_ERROR:
115 ret = call->app_errno;
116 kdebug("Got Error: %d", ret);
117 goto out_unwait;
118
119 case RXRPC_CSTATE_CLNT_GOT_REPLY:
120 /* read the reply */
121 kdebug("Got Reply: qty=%d", call->app_ready_qty);
122
123 ret = -EBADMSG;
124 if (call->app_ready_qty <= 4)
125 goto abort;
126
127 ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0);
128 if (ret < 0)
129 goto abort;
130
131#if 0
132 /* unmarshall the reply */
133 bp = buffer;
134 for (loop = 0; loop < 65; loop++)
135 entry->name[loop] = ntohl(*bp++);
136 entry->name[64] = 0;
137
138 entry->type = ntohl(*bp++);
139 entry->num_servers = ntohl(*bp++);
140
141 for (loop = 0; loop < 8; loop++)
142 entry->servers[loop].addr.s_addr = *bp++;
143
144 for (loop = 0; loop < 8; loop++)
145 entry->servers[loop].partition = ntohl(*bp++);
146
147 for (loop = 0; loop < 8; loop++)
148 entry->servers[loop].flags = ntohl(*bp++);
149
150 for (loop = 0; loop < 3; loop++)
151 entry->volume_ids[loop] = ntohl(*bp++);
152
153 entry->clone_id = ntohl(*bp++);
154 entry->flags = ntohl(*bp);
155#endif
156
157 /* success */
158 ret = 0;
159 goto out_unwait;
160
161 default:
162 BUG();
163 }
164
165 abort:
166 set_current_state(TASK_UNINTERRUPTIBLE);
167 rxrpc_call_abort(call, ret);
168 schedule();
169 out_unwait:
170 set_current_state(TASK_RUNNING);
171 remove_wait_queue(&call->waitq, &myself);
172 rxrpc_put_call(call);
173 out_put_conn:
174 afs_server_release_fsconn(server, conn);
175 out:
176 kleave("");
177 return ret;
178} /* end afs_rxfs_get_root_volume() */
179#endif
180
181/*****************************************************************************/
182/*
183 * get information about a volume
184 */
185#if 0
186int afs_rxfs_get_volume_info(struct afs_server *server,
187 const char *name,
188 struct afs_volume_info *vinfo)
189{
190 struct rxrpc_connection *conn;
191 struct rxrpc_call *call;
192 struct kvec piov[3];
193 size_t sent;
194 int ret;
195 u32 param[2], *bp, zero;
196
197 DECLARE_WAITQUEUE(myself, current);
198
199 _enter("%p,%s,%p", server, name, vinfo);
200
201 /* get hold of the fileserver connection */
202 ret = afs_server_get_fsconn(server, &conn);
203 if (ret < 0)
204 goto out;
205
206 /* create a call through that connection */
207 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
208 if (ret < 0) {
209 printk("kAFS: Unable to create call: %d\n", ret);
210 goto out_put_conn;
211 }
212 call->app_opcode = FSGETVOLUMEINFO;
213
214 /* we want to get event notifications from the call */
215 add_wait_queue(&call->waitq, &myself);
216
217 /* marshall the parameters */
218 piov[1].iov_len = strlen(name);
219 piov[1].iov_base = (char *) name;
220
221 zero = 0;
222 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
223 piov[2].iov_base = &zero;
224
225 param[0] = htonl(FSGETVOLUMEINFO);
226 param[1] = htonl(piov[1].iov_len);
227
228 piov[0].iov_len = sizeof(param);
229 piov[0].iov_base = param;
230
231 /* send the parameters to the server */
232 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
233 0, &sent);
234 if (ret < 0)
235 goto abort;
236
237 /* wait for the reply to completely arrive */
238 bp = rxrpc_call_alloc_scratch(call, 64);
239
240 ret = rxrpc_call_read_data(call, bp, 64,
241 RXRPC_CALL_READ_BLOCK |
242 RXRPC_CALL_READ_ALL);
243 if (ret < 0) {
244 if (ret == -ECONNABORTED) {
245 ret = call->app_errno;
246 goto out_unwait;
247 }
248 goto abort;
249 }
250
251 /* unmarshall the reply */
252 vinfo->vid = ntohl(*bp++);
253 vinfo->type = ntohl(*bp++);
254
255 vinfo->type_vids[0] = ntohl(*bp++);
256 vinfo->type_vids[1] = ntohl(*bp++);
257 vinfo->type_vids[2] = ntohl(*bp++);
258 vinfo->type_vids[3] = ntohl(*bp++);
259 vinfo->type_vids[4] = ntohl(*bp++);
260
261 vinfo->nservers = ntohl(*bp++);
262 vinfo->servers[0].addr.s_addr = *bp++;
263 vinfo->servers[1].addr.s_addr = *bp++;
264 vinfo->servers[2].addr.s_addr = *bp++;
265 vinfo->servers[3].addr.s_addr = *bp++;
266 vinfo->servers[4].addr.s_addr = *bp++;
267 vinfo->servers[5].addr.s_addr = *bp++;
268 vinfo->servers[6].addr.s_addr = *bp++;
269 vinfo->servers[7].addr.s_addr = *bp++;
270
271 ret = -EBADMSG;
272 if (vinfo->nservers > 8)
273 goto abort;
274
275 /* success */
276 ret = 0;
277
278 out_unwait:
279 set_current_state(TASK_RUNNING);
280 remove_wait_queue(&call->waitq, &myself);
281 rxrpc_put_call(call);
282 out_put_conn:
283 afs_server_release_fsconn(server, conn);
284 out:
285 _leave("");
286 return ret;
287
288 abort:
289 set_current_state(TASK_UNINTERRUPTIBLE);
290 rxrpc_call_abort(call, ret);
291 schedule();
292 goto out_unwait;
293
294} /* end afs_rxfs_get_volume_info() */
295#endif
296
297/*****************************************************************************/
298/*
299 * fetch the status information for a file
300 */
301int afs_rxfs_fetch_file_status(struct afs_server *server,
302 struct afs_vnode *vnode,
303 struct afs_volsync *volsync)
304{
305 struct afs_server_callslot callslot;
306 struct rxrpc_call *call;
307 struct kvec piov[1];
308 size_t sent;
309 int ret;
310 __be32 *bp;
311
312 DECLARE_WAITQUEUE(myself, current);
313
314 _enter("%p,{%u,%u,%u}",
315 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
316
317 /* get hold of the fileserver connection */
318 ret = afs_server_request_callslot(server, &callslot);
319 if (ret < 0)
320 goto out;
321
322 /* create a call through that connection */
323 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap,
324 &call);
325 if (ret < 0) {
326 printk("kAFS: Unable to create call: %d\n", ret);
327 goto out_put_conn;
328 }
329 call->app_opcode = FSFETCHSTATUS;
330
331 /* we want to get event notifications from the call */
332 add_wait_queue(&call->waitq, &myself);
333
334 /* marshall the parameters */
335 bp = rxrpc_call_alloc_scratch(call, 16);
336 bp[0] = htonl(FSFETCHSTATUS);
337 bp[1] = htonl(vnode->fid.vid);
338 bp[2] = htonl(vnode->fid.vnode);
339 bp[3] = htonl(vnode->fid.unique);
340
341 piov[0].iov_len = 16;
342 piov[0].iov_base = bp;
343
344 /* send the parameters to the server */
345 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
346 0, &sent);
347 if (ret < 0)
348 goto abort;
349
350 /* wait for the reply to completely arrive */
351 bp = rxrpc_call_alloc_scratch(call, 120);
352
353 ret = rxrpc_call_read_data(call, bp, 120,
354 RXRPC_CALL_READ_BLOCK |
355 RXRPC_CALL_READ_ALL);
356 if (ret < 0) {
357 if (ret == -ECONNABORTED) {
358 ret = call->app_errno;
359 goto out_unwait;
360 }
361 goto abort;
362 }
363
364 /* unmarshall the reply */
365 vnode->status.if_version = ntohl(*bp++);
366 vnode->status.type = ntohl(*bp++);
367 vnode->status.nlink = ntohl(*bp++);
368 vnode->status.size = ntohl(*bp++);
369 vnode->status.version = ntohl(*bp++);
370 vnode->status.author = ntohl(*bp++);
371 vnode->status.owner = ntohl(*bp++);
372 vnode->status.caller_access = ntohl(*bp++);
373 vnode->status.anon_access = ntohl(*bp++);
374 vnode->status.mode = ntohl(*bp++);
375 vnode->status.parent.vid = vnode->fid.vid;
376 vnode->status.parent.vnode = ntohl(*bp++);
377 vnode->status.parent.unique = ntohl(*bp++);
378 bp++; /* seg size */
379 vnode->status.mtime_client = ntohl(*bp++);
380 vnode->status.mtime_server = ntohl(*bp++);
381 bp++; /* group */
382 bp++; /* sync counter */
383 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
384 bp++; /* spare2 */
385 bp++; /* spare3 */
386 bp++; /* spare4 */
387
388 vnode->cb_version = ntohl(*bp++);
389 vnode->cb_expiry = ntohl(*bp++);
390 vnode->cb_type = ntohl(*bp++);
391
392 if (volsync) {
393 volsync->creation = ntohl(*bp++);
394 bp++; /* spare2 */
395 bp++; /* spare3 */
396 bp++; /* spare4 */
397 bp++; /* spare5 */
398 bp++; /* spare6 */
399 }
400
401 /* success */
402 ret = 0;
403
404 out_unwait:
405 set_current_state(TASK_RUNNING);
406 remove_wait_queue(&call->waitq, &myself);
407 rxrpc_put_call(call);
408 out_put_conn:
409 afs_server_release_callslot(server, &callslot);
410 out:
411 _leave("");
412 return ret;
413
414 abort:
415 set_current_state(TASK_UNINTERRUPTIBLE);
416 rxrpc_call_abort(call, ret);
417 schedule();
418 goto out_unwait;
419} /* end afs_rxfs_fetch_file_status() */
420
421/*****************************************************************************/
422/*
423 * fetch the contents of a file or directory
424 */
425int afs_rxfs_fetch_file_data(struct afs_server *server,
426 struct afs_vnode *vnode,
427 struct afs_rxfs_fetch_descriptor *desc,
428 struct afs_volsync *volsync)
429{
430 struct afs_server_callslot callslot;
431 struct rxrpc_call *call;
432 struct kvec piov[1];
433 size_t sent;
434 int ret;
435 __be32 *bp;
436
437 DECLARE_WAITQUEUE(myself, current);
438
439 _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}",
440 server,
441 desc->fid.vid,
442 desc->fid.vnode,
443 desc->fid.unique,
444 desc->size,
445 desc->offset);
446
447 /* get hold of the fileserver connection */
448 ret = afs_server_request_callslot(server, &callslot);
449 if (ret < 0)
450 goto out;
451
452 /* create a call through that connection */
453 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
454 if (ret < 0) {
455 printk("kAFS: Unable to create call: %d\n", ret);
456 goto out_put_conn;
457 }
458 call->app_opcode = FSFETCHDATA;
459
460 /* we want to get event notifications from the call */
461 add_wait_queue(&call->waitq, &myself);
462
463 /* marshall the parameters */
464 bp = rxrpc_call_alloc_scratch(call, 24);
465 bp[0] = htonl(FSFETCHDATA);
466 bp[1] = htonl(desc->fid.vid);
467 bp[2] = htonl(desc->fid.vnode);
468 bp[3] = htonl(desc->fid.unique);
469 bp[4] = htonl(desc->offset);
470 bp[5] = htonl(desc->size);
471
472 piov[0].iov_len = 24;
473 piov[0].iov_base = bp;
474
475 /* send the parameters to the server */
476 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
477 0, &sent);
478 if (ret < 0)
479 goto abort;
480
481 /* wait for the data count to arrive */
482 ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK);
483 if (ret < 0)
484 goto read_failed;
485
486 desc->actual = ntohl(bp[0]);
487 if (desc->actual != desc->size) {
488 ret = -EBADMSG;
489 goto abort;
490 }
491
492 /* call the app to read the actual data */
493 rxrpc_call_reset_scratch(call);
494
495 ret = rxrpc_call_read_data(call, desc->buffer, desc->actual,
496 RXRPC_CALL_READ_BLOCK);
497 if (ret < 0)
498 goto read_failed;
499
500 /* wait for the rest of the reply to completely arrive */
501 rxrpc_call_reset_scratch(call);
502 bp = rxrpc_call_alloc_scratch(call, 120);
503
504 ret = rxrpc_call_read_data(call, bp, 120,
505 RXRPC_CALL_READ_BLOCK |
506 RXRPC_CALL_READ_ALL);
507 if (ret < 0)
508 goto read_failed;
509
510 /* unmarshall the reply */
511 vnode->status.if_version = ntohl(*bp++);
512 vnode->status.type = ntohl(*bp++);
513 vnode->status.nlink = ntohl(*bp++);
514 vnode->status.size = ntohl(*bp++);
515 vnode->status.version = ntohl(*bp++);
516 vnode->status.author = ntohl(*bp++);
517 vnode->status.owner = ntohl(*bp++);
518 vnode->status.caller_access = ntohl(*bp++);
519 vnode->status.anon_access = ntohl(*bp++);
520 vnode->status.mode = ntohl(*bp++);
521 vnode->status.parent.vid = desc->fid.vid;
522 vnode->status.parent.vnode = ntohl(*bp++);
523 vnode->status.parent.unique = ntohl(*bp++);
524 bp++; /* seg size */
525 vnode->status.mtime_client = ntohl(*bp++);
526 vnode->status.mtime_server = ntohl(*bp++);
527 bp++; /* group */
528 bp++; /* sync counter */
529 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
530 bp++; /* spare2 */
531 bp++; /* spare3 */
532 bp++; /* spare4 */
533
534 vnode->cb_version = ntohl(*bp++);
535 vnode->cb_expiry = ntohl(*bp++);
536 vnode->cb_type = ntohl(*bp++);
537
538 if (volsync) {
539 volsync->creation = ntohl(*bp++);
540 bp++; /* spare2 */
541 bp++; /* spare3 */
542 bp++; /* spare4 */
543 bp++; /* spare5 */
544 bp++; /* spare6 */
545 }
546
547 /* success */
548 ret = 0;
549
550 out_unwait:
551 set_current_state(TASK_RUNNING);
552 remove_wait_queue(&call->waitq,&myself);
553 rxrpc_put_call(call);
554 out_put_conn:
555 afs_server_release_callslot(server, &callslot);
556 out:
557 _leave(" = %d", ret);
558 return ret;
559
560 read_failed:
561 if (ret == -ECONNABORTED) {
562 ret = call->app_errno;
563 goto out_unwait;
564 }
565
566 abort:
567 set_current_state(TASK_UNINTERRUPTIBLE);
568 rxrpc_call_abort(call, ret);
569 schedule();
570 goto out_unwait;
571
572} /* end afs_rxfs_fetch_file_data() */
573
574/*****************************************************************************/
575/*
576 * ask the AFS fileserver to discard a callback request on a file
577 */
578int afs_rxfs_give_up_callback(struct afs_server *server,
579 struct afs_vnode *vnode)
580{
581 struct afs_server_callslot callslot;
582 struct rxrpc_call *call;
583 struct kvec piov[1];
584 size_t sent;
585 int ret;
586 __be32 *bp;
587
588 DECLARE_WAITQUEUE(myself, current);
589
590 _enter("%p,{%u,%u,%u}",
591 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
592
593 /* get hold of the fileserver connection */
594 ret = afs_server_request_callslot(server, &callslot);
595 if (ret < 0)
596 goto out;
597
598 /* create a call through that connection */
599 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
600 if (ret < 0) {
601 printk("kAFS: Unable to create call: %d\n", ret);
602 goto out_put_conn;
603 }
604 call->app_opcode = FSGIVEUPCALLBACKS;
605
606 /* we want to get event notifications from the call */
607 add_wait_queue(&call->waitq, &myself);
608
609 /* marshall the parameters */
610 bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4);
611
612 piov[0].iov_len = (1 + 4 + 4) * 4;
613 piov[0].iov_base = bp;
614
615 *bp++ = htonl(FSGIVEUPCALLBACKS);
616 *bp++ = htonl(1);
617 *bp++ = htonl(vnode->fid.vid);
618 *bp++ = htonl(vnode->fid.vnode);
619 *bp++ = htonl(vnode->fid.unique);
620 *bp++ = htonl(1);
621 *bp++ = htonl(vnode->cb_version);
622 *bp++ = htonl(vnode->cb_expiry);
623 *bp++ = htonl(vnode->cb_type);
624
625 /* send the parameters to the server */
626 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
627 0, &sent);
628 if (ret < 0)
629 goto abort;
630
631 /* wait for the reply to completely arrive */
632 for (;;) {
633 set_current_state(TASK_INTERRUPTIBLE);
634 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
635 signal_pending(current))
636 break;
637 schedule();
638 }
639 set_current_state(TASK_RUNNING);
640
641 ret = -EINTR;
642 if (signal_pending(current))
643 goto abort;
644
645 switch (call->app_call_state) {
646 case RXRPC_CSTATE_ERROR:
647 ret = call->app_errno;
648 goto out_unwait;
649
650 case RXRPC_CSTATE_CLNT_GOT_REPLY:
651 ret = 0;
652 goto out_unwait;
653
654 default:
655 BUG();
656 }
657
658 out_unwait:
659 set_current_state(TASK_RUNNING);
660 remove_wait_queue(&call->waitq, &myself);
661 rxrpc_put_call(call);
662 out_put_conn:
663 afs_server_release_callslot(server, &callslot);
664 out:
665 _leave("");
666 return ret;
667
668 abort:
669 set_current_state(TASK_UNINTERRUPTIBLE);
670 rxrpc_call_abort(call, ret);
671 schedule();
672 goto out_unwait;
673} /* end afs_rxfs_give_up_callback() */
674
675/*****************************************************************************/
676/*
677 * look a filename up in a directory
678 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
679 */
680#if 0
681int afs_rxfs_lookup(struct afs_server *server,
682 struct afs_vnode *dir,
683 const char *filename,
684 struct afs_vnode *vnode,
685 struct afs_volsync *volsync)
686{
687 struct rxrpc_connection *conn;
688 struct rxrpc_call *call;
689 struct kvec piov[3];
690 size_t sent;
691 int ret;
692 u32 *bp, zero;
693
694 DECLARE_WAITQUEUE(myself, current);
695
696 kenter("%p,{%u,%u,%u},%s",
697 server, fid->vid, fid->vnode, fid->unique, filename);
698
699 /* get hold of the fileserver connection */
700 ret = afs_server_get_fsconn(server, &conn);
701 if (ret < 0)
702 goto out;
703
704 /* create a call through that connection */
705 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
706 if (ret < 0) {
707 printk("kAFS: Unable to create call: %d\n", ret);
708 goto out_put_conn;
709 }
710 call->app_opcode = FSLOOKUP;
711
712 /* we want to get event notifications from the call */
713 add_wait_queue(&call->waitq,&myself);
714
715 /* marshall the parameters */
716 bp = rxrpc_call_alloc_scratch(call, 20);
717
718 zero = 0;
719
720 piov[0].iov_len = 20;
721 piov[0].iov_base = bp;
722 piov[1].iov_len = strlen(filename);
723 piov[1].iov_base = (char *) filename;
724 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
725 piov[2].iov_base = &zero;
726
727 *bp++ = htonl(FSLOOKUP);
728 *bp++ = htonl(dirfid->vid);
729 *bp++ = htonl(dirfid->vnode);
730 *bp++ = htonl(dirfid->unique);
731 *bp++ = htonl(piov[1].iov_len);
732
733 /* send the parameters to the server */
734 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
735 0, &sent);
736 if (ret < 0)
737 goto abort;
738
739 /* wait for the reply to completely arrive */
740 bp = rxrpc_call_alloc_scratch(call, 220);
741
742 ret = rxrpc_call_read_data(call, bp, 220,
743 RXRPC_CALL_READ_BLOCK |
744 RXRPC_CALL_READ_ALL);
745 if (ret < 0) {
746 if (ret == -ECONNABORTED) {
747 ret = call->app_errno;
748 goto out_unwait;
749 }
750 goto abort;
751 }
752
753 /* unmarshall the reply */
754 fid->vid = ntohl(*bp++);
755 fid->vnode = ntohl(*bp++);
756 fid->unique = ntohl(*bp++);
757
758 vnode->status.if_version = ntohl(*bp++);
759 vnode->status.type = ntohl(*bp++);
760 vnode->status.nlink = ntohl(*bp++);
761 vnode->status.size = ntohl(*bp++);
762 vnode->status.version = ntohl(*bp++);
763 vnode->status.author = ntohl(*bp++);
764 vnode->status.owner = ntohl(*bp++);
765 vnode->status.caller_access = ntohl(*bp++);
766 vnode->status.anon_access = ntohl(*bp++);
767 vnode->status.mode = ntohl(*bp++);
768 vnode->status.parent.vid = dirfid->vid;
769 vnode->status.parent.vnode = ntohl(*bp++);
770 vnode->status.parent.unique = ntohl(*bp++);
771 bp++; /* seg size */
772 vnode->status.mtime_client = ntohl(*bp++);
773 vnode->status.mtime_server = ntohl(*bp++);
774 bp++; /* group */
775 bp++; /* sync counter */
776 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
777 bp++; /* spare2 */
778 bp++; /* spare3 */
779 bp++; /* spare4 */
780
781 dir->status.if_version = ntohl(*bp++);
782 dir->status.type = ntohl(*bp++);
783 dir->status.nlink = ntohl(*bp++);
784 dir->status.size = ntohl(*bp++);
785 dir->status.version = ntohl(*bp++);
786 dir->status.author = ntohl(*bp++);
787 dir->status.owner = ntohl(*bp++);
788 dir->status.caller_access = ntohl(*bp++);
789 dir->status.anon_access = ntohl(*bp++);
790 dir->status.mode = ntohl(*bp++);
791 dir->status.parent.vid = dirfid->vid;
792 dir->status.parent.vnode = ntohl(*bp++);
793 dir->status.parent.unique = ntohl(*bp++);
794 bp++; /* seg size */
795 dir->status.mtime_client = ntohl(*bp++);
796 dir->status.mtime_server = ntohl(*bp++);
797 bp++; /* group */
798 bp++; /* sync counter */
799 dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
800 bp++; /* spare2 */
801 bp++; /* spare3 */
802 bp++; /* spare4 */
803
804 callback->fid = *fid;
805 callback->version = ntohl(*bp++);
806 callback->expiry = ntohl(*bp++);
807 callback->type = ntohl(*bp++);
808
809 if (volsync) {
810 volsync->creation = ntohl(*bp++);
811 bp++; /* spare2 */
812 bp++; /* spare3 */
813 bp++; /* spare4 */
814 bp++; /* spare5 */
815 bp++; /* spare6 */
816 }
817
818 /* success */
819 ret = 0;
820
821 out_unwait:
822 set_current_state(TASK_RUNNING);
823 remove_wait_queue(&call->waitq, &myself);
824 rxrpc_put_call(call);
825 out_put_conn:
826 afs_server_release_fsconn(server, conn);
827 out:
828 kleave("");
829 return ret;
830
831 abort:
832 set_current_state(TASK_UNINTERRUPTIBLE);
833 rxrpc_call_abort(call, ret);
834 schedule();
835 goto out_unwait;
836} /* end afs_rxfs_lookup() */
837#endif