[AF_RXRPC]: Add an interface to the AF_RXRPC module for the AFS filesystem to use
[deliverable/linux.git] / fs / afs / fsclient.c
CommitLineData
1da177e4
LT
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
1da177e4
LT
32/*
33 * map afs abort codes to/from Linux error codes
34 * - called with call->lock held
35 */
36static 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 }
ec26815a 48}
1da177e4 49
1da177e4
LT
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
55int 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
ec26815a 163abort:
1da177e4
LT
164 set_current_state(TASK_UNINTERRUPTIBLE);
165 rxrpc_call_abort(call, ret);
166 schedule();
ec26815a 167out_unwait:
1da177e4
LT
168 set_current_state(TASK_RUNNING);
169 remove_wait_queue(&call->waitq, &myself);
170 rxrpc_put_call(call);
ec26815a 171out_put_conn:
1da177e4 172 afs_server_release_fsconn(server, conn);
ec26815a 173out:
1da177e4
LT
174 kleave("");
175 return ret;
ec26815a 176}
1da177e4
LT
177#endif
178
1da177e4
LT
179/*
180 * get information about a volume
181 */
182#if 0
183int 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
ec26815a 275out_unwait:
1da177e4
LT
276 set_current_state(TASK_RUNNING);
277 remove_wait_queue(&call->waitq, &myself);
278 rxrpc_put_call(call);
ec26815a 279out_put_conn:
1da177e4 280 afs_server_release_fsconn(server, conn);
ec26815a 281out:
1da177e4
LT
282 _leave("");
283 return ret;
284
ec26815a 285abort:
1da177e4
LT
286 set_current_state(TASK_UNINTERRUPTIBLE);
287 rxrpc_call_abort(call, ret);
288 schedule();
289 goto out_unwait;
ec26815a 290}
1da177e4
LT
291#endif
292
1da177e4
LT
293/*
294 * fetch the status information for a file
295 */
296int 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
ec26815a 399out_unwait:
1da177e4
LT
400 set_current_state(TASK_RUNNING);
401 remove_wait_queue(&call->waitq, &myself);
402 rxrpc_put_call(call);
ec26815a 403out_put_conn:
1da177e4 404 afs_server_release_callslot(server, &callslot);
ec26815a 405out:
1da177e4
LT
406 _leave("");
407 return ret;
408
ec26815a 409abort:
1da177e4
LT
410 set_current_state(TASK_UNINTERRUPTIBLE);
411 rxrpc_call_abort(call, ret);
412 schedule();
413 goto out_unwait;
ec26815a 414}
1da177e4 415
1da177e4
LT
416/*
417 * fetch the contents of a file or directory
418 */
419int 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
ec26815a 544out_unwait:
1da177e4
LT
545 set_current_state(TASK_RUNNING);
546 remove_wait_queue(&call->waitq,&myself);
547 rxrpc_put_call(call);
ec26815a 548out_put_conn:
1da177e4 549 afs_server_release_callslot(server, &callslot);
ec26815a 550out:
1da177e4
LT
551 _leave(" = %d", ret);
552 return ret;
553
ec26815a 554read_failed:
1da177e4
LT
555 if (ret == -ECONNABORTED) {
556 ret = call->app_errno;
557 goto out_unwait;
558 }
559
ec26815a 560abort:
1da177e4
LT
561 set_current_state(TASK_UNINTERRUPTIBLE);
562 rxrpc_call_abort(call, ret);
563 schedule();
564 goto out_unwait;
ec26815a 565}
1da177e4 566
1da177e4
LT
567/*
568 * ask the AFS fileserver to discard a callback request on a file
569 */
570int 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
ec26815a 650out_unwait:
1da177e4
LT
651 set_current_state(TASK_RUNNING);
652 remove_wait_queue(&call->waitq, &myself);
653 rxrpc_put_call(call);
ec26815a 654out_put_conn:
1da177e4 655 afs_server_release_callslot(server, &callslot);
ec26815a 656out:
1da177e4
LT
657 _leave("");
658 return ret;
659
ec26815a 660abort:
1da177e4
LT
661 set_current_state(TASK_UNINTERRUPTIBLE);
662 rxrpc_call_abort(call, ret);
663 schedule();
664 goto out_unwait;
ec26815a 665}
1da177e4 666
1da177e4
LT
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
672int 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
ec26815a 812out_unwait:
1da177e4
LT
813 set_current_state(TASK_RUNNING);
814 remove_wait_queue(&call->waitq, &myself);
815 rxrpc_put_call(call);
ec26815a 816out_put_conn:
1da177e4 817 afs_server_release_fsconn(server, conn);
ec26815a 818out:
1da177e4
LT
819 kleave("");
820 return ret;
821
ec26815a 822abort:
1da177e4
LT
823 set_current_state(TASK_UNINTERRUPTIBLE);
824 rxrpc_call_abort(call, ret);
825 schedule();
826 goto out_unwait;
ec26815a 827}
1da177e4 828#endif
This page took 0.211921 seconds and 5 git commands to generate.