Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.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 /*
34  * map afs abort codes to/from Linux error codes
35  * - called with call->lock held
36  */
37 static 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
57 int 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
186 int 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  */
301 int 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         _debug("Data Version %llx\n", vnode->status.version);
402
403         /* success */
404         ret = 0;
405
406  out_unwait:
407         set_current_state(TASK_RUNNING);
408         remove_wait_queue(&call->waitq, &myself);
409         rxrpc_put_call(call);
410  out_put_conn:
411         afs_server_release_callslot(server, &callslot);
412  out:
413         _leave(" = %d", ret);
414         return ret;
415
416  abort:
417         set_current_state(TASK_UNINTERRUPTIBLE);
418         rxrpc_call_abort(call, ret);
419         schedule();
420         goto out_unwait;
421 } /* end afs_rxfs_fetch_file_status() */
422
423 /*****************************************************************************/
424 /*
425  * fetch the contents of a file or directory
426  */
427 int afs_rxfs_fetch_file_data(struct afs_server *server,
428                              struct afs_vnode *vnode,
429                              struct afs_rxfs_fetch_descriptor *desc,
430                              struct afs_volsync *volsync)
431 {
432         struct afs_server_callslot callslot;
433         struct rxrpc_call *call;
434         struct kvec piov[1];
435         size_t sent;
436         int ret;
437         __be32 *bp;
438
439         DECLARE_WAITQUEUE(myself, current);
440
441         _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}",
442                server,
443                desc->fid.vid,
444                desc->fid.vnode,
445                desc->fid.unique,
446                desc->size,
447                desc->offset);
448
449         /* get hold of the fileserver connection */
450         ret = afs_server_request_callslot(server, &callslot);
451         if (ret < 0)
452                 goto out;
453
454         /* create a call through that connection */
455         ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
456         if (ret < 0) {
457                 printk("kAFS: Unable to create call: %d\n", ret);
458                 goto out_put_conn;
459         }
460         call->app_opcode = FSFETCHDATA;
461
462         /* we want to get event notifications from the call */
463         add_wait_queue(&call->waitq, &myself);
464
465         /* marshall the parameters */
466         bp = rxrpc_call_alloc_scratch(call, 24);
467         bp[0] = htonl(FSFETCHDATA);
468         bp[1] = htonl(desc->fid.vid);
469         bp[2] = htonl(desc->fid.vnode);
470         bp[3] = htonl(desc->fid.unique);
471         bp[4] = htonl(desc->offset);
472         bp[5] = htonl(desc->size);
473
474         piov[0].iov_len = 24;
475         piov[0].iov_base = bp;
476
477         /* send the parameters to the server */
478         ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
479                                     0, &sent);
480         if (ret < 0)
481                 goto abort;
482
483         /* wait for the data count to arrive */
484         ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK);
485         if (ret < 0)
486                 goto read_failed;
487
488         desc->actual = ntohl(bp[0]);
489         if (desc->actual != desc->size) {
490                 ret = -EBADMSG;
491                 goto abort;
492         }
493
494         /* call the app to read the actual data */
495         rxrpc_call_reset_scratch(call);
496
497         ret = rxrpc_call_read_data(call, desc->buffer, desc->actual,
498                                    RXRPC_CALL_READ_BLOCK);
499         if (ret < 0)
500                 goto read_failed;
501
502         /* wait for the rest of the reply to completely arrive */
503         rxrpc_call_reset_scratch(call);
504         bp = rxrpc_call_alloc_scratch(call, 120);
505
506         ret = rxrpc_call_read_data(call, bp, 120,
507                                    RXRPC_CALL_READ_BLOCK |
508                                    RXRPC_CALL_READ_ALL);
509         if (ret < 0)
510                 goto read_failed;
511
512         /* unmarshall the reply */
513         vnode->status.if_version        = ntohl(*bp++);
514         vnode->status.type              = ntohl(*bp++);
515         vnode->status.nlink             = ntohl(*bp++);
516         vnode->status.size              = ntohl(*bp++);
517         vnode->status.version           = ntohl(*bp++);
518         vnode->status.author            = ntohl(*bp++);
519         vnode->status.owner             = ntohl(*bp++);
520         vnode->status.caller_access     = ntohl(*bp++);
521         vnode->status.anon_access       = ntohl(*bp++);
522         vnode->status.mode              = ntohl(*bp++);
523         vnode->status.parent.vid        = desc->fid.vid;
524         vnode->status.parent.vnode      = ntohl(*bp++);
525         vnode->status.parent.unique     = ntohl(*bp++);
526         bp++; /* seg size */
527         vnode->status.mtime_client      = ntohl(*bp++);
528         vnode->status.mtime_server      = ntohl(*bp++);
529         bp++; /* group */
530         bp++; /* sync counter */
531         vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
532         bp++; /* spare2 */
533         bp++; /* spare3 */
534         bp++; /* spare4 */
535
536         vnode->cb_version               = ntohl(*bp++);
537         vnode->cb_expiry                = ntohl(*bp++);
538         vnode->cb_type                  = ntohl(*bp++);
539
540         if (volsync) {
541                 volsync->creation       = ntohl(*bp++);
542                 bp++; /* spare2 */
543                 bp++; /* spare3 */
544                 bp++; /* spare4 */
545                 bp++; /* spare5 */
546                 bp++; /* spare6 */
547         }
548
549         /* success */
550         ret = 0;
551
552  out_unwait:
553         set_current_state(TASK_RUNNING);
554         remove_wait_queue(&call->waitq,&myself);
555         rxrpc_put_call(call);
556  out_put_conn:
557         afs_server_release_callslot(server, &callslot);
558  out:
559         _leave(" = %d", ret);
560         return ret;
561
562  read_failed:
563         if (ret == -ECONNABORTED) {
564                 ret = call->app_errno;
565                 goto out_unwait;
566         }
567
568  abort:
569         set_current_state(TASK_UNINTERRUPTIBLE);
570         rxrpc_call_abort(call, ret);
571         schedule();
572         goto out_unwait;
573
574 } /* end afs_rxfs_fetch_file_data() */
575
576 /*****************************************************************************/
577 /*
578  * ask the AFS fileserver to discard a callback request on a file
579  */
580 int afs_rxfs_give_up_callback(struct afs_server *server,
581                               struct afs_vnode *vnode)
582 {
583         struct afs_server_callslot callslot;
584         struct rxrpc_call *call;
585         struct kvec piov[1];
586         size_t sent;
587         int ret;
588         __be32 *bp;
589
590         DECLARE_WAITQUEUE(myself, current);
591
592         _enter("%p,{%u,%u,%u}",
593                server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
594
595         /* get hold of the fileserver connection */
596         ret = afs_server_request_callslot(server, &callslot);
597         if (ret < 0)
598                 goto out;
599
600         /* create a call through that connection */
601         ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
602         if (ret < 0) {
603                 printk("kAFS: Unable to create call: %d\n", ret);
604                 goto out_put_conn;
605         }
606         call->app_opcode = FSGIVEUPCALLBACKS;
607
608         /* we want to get event notifications from the call */
609         add_wait_queue(&call->waitq, &myself);
610
611         /* marshall the parameters */
612         bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4);
613
614         piov[0].iov_len = (1 + 4 + 4) * 4;
615         piov[0].iov_base = bp;
616
617         *bp++ = htonl(FSGIVEUPCALLBACKS);
618         *bp++ = htonl(1);
619         *bp++ = htonl(vnode->fid.vid);
620         *bp++ = htonl(vnode->fid.vnode);
621         *bp++ = htonl(vnode->fid.unique);
622         *bp++ = htonl(1);
623         *bp++ = htonl(vnode->cb_version);
624         *bp++ = htonl(vnode->cb_expiry);
625         *bp++ = htonl(vnode->cb_type);
626
627         /* send the parameters to the server */
628         ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
629                                     0, &sent);
630         if (ret < 0)
631                 goto abort;
632
633         /* wait for the reply to completely arrive */
634         for (;;) {
635                 set_current_state(TASK_INTERRUPTIBLE);
636                 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
637                     signal_pending(current))
638                         break;
639                 schedule();
640         }
641         set_current_state(TASK_RUNNING);
642
643         ret = -EINTR;
644         if (signal_pending(current))
645                 goto abort;
646
647         switch (call->app_call_state) {
648         case RXRPC_CSTATE_ERROR:
649                 ret = call->app_errno;
650                 goto out_unwait;
651
652         case RXRPC_CSTATE_CLNT_GOT_REPLY:
653                 ret = 0;
654                 goto out_unwait;
655
656         default:
657                 BUG();
658         }
659
660  out_unwait:
661         set_current_state(TASK_RUNNING);
662         remove_wait_queue(&call->waitq, &myself);
663         rxrpc_put_call(call);
664  out_put_conn:
665         afs_server_release_callslot(server, &callslot);
666  out:
667         _leave("");
668         return ret;
669
670  abort:
671         set_current_state(TASK_UNINTERRUPTIBLE);
672         rxrpc_call_abort(call, ret);
673         schedule();
674         goto out_unwait;
675 } /* end afs_rxfs_give_up_callback() */
676
677 /*****************************************************************************/
678 /*
679  * look a filename up in a directory
680  * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
681  */
682 #if 0
683 int afs_rxfs_lookup(struct afs_server *server,
684                     struct afs_vnode *dir,
685                     const char *filename,
686                     struct afs_vnode *vnode,
687                     struct afs_volsync *volsync)
688 {
689         struct rxrpc_connection *conn;
690         struct rxrpc_call *call;
691         struct kvec piov[3];
692         size_t sent;
693         int ret;
694         u32 *bp, zero;
695
696         DECLARE_WAITQUEUE(myself, current);
697
698         kenter("%p,{%u,%u,%u},%s",
699                server, fid->vid, fid->vnode, fid->unique, filename);
700
701         /* get hold of the fileserver connection */
702         ret = afs_server_get_fsconn(server, &conn);
703         if (ret < 0)
704                 goto out;
705
706         /* create a call through that connection */
707         ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
708         if (ret < 0) {
709                 printk("kAFS: Unable to create call: %d\n", ret);
710                 goto out_put_conn;
711         }
712         call->app_opcode = FSLOOKUP;
713
714         /* we want to get event notifications from the call */
715         add_wait_queue(&call->waitq,&myself);
716
717         /* marshall the parameters */
718         bp = rxrpc_call_alloc_scratch(call, 20);
719
720         zero = 0;
721
722         piov[0].iov_len = 20;
723         piov[0].iov_base = bp;
724         piov[1].iov_len = strlen(filename);
725         piov[1].iov_base = (char *) filename;
726         piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
727         piov[2].iov_base = &zero;
728
729         *bp++ = htonl(FSLOOKUP);
730         *bp++ = htonl(dirfid->vid);
731         *bp++ = htonl(dirfid->vnode);
732         *bp++ = htonl(dirfid->unique);
733         *bp++ = htonl(piov[1].iov_len);
734
735         /* send the parameters to the server */
736         ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
737                                     0, &sent);
738         if (ret < 0)
739                 goto abort;
740
741         /* wait for the reply to completely arrive */
742         bp = rxrpc_call_alloc_scratch(call, 220);
743
744         ret = rxrpc_call_read_data(call, bp, 220,
745                                    RXRPC_CALL_READ_BLOCK |
746                                    RXRPC_CALL_READ_ALL);
747         if (ret < 0) {
748                 if (ret == -ECONNABORTED) {
749                         ret = call->app_errno;
750                         goto out_unwait;
751                 }
752                 goto abort;
753         }
754
755         /* unmarshall the reply */
756         fid->vid                = ntohl(*bp++);
757         fid->vnode              = ntohl(*bp++);
758         fid->unique             = ntohl(*bp++);
759
760         vnode->status.if_version        = ntohl(*bp++);
761         vnode->status.type              = ntohl(*bp++);
762         vnode->status.nlink             = ntohl(*bp++);
763         vnode->status.size              = ntohl(*bp++);
764         vnode->status.version           = ntohl(*bp++);
765         vnode->status.author            = ntohl(*bp++);
766         vnode->status.owner             = ntohl(*bp++);
767         vnode->status.caller_access     = ntohl(*bp++);
768         vnode->status.anon_access       = ntohl(*bp++);
769         vnode->status.mode              = ntohl(*bp++);
770         vnode->status.parent.vid        = dirfid->vid;
771         vnode->status.parent.vnode      = ntohl(*bp++);
772         vnode->status.parent.unique     = ntohl(*bp++);
773         bp++; /* seg size */
774         vnode->status.mtime_client      = ntohl(*bp++);
775         vnode->status.mtime_server      = ntohl(*bp++);
776         bp++; /* group */
777         bp++; /* sync counter */
778         vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
779         bp++; /* spare2 */
780         bp++; /* spare3 */
781         bp++; /* spare4 */
782
783         dir->status.if_version          = ntohl(*bp++);
784         dir->status.type                = ntohl(*bp++);
785         dir->status.nlink               = ntohl(*bp++);
786         dir->status.size                = ntohl(*bp++);
787         dir->status.version             = ntohl(*bp++);
788         dir->status.author              = ntohl(*bp++);
789         dir->status.owner               = ntohl(*bp++);
790         dir->status.caller_access       = ntohl(*bp++);
791         dir->status.anon_access         = ntohl(*bp++);
792         dir->status.mode                = ntohl(*bp++);
793         dir->status.parent.vid          = dirfid->vid;
794         dir->status.parent.vnode        = ntohl(*bp++);
795         dir->status.parent.unique       = ntohl(*bp++);
796         bp++; /* seg size */
797         dir->status.mtime_client        = ntohl(*bp++);
798         dir->status.mtime_server        = ntohl(*bp++);
799         bp++; /* group */
800         bp++; /* sync counter */
801         dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
802         bp++; /* spare2 */
803         bp++; /* spare3 */
804         bp++; /* spare4 */
805
806         callback->fid           = *fid;
807         callback->version       = ntohl(*bp++);
808         callback->expiry        = ntohl(*bp++);
809         callback->type          = ntohl(*bp++);
810
811         if (volsync) {
812                 volsync->creation       = ntohl(*bp++);
813                 bp++; /* spare2 */
814                 bp++; /* spare3 */
815                 bp++; /* spare4 */
816                 bp++; /* spare5 */
817                 bp++; /* spare6 */
818         }
819
820         /* success */
821         ret = 0;
822
823  out_unwait:
824         set_current_state(TASK_RUNNING);
825         remove_wait_queue(&call->waitq, &myself);
826         rxrpc_put_call(call);
827  out_put_conn:
828         afs_server_release_fsconn(server, conn);
829  out:
830         kleave("");
831         return ret;
832
833  abort:
834         set_current_state(TASK_UNINTERRUPTIBLE);
835         rxrpc_call_abort(call, ret);
836         schedule();
837         goto out_unwait;
838 } /* end afs_rxfs_lookup() */
839 #endif