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