MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / fs / afs / fsclient.c
blob61bc371532ab6d0f325d06d776fd7389047299e8
1 /* fsclient.c: AFS File Server client stubs
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
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"
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 */
32 /*****************************************************************************/
34 * map afs abort codes to/from Linux error codes
35 * - called with call->lock held
37 static void afs_rxfs_aemap(struct rxrpc_call *call)
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;
49 } /* end afs_rxfs_aemap() */
51 /*****************************************************************************/
53 * get the root volume name from a fileserver
54 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
56 #if 0
57 int afs_rxfs_get_root_volume(struct afs_server *server,
58 char *buf, size_t *buflen)
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];
67 DECLARE_WAITQUEUE(myself, current);
69 kenter("%p,%p,%u",server, buf, *buflen);
71 /* get hold of the fileserver connection */
72 ret = afs_server_get_fsconn(server, &conn);
73 if (ret < 0)
74 goto out;
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;
82 call->app_opcode = FSGETROOTVOLUME;
84 /* we want to get event notifications from the call */
85 add_wait_queue(&call->waitq, &myself);
87 /* marshall the parameters */
88 param[0] = htonl(FSGETROOTVOLUME);
90 piov[0].iov_len = sizeof(param);
91 piov[0].iov_base = param;
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;
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();
107 set_current_state(TASK_RUNNING);
109 ret = -EINTR;
110 if (signal_pending(current))
111 goto abort;
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;
119 case RXRPC_CSTATE_CLNT_GOT_REPLY:
120 /* read the reply */
121 kdebug("Got Reply: qty=%d", call->app_ready_qty);
123 ret = -EBADMSG;
124 if (call->app_ready_qty <= 4)
125 goto abort;
127 ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0);
128 if (ret < 0)
129 goto abort;
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;
138 entry->type = ntohl(*bp++);
139 entry->num_servers = ntohl(*bp++);
141 for (loop = 0; loop < 8; loop++)
142 entry->servers[loop].addr.s_addr = *bp++;
144 for (loop = 0; loop < 8; loop++)
145 entry->servers[loop].partition = ntohl(*bp++);
147 for (loop = 0; loop < 8; loop++)
148 entry->servers[loop].flags = ntohl(*bp++);
150 for (loop = 0; loop < 3; loop++)
151 entry->volume_ids[loop] = ntohl(*bp++);
153 entry->clone_id = ntohl(*bp++);
154 entry->flags = ntohl(*bp);
155 #endif
157 /* success */
158 ret = 0;
159 goto out_unwait;
161 default:
162 BUG();
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
181 /*****************************************************************************/
183 * get information about a volume
185 #if 0
186 int afs_rxfs_get_volume_info(struct afs_server *server,
187 const char *name,
188 struct afs_volume_info *vinfo)
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;
197 DECLARE_WAITQUEUE(myself, current);
199 _enter("%p,%s,%p", server, name, vinfo);
201 /* get hold of the fileserver connection */
202 ret = afs_server_get_fsconn(server, &conn);
203 if (ret < 0)
204 goto out;
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;
212 call->app_opcode = FSGETVOLUMEINFO;
214 /* we want to get event notifications from the call */
215 add_wait_queue(&call->waitq, &myself);
217 /* marshall the parameters */
218 piov[1].iov_len = strlen(name);
219 piov[1].iov_base = (char *) name;
221 zero = 0;
222 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
223 piov[2].iov_base = &zero;
225 param[0] = htonl(FSGETVOLUMEINFO);
226 param[1] = htonl(piov[1].iov_len);
228 piov[0].iov_len = sizeof(param);
229 piov[0].iov_base = param;
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;
237 /* wait for the reply to completely arrive */
238 bp = rxrpc_call_alloc_scratch(call, 64);
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;
248 goto abort;
251 /* unmarshall the reply */
252 vinfo->vid = ntohl(*bp++);
253 vinfo->type = ntohl(*bp++);
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++);
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++;
271 ret = -EBADMSG;
272 if (vinfo->nservers > 8)
273 goto abort;
275 /* success */
276 ret = 0;
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;
288 abort:
289 set_current_state(TASK_UNINTERRUPTIBLE);
290 rxrpc_call_abort(call, ret);
291 schedule();
292 goto out_unwait;
294 } /* end afs_rxfs_get_volume_info() */
295 #endif
297 /*****************************************************************************/
299 * fetch the status information for a file
301 int afs_rxfs_fetch_file_status(struct afs_server *server,
302 struct afs_vnode *vnode,
303 struct afs_volsync *volsync)
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;
312 DECLARE_WAITQUEUE(myself, current);
314 _enter("%p,{%u,%u,%u}",
315 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
317 /* get hold of the fileserver connection */
318 ret = afs_server_request_callslot(server, &callslot);
319 if (ret < 0)
320 goto out;
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;
329 call->app_opcode = FSFETCHSTATUS;
331 /* we want to get event notifications from the call */
332 add_wait_queue(&call->waitq, &myself);
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);
341 piov[0].iov_len = 16;
342 piov[0].iov_base = bp;
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;
350 /* wait for the reply to completely arrive */
351 bp = rxrpc_call_alloc_scratch(call, 120);
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;
361 goto abort;
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 */
388 vnode->cb_version = ntohl(*bp++);
389 vnode->cb_expiry = ntohl(*bp++);
390 vnode->cb_type = ntohl(*bp++);
392 if (volsync) {
393 volsync->creation = ntohl(*bp++);
394 bp++; /* spare2 */
395 bp++; /* spare3 */
396 bp++; /* spare4 */
397 bp++; /* spare5 */
398 bp++; /* spare6 */
401 /* success */
402 ret = 0;
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;
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() */
421 /*****************************************************************************/
423 * fetch the contents of a file or directory
425 int 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)
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;
437 DECLARE_WAITQUEUE(myself, current);
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);
447 /* get hold of the fileserver connection */
448 ret = afs_server_request_callslot(server, &callslot);
449 if (ret < 0)
450 goto out;
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;
458 call->app_opcode = FSFETCHDATA;
460 /* we want to get event notifications from the call */
461 add_wait_queue(&call->waitq, &myself);
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);
472 piov[0].iov_len = 24;
473 piov[0].iov_base = bp;
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;
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;
486 desc->actual = ntohl(bp[0]);
487 if (desc->actual != desc->size) {
488 ret = -EBADMSG;
489 goto abort;
492 /* call the app to read the actual data */
493 rxrpc_call_reset_scratch(call);
495 ret = rxrpc_call_read_data(call, desc->buffer, desc->actual,
496 RXRPC_CALL_READ_BLOCK);
497 if (ret < 0)
498 goto read_failed;
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);
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;
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 */
534 vnode->cb_version = ntohl(*bp++);
535 vnode->cb_expiry = ntohl(*bp++);
536 vnode->cb_type = ntohl(*bp++);
538 if (volsync) {
539 volsync->creation = ntohl(*bp++);
540 bp++; /* spare2 */
541 bp++; /* spare3 */
542 bp++; /* spare4 */
543 bp++; /* spare5 */
544 bp++; /* spare6 */
547 /* success */
548 ret = 0;
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;
560 read_failed:
561 if (ret == -ECONNABORTED) {
562 ret = call->app_errno;
563 goto out_unwait;
566 abort:
567 set_current_state(TASK_UNINTERRUPTIBLE);
568 rxrpc_call_abort(call, ret);
569 schedule();
570 goto out_unwait;
572 } /* end afs_rxfs_fetch_file_data() */
574 /*****************************************************************************/
576 * ask the AFS fileserver to discard a callback request on a file
578 int afs_rxfs_give_up_callback(struct afs_server *server,
579 struct afs_vnode *vnode)
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;
588 DECLARE_WAITQUEUE(myself, current);
590 _enter("%p,{%u,%u,%u}",
591 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
593 /* get hold of the fileserver connection */
594 ret = afs_server_request_callslot(server, &callslot);
595 if (ret < 0)
596 goto out;
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;
604 call->app_opcode = FSGIVEUPCALLBACKS;
606 /* we want to get event notifications from the call */
607 add_wait_queue(&call->waitq, &myself);
609 /* marshall the parameters */
610 bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4);
612 piov[0].iov_len = (1 + 4 + 4) * 4;
613 piov[0].iov_base = bp;
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);
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;
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();
639 set_current_state(TASK_RUNNING);
641 ret = -EINTR;
642 if (signal_pending(current))
643 goto abort;
645 switch (call->app_call_state) {
646 case RXRPC_CSTATE_ERROR:
647 ret = call->app_errno;
648 goto out_unwait;
650 case RXRPC_CSTATE_CLNT_GOT_REPLY:
651 ret = 0;
652 goto out_unwait;
654 default:
655 BUG();
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;
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() */
675 /*****************************************************************************/
677 * look a filename up in a directory
678 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
680 #if 0
681 int 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)
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;
694 DECLARE_WAITQUEUE(myself, current);
696 kenter("%p,{%u,%u,%u},%s",
697 server, fid->vid, fid->vnode, fid->unique, filename);
699 /* get hold of the fileserver connection */
700 ret = afs_server_get_fsconn(server, &conn);
701 if (ret < 0)
702 goto out;
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;
710 call->app_opcode = FSLOOKUP;
712 /* we want to get event notifications from the call */
713 add_wait_queue(&call->waitq,&myself);
715 /* marshall the parameters */
716 bp = rxrpc_call_alloc_scratch(call, 20);
718 zero = 0;
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;
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);
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;
739 /* wait for the reply to completely arrive */
740 bp = rxrpc_call_alloc_scratch(call, 220);
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;
750 goto abort;
753 /* unmarshall the reply */
754 fid->vid = ntohl(*bp++);
755 fid->vnode = ntohl(*bp++);
756 fid->unique = ntohl(*bp++);
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 */
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 */
804 callback->fid = *fid;
805 callback->version = ntohl(*bp++);
806 callback->expiry = ntohl(*bp++);
807 callback->type = ntohl(*bp++);
809 if (volsync) {
810 volsync->creation = ntohl(*bp++);
811 bp++; /* spare2 */
812 bp++; /* spare3 */
813 bp++; /* spare4 */
814 bp++; /* spare5 */
815 bp++; /* spare6 */
818 /* success */
819 ret = 0;
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;
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