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 */
33 * map afs abort codes to/from Linux error codes
34 * - called with call->lock held
36 static void afs_rxfs_aemap(struct rxrpc_call *call)
38 switch (call->app_err_state) {
39 case RXRPC_ESTATE_LOCAL_ABORT:
40 call->app_abort_code = -call->app_errno;
42 case RXRPC_ESTATE_PEER_ABORT:
43 call->app_errno = afs_abort_to_error(call->app_abort_code);
51 * get the root volume name from a fileserver
52 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
55 int afs_rxfs_get_root_volume(struct afs_server *server,
56 char *buf, size_t *buflen)
58 struct rxrpc_connection *conn;
59 struct rxrpc_call *call;
65 DECLARE_WAITQUEUE(myself, current);
67 kenter("%p,%p,%u",server, buf, *buflen);
69 /* get hold of the fileserver connection */
70 ret = afs_server_get_fsconn(server, &conn);
74 /* create a call through that connection */
75 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
77 printk("kAFS: Unable to create call: %d\n", ret);
80 call->app_opcode = FSGETROOTVOLUME;
82 /* we want to get event notifications from the call */
83 add_wait_queue(&call->waitq, &myself);
85 /* marshall the parameters */
86 param[0] = htonl(FSGETROOTVOLUME);
88 piov[0].iov_len = sizeof(param);
89 piov[0].iov_base = param;
91 /* send the parameters to the server */
92 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
97 /* wait for the reply to completely arrive */
99 set_current_state(TASK_INTERRUPTIBLE);
100 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
101 signal_pending(current))
105 set_current_state(TASK_RUNNING);
108 if (signal_pending(current))
111 switch (call->app_call_state) {
112 case RXRPC_CSTATE_ERROR:
113 ret = call->app_errno;
114 kdebug("Got Error: %d", ret);
117 case RXRPC_CSTATE_CLNT_GOT_REPLY:
119 kdebug("Got Reply: qty=%d", call->app_ready_qty);
122 if (call->app_ready_qty <= 4)
125 ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0);
130 /* unmarshall the reply */
132 for (loop = 0; loop < 65; loop++)
133 entry->name[loop] = ntohl(*bp++);
136 entry->type = ntohl(*bp++);
137 entry->num_servers = ntohl(*bp++);
139 for (loop = 0; loop < 8; loop++)
140 entry->servers[loop].addr.s_addr = *bp++;
142 for (loop = 0; loop < 8; loop++)
143 entry->servers[loop].partition = ntohl(*bp++);
145 for (loop = 0; loop < 8; loop++)
146 entry->servers[loop].flags = ntohl(*bp++);
148 for (loop = 0; loop < 3; loop++)
149 entry->volume_ids[loop] = ntohl(*bp++);
151 entry->clone_id = ntohl(*bp++);
152 entry->flags = ntohl(*bp);
164 set_current_state(TASK_UNINTERRUPTIBLE);
165 rxrpc_call_abort(call, ret);
168 set_current_state(TASK_RUNNING);
169 remove_wait_queue(&call->waitq, &myself);
170 rxrpc_put_call(call);
172 afs_server_release_fsconn(server, conn);
180 * get information about a volume
183 int afs_rxfs_get_volume_info(struct afs_server *server,
185 struct afs_volume_info *vinfo)
187 struct rxrpc_connection *conn;
188 struct rxrpc_call *call;
192 u32 param[2], *bp, zero;
194 DECLARE_WAITQUEUE(myself, current);
196 _enter("%p,%s,%p", server, name, vinfo);
198 /* get hold of the fileserver connection */
199 ret = afs_server_get_fsconn(server, &conn);
203 /* create a call through that connection */
204 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
206 printk("kAFS: Unable to create call: %d\n", ret);
209 call->app_opcode = FSGETVOLUMEINFO;
211 /* we want to get event notifications from the call */
212 add_wait_queue(&call->waitq, &myself);
214 /* marshall the parameters */
215 piov[1].iov_len = strlen(name);
216 piov[1].iov_base = (char *) name;
219 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
220 piov[2].iov_base = &zero;
222 param[0] = htonl(FSGETVOLUMEINFO);
223 param[1] = htonl(piov[1].iov_len);
225 piov[0].iov_len = sizeof(param);
226 piov[0].iov_base = param;
228 /* send the parameters to the server */
229 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
234 /* wait for the reply to completely arrive */
235 bp = rxrpc_call_alloc_scratch(call, 64);
237 ret = rxrpc_call_read_data(call, bp, 64,
238 RXRPC_CALL_READ_BLOCK |
239 RXRPC_CALL_READ_ALL);
241 if (ret == -ECONNABORTED) {
242 ret = call->app_errno;
248 /* unmarshall the reply */
249 vinfo->vid = ntohl(*bp++);
250 vinfo->type = ntohl(*bp++);
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++);
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++;
269 if (vinfo->nservers > 8)
276 set_current_state(TASK_RUNNING);
277 remove_wait_queue(&call->waitq, &myself);
278 rxrpc_put_call(call);
280 afs_server_release_fsconn(server, conn);
286 set_current_state(TASK_UNINTERRUPTIBLE);
287 rxrpc_call_abort(call, ret);
294 * fetch the status information for a file
296 int afs_rxfs_fetch_file_status(struct afs_server *server,
297 struct afs_vnode *vnode,
298 struct afs_volsync *volsync)
300 struct afs_server_callslot callslot;
301 struct rxrpc_call *call;
307 DECLARE_WAITQUEUE(myself, current);
309 _enter("%p,{%u,%u,%u}",
310 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
312 /* get hold of the fileserver connection */
313 ret = afs_server_request_callslot(server, &callslot);
317 /* create a call through that connection */
318 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap,
321 printk("kAFS: Unable to create call: %d\n", ret);
324 call->app_opcode = FSFETCHSTATUS;
326 /* we want to get event notifications from the call */
327 add_wait_queue(&call->waitq, &myself);
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);
336 piov[0].iov_len = 16;
337 piov[0].iov_base = bp;
339 /* send the parameters to the server */
340 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
345 /* wait for the reply to completely arrive */
346 bp = rxrpc_call_alloc_scratch(call, 120);
348 ret = rxrpc_call_read_data(call, bp, 120,
349 RXRPC_CALL_READ_BLOCK |
350 RXRPC_CALL_READ_ALL);
352 if (ret == -ECONNABORTED) {
353 ret = call->app_errno;
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++);
374 vnode->status.mtime_client = ntohl(*bp++);
375 vnode->status.mtime_server = ntohl(*bp++);
377 bp++; /* sync counter */
378 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
383 vnode->cb_version = ntohl(*bp++);
384 vnode->cb_expiry = ntohl(*bp++);
385 vnode->cb_type = ntohl(*bp++);
388 volsync->creation = ntohl(*bp++);
400 set_current_state(TASK_RUNNING);
401 remove_wait_queue(&call->waitq, &myself);
402 rxrpc_put_call(call);
404 afs_server_release_callslot(server, &callslot);
410 set_current_state(TASK_UNINTERRUPTIBLE);
411 rxrpc_call_abort(call, ret);
417 * fetch the contents of a file or directory
419 int afs_rxfs_fetch_file_data(struct afs_server *server,
420 struct afs_vnode *vnode,
421 struct afs_rxfs_fetch_descriptor *desc,
422 struct afs_volsync *volsync)
424 struct afs_server_callslot callslot;
425 struct rxrpc_call *call;
431 DECLARE_WAITQUEUE(myself, current);
433 _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}",
441 /* get hold of the fileserver connection */
442 ret = afs_server_request_callslot(server, &callslot);
446 /* create a call through that connection */
447 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
449 printk("kAFS: Unable to create call: %d\n", ret);
452 call->app_opcode = FSFETCHDATA;
454 /* we want to get event notifications from the call */
455 add_wait_queue(&call->waitq, &myself);
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);
466 piov[0].iov_len = 24;
467 piov[0].iov_base = bp;
469 /* send the parameters to the server */
470 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
475 /* wait for the data count to arrive */
476 ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK);
480 desc->actual = ntohl(bp[0]);
481 if (desc->actual != desc->size) {
486 /* call the app to read the actual data */
487 rxrpc_call_reset_scratch(call);
489 ret = rxrpc_call_read_data(call, desc->buffer, desc->actual,
490 RXRPC_CALL_READ_BLOCK);
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);
498 ret = rxrpc_call_read_data(call, bp, 120,
499 RXRPC_CALL_READ_BLOCK |
500 RXRPC_CALL_READ_ALL);
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++);
519 vnode->status.mtime_client = ntohl(*bp++);
520 vnode->status.mtime_server = ntohl(*bp++);
522 bp++; /* sync counter */
523 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
528 vnode->cb_version = ntohl(*bp++);
529 vnode->cb_expiry = ntohl(*bp++);
530 vnode->cb_type = ntohl(*bp++);
533 volsync->creation = ntohl(*bp++);
545 set_current_state(TASK_RUNNING);
546 remove_wait_queue(&call->waitq,&myself);
547 rxrpc_put_call(call);
549 afs_server_release_callslot(server, &callslot);
551 _leave(" = %d", ret);
555 if (ret == -ECONNABORTED) {
556 ret = call->app_errno;
561 set_current_state(TASK_UNINTERRUPTIBLE);
562 rxrpc_call_abort(call, ret);
568 * ask the AFS fileserver to discard a callback request on a file
570 int afs_rxfs_give_up_callback(struct afs_server *server,
571 struct afs_vnode *vnode)
573 struct afs_server_callslot callslot;
574 struct rxrpc_call *call;
580 DECLARE_WAITQUEUE(myself, current);
582 _enter("%p,{%u,%u,%u}",
583 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
585 /* get hold of the fileserver connection */
586 ret = afs_server_request_callslot(server, &callslot);
590 /* create a call through that connection */
591 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call);
593 printk("kAFS: Unable to create call: %d\n", ret);
596 call->app_opcode = FSGIVEUPCALLBACKS;
598 /* we want to get event notifications from the call */
599 add_wait_queue(&call->waitq, &myself);
601 /* marshall the parameters */
602 bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4);
604 piov[0].iov_len = (1 + 4 + 4) * 4;
605 piov[0].iov_base = bp;
607 *bp++ = htonl(FSGIVEUPCALLBACKS);
609 *bp++ = htonl(vnode->fid.vid);
610 *bp++ = htonl(vnode->fid.vnode);
611 *bp++ = htonl(vnode->fid.unique);
613 *bp++ = htonl(vnode->cb_version);
614 *bp++ = htonl(vnode->cb_expiry);
615 *bp++ = htonl(vnode->cb_type);
617 /* send the parameters to the server */
618 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
623 /* wait for the reply to completely arrive */
625 set_current_state(TASK_INTERRUPTIBLE);
626 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
627 signal_pending(current))
631 set_current_state(TASK_RUNNING);
634 if (signal_pending(current))
637 switch (call->app_call_state) {
638 case RXRPC_CSTATE_ERROR:
639 ret = call->app_errno;
642 case RXRPC_CSTATE_CLNT_GOT_REPLY:
651 set_current_state(TASK_RUNNING);
652 remove_wait_queue(&call->waitq, &myself);
653 rxrpc_put_call(call);
655 afs_server_release_callslot(server, &callslot);
661 set_current_state(TASK_UNINTERRUPTIBLE);
662 rxrpc_call_abort(call, ret);
668 * look a filename up in a directory
669 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
672 int afs_rxfs_lookup(struct afs_server *server,
673 struct afs_vnode *dir,
674 const char *filename,
675 struct afs_vnode *vnode,
676 struct afs_volsync *volsync)
678 struct rxrpc_connection *conn;
679 struct rxrpc_call *call;
685 DECLARE_WAITQUEUE(myself, current);
687 kenter("%p,{%u,%u,%u},%s",
688 server, fid->vid, fid->vnode, fid->unique, filename);
690 /* get hold of the fileserver connection */
691 ret = afs_server_get_fsconn(server, &conn);
695 /* create a call through that connection */
696 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call);
698 printk("kAFS: Unable to create call: %d\n", ret);
701 call->app_opcode = FSLOOKUP;
703 /* we want to get event notifications from the call */
704 add_wait_queue(&call->waitq,&myself);
706 /* marshall the parameters */
707 bp = rxrpc_call_alloc_scratch(call, 20);
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;
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);
724 /* send the parameters to the server */
725 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
730 /* wait for the reply to completely arrive */
731 bp = rxrpc_call_alloc_scratch(call, 220);
733 ret = rxrpc_call_read_data(call, bp, 220,
734 RXRPC_CALL_READ_BLOCK |
735 RXRPC_CALL_READ_ALL);
737 if (ret == -ECONNABORTED) {
738 ret = call->app_errno;
744 /* unmarshall the reply */
745 fid->vid = ntohl(*bp++);
746 fid->vnode = ntohl(*bp++);
747 fid->unique = ntohl(*bp++);
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++);
763 vnode->status.mtime_client = ntohl(*bp++);
764 vnode->status.mtime_server = ntohl(*bp++);
766 bp++; /* sync counter */
767 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
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++);
786 dir->status.mtime_client = ntohl(*bp++);
787 dir->status.mtime_server = ntohl(*bp++);
789 bp++; /* sync counter */
790 dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
795 callback->fid = *fid;
796 callback->version = ntohl(*bp++);
797 callback->expiry = ntohl(*bp++);
798 callback->type = ntohl(*bp++);
801 volsync->creation = ntohl(*bp++);
813 set_current_state(TASK_RUNNING);
814 remove_wait_queue(&call->waitq, &myself);
815 rxrpc_put_call(call);
817 afs_server_release_fsconn(server, conn);
823 set_current_state(TASK_UNINTERRUPTIBLE);
824 rxrpc_call_abort(call, ret);