Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / 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         /* 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  */
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)
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  */
578 int 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
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)
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