1 /* fsclient.c: AFS File Server client stubs
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/init.h>
13 #include <linux/sched.h>
14 #include <rxrpc/rxrpc.h>
15 #include <rxrpc/transport.h>
16 #include <rxrpc/connection.h>
17 #include <rxrpc/call.h>
19 #include "cmservice.h"
25 #define FSFETCHSTATUS 132 /* AFS Fetch file status */
26 #define FSFETCHDATA 130 /* AFS Fetch file data */
27 #define FSGIVEUPCALLBACKS 147 /* AFS Discard callback promises */
28 #define FSGETVOLUMEINFO 148 /* AFS Get root volume information */
29 #define FSGETROOTVOLUME 151 /* AFS Get root volume name */
30 #define FSLOOKUP 161 /* AFS lookup file in directory */
32 /*****************************************************************************/
34 * map afs abort codes to/from Linux error codes
35 * - called with call->lock held
37 static void afs_rxfs_aemap(struct rxrpc_call *call)
39 switch (call->app_err_state) {
40 case RXRPC_ESTATE_LOCAL_ABORT:
41 call->app_abort_code = -call->app_errno;
43 case RXRPC_ESTATE_PEER_ABORT:
44 call->app_errno = afs_abort_to_error(call->app_abort_code);
49 } /* end afs_rxfs_aemap() */
51 /*****************************************************************************/
53 * get the root volume name from a fileserver
54 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
57 int afs_rxfs_get_root_volume(struct afs_server *server,
58 char *buf, size_t *buflen)
60 struct rxrpc_connection *conn;
61 struct rxrpc_call *call;
67 DECLARE_WAITQUEUE(myself, current);
69 kenter("%p,%p,%u",server, buf, *buflen);
71 /* get hold of the fileserver connection */
72 ret = afs_server_get_fsconn(server, &conn);
76 /* create a call through that connection */
77 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
79 printk("kAFS: Unable to create call: %d\n", ret);
82 call->app_opcode = FSGETROOTVOLUME;
84 /* we want to get event notifications from the call */
85 add_wait_queue(&call->waitq, &myself);
87 /* marshall the parameters */
88 param[0] = htonl(FSGETROOTVOLUME);
90 piov[0].iov_len = sizeof(param);
91 piov[0].iov_base = param;
93 /* send the parameters to the server */
94 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
99 /* wait for the reply to completely arrive */
101 set_current_state(TASK_INTERRUPTIBLE);
102 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
103 signal_pending(current))
107 set_current_state(TASK_RUNNING);
110 if (signal_pending(current))
113 switch (call->app_call_state) {
114 case RXRPC_CSTATE_ERROR:
115 ret = call->app_errno;
116 kdebug("Got Error: %d", ret);
119 case RXRPC_CSTATE_CLNT_GOT_REPLY:
121 kdebug("Got Reply: qty=%d", call->app_ready_qty);
124 if (call->app_ready_qty <= 4)
127 ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0);
132 /* unmarshall the reply */
134 for (loop = 0; loop < 65; loop++)
135 entry->name[loop] = ntohl(*bp++);
138 entry->type = ntohl(*bp++);
139 entry->num_servers = ntohl(*bp++);
141 for (loop = 0; loop < 8; loop++)
142 entry->servers[loop].addr.s_addr = *bp++;
144 for (loop = 0; loop < 8; loop++)
145 entry->servers[loop].partition = ntohl(*bp++);
147 for (loop = 0; loop < 8; loop++)
148 entry->servers[loop].flags = ntohl(*bp++);
150 for (loop = 0; loop < 3; loop++)
151 entry->volume_ids[loop] = ntohl(*bp++);
153 entry->clone_id = ntohl(*bp++);
154 entry->flags = ntohl(*bp);
166 set_current_state(TASK_UNINTERRUPTIBLE);
167 rxrpc_call_abort(call, ret);
170 set_current_state(TASK_RUNNING);
171 remove_wait_queue(&call->waitq, &myself);
172 rxrpc_put_call(call);
174 afs_server_release_fsconn(server, conn);
178 } /* end afs_rxfs_get_root_volume() */
181 /*****************************************************************************/
183 * get information about a volume
186 int afs_rxfs_get_volume_info(struct afs_server *server,
188 struct afs_volume_info *vinfo)
190 struct rxrpc_connection *conn;
191 struct rxrpc_call *call;
195 u32 param[2], *bp, zero;
197 DECLARE_WAITQUEUE(myself, current);
199 _enter("%p,%s,%p", server, name, vinfo);
201 /* get hold of the fileserver connection */
202 ret = afs_server_get_fsconn(server, &conn);
206 /* create a call through that connection */
207 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
209 printk("kAFS: Unable to create call: %d\n", ret);
212 call->app_opcode = FSGETVOLUMEINFO;
214 /* we want to get event notifications from the call */
215 add_wait_queue(&call->waitq, &myself);
217 /* marshall the parameters */
218 piov[1].iov_len = strlen(name);
219 piov[1].iov_base = (char *) name;
222 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
223 piov[2].iov_base = &zero;
225 param[0] = htonl(FSGETVOLUMEINFO);
226 param[1] = htonl(piov[1].iov_len);
228 piov[0].iov_len = sizeof(param);
229 piov[0].iov_base = param;
231 /* send the parameters to the server */
232 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
237 /* wait for the reply to completely arrive */
238 bp = rxrpc_call_alloc_scratch(call, 64);
240 ret = rxrpc_call_read_data(call, bp, 64,
241 RXRPC_CALL_READ_BLOCK |
242 RXRPC_CALL_READ_ALL);
244 if (ret == -ECONNABORTED) {
245 ret = call->app_errno;
251 /* unmarshall the reply */
252 vinfo->vid = ntohl(*bp++);
253 vinfo->type = ntohl(*bp++);
255 vinfo->type_vids[0] = ntohl(*bp++);
256 vinfo->type_vids[1] = ntohl(*bp++);
257 vinfo->type_vids[2] = ntohl(*bp++);
258 vinfo->type_vids[3] = ntohl(*bp++);
259 vinfo->type_vids[4] = ntohl(*bp++);
261 vinfo->nservers = ntohl(*bp++);
262 vinfo->servers[0].addr.s_addr = *bp++;
263 vinfo->servers[1].addr.s_addr = *bp++;
264 vinfo->servers[2].addr.s_addr = *bp++;
265 vinfo->servers[3].addr.s_addr = *bp++;
266 vinfo->servers[4].addr.s_addr = *bp++;
267 vinfo->servers[5].addr.s_addr = *bp++;
268 vinfo->servers[6].addr.s_addr = *bp++;
269 vinfo->servers[7].addr.s_addr = *bp++;
272 if (vinfo->nservers > 8)
279 set_current_state(TASK_RUNNING);
280 remove_wait_queue(&call->waitq, &myself);
281 rxrpc_put_call(call);
283 afs_server_release_fsconn(server, conn);
289 set_current_state(TASK_UNINTERRUPTIBLE);
290 rxrpc_call_abort(call, ret);
294 } /* end afs_rxfs_get_volume_info() */
297 /*****************************************************************************/
299 * fetch the status information for a file
301 int afs_rxfs_fetch_file_status(struct afs_server *server,
302 struct afs_vnode *vnode,
303 struct afs_volsync *volsync)
305 struct afs_server_callslot callslot;
306 struct rxrpc_call *call;
312 DECLARE_WAITQUEUE(myself, current);
314 _enter("%p,{%u,%u,%u}",
315 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
317 /* get hold of the fileserver connection */
318 ret = afs_server_request_callslot(server, &callslot);
322 /* create a call through that connection */
323 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap,
326 printk("kAFS: Unable to create call: %d\n", ret);
329 call->app_opcode = FSFETCHSTATUS;
331 /* we want to get event notifications from the call */
332 add_wait_queue(&call->waitq, &myself);
334 /* marshall the parameters */
335 bp = rxrpc_call_alloc_scratch(call, 16);
336 bp[0] = htonl(FSFETCHSTATUS);
337 bp[1] = htonl(vnode->fid.vid);
338 bp[2] = htonl(vnode->fid.vnode);
339 bp[3] = htonl(vnode->fid.unique);
341 piov[0].iov_len = 16;
342 piov[0].iov_base = bp;
344 /* send the parameters to the server */
345 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
350 /* wait for the reply to completely arrive */
351 bp = rxrpc_call_alloc_scratch(call, 120);
353 ret = rxrpc_call_read_data(call, bp, 120,
354 RXRPC_CALL_READ_BLOCK |
355 RXRPC_CALL_READ_ALL);
357 if (ret == -ECONNABORTED) {
358 ret = call->app_errno;
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++);
379 vnode->status.mtime_client = ntohl(*bp++);
380 vnode->status.mtime_server = ntohl(*bp++);
382 bp++; /* sync counter */
383 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
388 vnode->cb_version = ntohl(*bp++);
389 vnode->cb_expiry = ntohl(*bp++);
390 vnode->cb_type = ntohl(*bp++);
393 volsync->creation = ntohl(*bp++);
405 set_current_state(TASK_RUNNING);
406 remove_wait_queue(&call->waitq, &myself);
407 rxrpc_put_call(call);
409 afs_server_release_callslot(server, &callslot);
415 set_current_state(TASK_UNINTERRUPTIBLE);
416 rxrpc_call_abort(call, ret);
419 } /* end afs_rxfs_fetch_file_status() */
421 /*****************************************************************************/
423 * fetch the contents of a file or directory
425 int afs_rxfs_fetch_file_data(struct afs_server *server,
426 struct afs_vnode *vnode,
427 struct afs_rxfs_fetch_descriptor *desc,
428 struct afs_volsync *volsync)
430 struct afs_server_callslot callslot;
431 struct rxrpc_call *call;
437 DECLARE_WAITQUEUE(myself, current);
439 _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}",
447 /* get hold of the fileserver connection */
448 ret = afs_server_request_callslot(server, &callslot);
452 /* create a call through that connection */
453 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
455 printk("kAFS: Unable to create call: %d\n", ret);
458 call->app_opcode = FSFETCHDATA;
460 /* we want to get event notifications from the call */
461 add_wait_queue(&call->waitq, &myself);
463 /* marshall the parameters */
464 bp = rxrpc_call_alloc_scratch(call, 24);
465 bp[0] = htonl(FSFETCHDATA);
466 bp[1] = htonl(desc->fid.vid);
467 bp[2] = htonl(desc->fid.vnode);
468 bp[3] = htonl(desc->fid.unique);
469 bp[4] = htonl(desc->offset);
470 bp[5] = htonl(desc->size);
472 piov[0].iov_len = 24;
473 piov[0].iov_base = bp;
475 /* send the parameters to the server */
476 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
481 /* wait for the data count to arrive */
482 ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK);
486 desc->actual = ntohl(bp[0]);
487 if (desc->actual != desc->size) {
492 /* call the app to read the actual data */
493 rxrpc_call_reset_scratch(call);
495 ret = rxrpc_call_read_data(call, desc->buffer, desc->actual,
496 RXRPC_CALL_READ_BLOCK);
500 /* wait for the rest of the reply to completely arrive */
501 rxrpc_call_reset_scratch(call);
502 bp = rxrpc_call_alloc_scratch(call, 120);
504 ret = rxrpc_call_read_data(call, bp, 120,
505 RXRPC_CALL_READ_BLOCK |
506 RXRPC_CALL_READ_ALL);
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++);
525 vnode->status.mtime_client = ntohl(*bp++);
526 vnode->status.mtime_server = ntohl(*bp++);
528 bp++; /* sync counter */
529 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
534 vnode->cb_version = ntohl(*bp++);
535 vnode->cb_expiry = ntohl(*bp++);
536 vnode->cb_type = ntohl(*bp++);
539 volsync->creation = ntohl(*bp++);
551 set_current_state(TASK_RUNNING);
552 remove_wait_queue(&call->waitq,&myself);
553 rxrpc_put_call(call);
555 afs_server_release_callslot(server, &callslot);
557 _leave(" = %d", ret);
561 if (ret == -ECONNABORTED) {
562 ret = call->app_errno;
567 set_current_state(TASK_UNINTERRUPTIBLE);
568 rxrpc_call_abort(call, ret);
572 } /* end afs_rxfs_fetch_file_data() */
574 /*****************************************************************************/
576 * ask the AFS fileserver to discard a callback request on a file
578 int afs_rxfs_give_up_callback(struct afs_server *server,
579 struct afs_vnode *vnode)
581 struct afs_server_callslot callslot;
582 struct rxrpc_call *call;
588 DECLARE_WAITQUEUE(myself, current);
590 _enter("%p,{%u,%u,%u}",
591 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
593 /* get hold of the fileserver connection */
594 ret = afs_server_request_callslot(server, &callslot);
598 /* create a call through that connection */
599 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
601 printk("kAFS: Unable to create call: %d\n", ret);
604 call->app_opcode = FSGIVEUPCALLBACKS;
606 /* we want to get event notifications from the call */
607 add_wait_queue(&call->waitq, &myself);
609 /* marshall the parameters */
610 bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4);
612 piov[0].iov_len = (1 + 4 + 4) * 4;
613 piov[0].iov_base = bp;
615 *bp++ = htonl(FSGIVEUPCALLBACKS);
617 *bp++ = htonl(vnode->fid.vid);
618 *bp++ = htonl(vnode->fid.vnode);
619 *bp++ = htonl(vnode->fid.unique);
621 *bp++ = htonl(vnode->cb_version);
622 *bp++ = htonl(vnode->cb_expiry);
623 *bp++ = htonl(vnode->cb_type);
625 /* send the parameters to the server */
626 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
631 /* wait for the reply to completely arrive */
633 set_current_state(TASK_INTERRUPTIBLE);
634 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
635 signal_pending(current))
639 set_current_state(TASK_RUNNING);
642 if (signal_pending(current))
645 switch (call->app_call_state) {
646 case RXRPC_CSTATE_ERROR:
647 ret = call->app_errno;
650 case RXRPC_CSTATE_CLNT_GOT_REPLY:
659 set_current_state(TASK_RUNNING);
660 remove_wait_queue(&call->waitq, &myself);
661 rxrpc_put_call(call);
663 afs_server_release_callslot(server, &callslot);
669 set_current_state(TASK_UNINTERRUPTIBLE);
670 rxrpc_call_abort(call, ret);
673 } /* end afs_rxfs_give_up_callback() */
675 /*****************************************************************************/
677 * look a filename up in a directory
678 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
681 int afs_rxfs_lookup(struct afs_server *server,
682 struct afs_vnode *dir,
683 const char *filename,
684 struct afs_vnode *vnode,
685 struct afs_volsync *volsync)
687 struct rxrpc_connection *conn;
688 struct rxrpc_call *call;
694 DECLARE_WAITQUEUE(myself, current);
696 kenter("%p,{%u,%u,%u},%s",
697 server, fid->vid, fid->vnode, fid->unique, filename);
699 /* get hold of the fileserver connection */
700 ret = afs_server_get_fsconn(server, &conn);
704 /* create a call through that connection */
705 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
707 printk("kAFS: Unable to create call: %d\n", ret);
710 call->app_opcode = FSLOOKUP;
712 /* we want to get event notifications from the call */
713 add_wait_queue(&call->waitq,&myself);
715 /* marshall the parameters */
716 bp = rxrpc_call_alloc_scratch(call, 20);
720 piov[0].iov_len = 20;
721 piov[0].iov_base = bp;
722 piov[1].iov_len = strlen(filename);
723 piov[1].iov_base = (char *) filename;
724 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
725 piov[2].iov_base = &zero;
727 *bp++ = htonl(FSLOOKUP);
728 *bp++ = htonl(dirfid->vid);
729 *bp++ = htonl(dirfid->vnode);
730 *bp++ = htonl(dirfid->unique);
731 *bp++ = htonl(piov[1].iov_len);
733 /* send the parameters to the server */
734 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
739 /* wait for the reply to completely arrive */
740 bp = rxrpc_call_alloc_scratch(call, 220);
742 ret = rxrpc_call_read_data(call, bp, 220,
743 RXRPC_CALL_READ_BLOCK |
744 RXRPC_CALL_READ_ALL);
746 if (ret == -ECONNABORTED) {
747 ret = call->app_errno;
753 /* unmarshall the reply */
754 fid->vid = ntohl(*bp++);
755 fid->vnode = ntohl(*bp++);
756 fid->unique = ntohl(*bp++);
758 vnode->status.if_version = ntohl(*bp++);
759 vnode->status.type = ntohl(*bp++);
760 vnode->status.nlink = ntohl(*bp++);
761 vnode->status.size = ntohl(*bp++);
762 vnode->status.version = ntohl(*bp++);
763 vnode->status.author = ntohl(*bp++);
764 vnode->status.owner = ntohl(*bp++);
765 vnode->status.caller_access = ntohl(*bp++);
766 vnode->status.anon_access = ntohl(*bp++);
767 vnode->status.mode = ntohl(*bp++);
768 vnode->status.parent.vid = dirfid->vid;
769 vnode->status.parent.vnode = ntohl(*bp++);
770 vnode->status.parent.unique = ntohl(*bp++);
772 vnode->status.mtime_client = ntohl(*bp++);
773 vnode->status.mtime_server = ntohl(*bp++);
775 bp++; /* sync counter */
776 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
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++);
795 dir->status.mtime_client = ntohl(*bp++);
796 dir->status.mtime_server = ntohl(*bp++);
798 bp++; /* sync counter */
799 dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
804 callback->fid = *fid;
805 callback->version = ntohl(*bp++);
806 callback->expiry = ntohl(*bp++);
807 callback->type = ntohl(*bp++);
810 volsync->creation = ntohl(*bp++);
822 set_current_state(TASK_RUNNING);
823 remove_wait_queue(&call->waitq, &myself);
824 rxrpc_put_call(call);
826 afs_server_release_fsconn(server, conn);
832 set_current_state(TASK_UNINTERRUPTIBLE);
833 rxrpc_call_abort(call, ret);
836 } /* end afs_rxfs_lookup() */