1 /* AFS Volume Location Service client
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>
21 #include "kafsasyncd.h"
22 #include "kafstimod.h"
26 #define VLGETENTRYBYID 503 /* AFS Get Cache Entry By ID operation ID */
27 #define VLGETENTRYBYNAME 504 /* AFS Get Cache Entry By Name operation ID */
28 #define VLPROBE 514 /* AFS Probe Volume Location Service operation ID */
30 static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call);
31 static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call);
34 * map afs VL abort codes to/from Linux error codes
35 * - called with call->lock held
37 static void afs_rxvl_aemap(struct rxrpc_call *call)
42 call->app_err_state, call->app_abort_code, call->app_errno);
44 switch (call->app_err_state) {
45 case RXRPC_ESTATE_LOCAL_ABORT:
46 call->app_abort_code = -call->app_errno;
49 case RXRPC_ESTATE_PEER_ABORT:
50 switch (call->app_abort_code) {
51 case AFSVL_IDEXIST: err = -EEXIST; break;
52 case AFSVL_IO: err = -EREMOTEIO; break;
53 case AFSVL_NAMEEXIST: err = -EEXIST; break;
54 case AFSVL_CREATEFAIL: err = -EREMOTEIO; break;
55 case AFSVL_NOENT: err = -ENOMEDIUM; break;
56 case AFSVL_EMPTY: err = -ENOMEDIUM; break;
57 case AFSVL_ENTDELETED: err = -ENOMEDIUM; break;
58 case AFSVL_BADNAME: err = -EINVAL; break;
59 case AFSVL_BADINDEX: err = -EINVAL; break;
60 case AFSVL_BADVOLTYPE: err = -EINVAL; break;
61 case AFSVL_BADSERVER: err = -EINVAL; break;
62 case AFSVL_BADPARTITION: err = -EINVAL; break;
63 case AFSVL_REPSFULL: err = -EFBIG; break;
64 case AFSVL_NOREPSERVER: err = -ENOENT; break;
65 case AFSVL_DUPREPSERVER: err = -EEXIST; break;
66 case AFSVL_RWNOTFOUND: err = -ENOENT; break;
67 case AFSVL_BADREFCOUNT: err = -EINVAL; break;
68 case AFSVL_SIZEEXCEEDED: err = -EINVAL; break;
69 case AFSVL_BADENTRY: err = -EINVAL; break;
70 case AFSVL_BADVOLIDBUMP: err = -EINVAL; break;
71 case AFSVL_IDALREADYHASHED: err = -EINVAL; break;
72 case AFSVL_ENTRYLOCKED: err = -EBUSY; break;
73 case AFSVL_BADVOLOPER: err = -EBADRQC; break;
74 case AFSVL_BADRELLOCKTYPE: err = -EINVAL; break;
75 case AFSVL_RERELEASE: err = -EREMOTEIO; break;
76 case AFSVL_BADSERVERFLAG: err = -EINVAL; break;
77 case AFSVL_PERM: err = -EACCES; break;
78 case AFSVL_NOMEM: err = -EREMOTEIO; break;
80 err = afs_abort_to_error(call->app_abort_code);
83 call->app_errno = err;
93 * probe a volume location server to see if it is still alive -- unused
95 static int afs_rxvl_probe(struct afs_server *server, int alloc_flags)
97 struct rxrpc_connection *conn;
98 struct rxrpc_call *call;
104 DECLARE_WAITQUEUE(myself, current);
106 /* get hold of the vlserver connection */
107 ret = afs_server_get_vlconn(server, &conn);
111 /* create a call through that connection */
112 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);
114 printk("kAFS: Unable to create call: %d\n", ret);
117 call->app_opcode = VLPROBE;
119 /* we want to get event notifications from the call */
120 add_wait_queue(&call->waitq, &myself);
122 /* marshall the parameters */
123 param[0] = htonl(VLPROBE);
124 piov[0].iov_len = sizeof(param);
125 piov[0].iov_base = param;
127 /* send the parameters to the server */
128 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET,
129 alloc_flags, 0, &sent);
133 /* wait for the reply to completely arrive */
135 set_current_state(TASK_INTERRUPTIBLE);
136 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
137 signal_pending(current))
141 set_current_state(TASK_RUNNING);
144 if (signal_pending(current))
147 switch (call->app_call_state) {
148 case RXRPC_CSTATE_ERROR:
149 ret = call->app_errno;
152 case RXRPC_CSTATE_CLNT_GOT_REPLY:
161 set_current_state(TASK_UNINTERRUPTIBLE);
162 rxrpc_call_abort(call, ret);
166 set_current_state(TASK_RUNNING);
167 remove_wait_queue(&call->waitq, &myself);
168 rxrpc_put_call(call);
170 rxrpc_put_connection(conn);
177 * look up a volume location database entry by name
179 int afs_rxvl_get_entry_by_name(struct afs_server *server,
182 struct afs_cache_vlocation *entry)
184 DECLARE_WAITQUEUE(myself, current);
186 struct rxrpc_connection *conn;
187 struct rxrpc_call *call;
192 __be32 *bp, param[2], zero;
194 _enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz);
196 memset(entry, 0, sizeof(*entry));
198 /* get hold of the vlserver connection */
199 ret = afs_server_get_vlconn(server, &conn);
203 /* create a call through that connection */
204 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);
206 printk("kAFS: Unable to create call: %d\n", ret);
209 call->app_opcode = VLGETENTRYBYNAME;
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 = volnamesz;
216 piov[1].iov_base = (char *) volname;
219 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
220 piov[2].iov_base = &zero;
222 param[0] = htonl(VLGETENTRYBYNAME);
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, 384);
237 ret = rxrpc_call_read_data(call, bp, 384,
238 RXRPC_CALL_READ_BLOCK |
239 RXRPC_CALL_READ_ALL);
241 if (ret == -ECONNABORTED) {
242 ret = call->app_errno;
248 /* unmarshall the reply */
249 for (loop = 0; loop < 64; loop++)
250 entry->name[loop] = ntohl(*bp++);
251 bp++; /* final NUL */
254 entry->nservers = ntohl(*bp++);
256 for (loop = 0; loop < 8; loop++)
257 entry->servers[loop].s_addr = *bp++;
259 bp += 8; /* partition IDs */
261 for (loop = 0; loop < 8; loop++) {
263 if (tmp & AFS_VLSF_RWVOL)
264 entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
265 if (tmp & AFS_VLSF_ROVOL)
266 entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
267 if (tmp & AFS_VLSF_BACKVOL)
268 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
271 entry->vid[0] = ntohl(*bp++);
272 entry->vid[1] = ntohl(*bp++);
273 entry->vid[2] = ntohl(*bp++);
277 tmp = ntohl(*bp++); /* flags */
278 if (tmp & AFS_VLF_RWEXISTS)
279 entry->vidmask |= AFS_VOL_VTM_RW;
280 if (tmp & AFS_VLF_ROEXISTS)
281 entry->vidmask |= AFS_VOL_VTM_RO;
282 if (tmp & AFS_VLF_BACKEXISTS)
283 entry->vidmask |= AFS_VOL_VTM_BAK;
290 entry->rtime = get_seconds();
294 set_current_state(TASK_RUNNING);
295 remove_wait_queue(&call->waitq, &myself);
296 rxrpc_put_call(call);
298 rxrpc_put_connection(conn);
300 _leave(" = %d", ret);
304 set_current_state(TASK_UNINTERRUPTIBLE);
305 rxrpc_call_abort(call, ret);
311 * look up a volume location database entry by ID
313 int afs_rxvl_get_entry_by_id(struct afs_server *server,
315 afs_voltype_t voltype,
316 struct afs_cache_vlocation *entry)
318 DECLARE_WAITQUEUE(myself, current);
320 struct rxrpc_connection *conn;
321 struct rxrpc_call *call;
326 __be32 *bp, param[3];
328 _enter(",%x,%d,", volid, voltype);
330 memset(entry, 0, sizeof(*entry));
332 /* get hold of the vlserver connection */
333 ret = afs_server_get_vlconn(server, &conn);
337 /* create a call through that connection */
338 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);
340 printk("kAFS: Unable to create call: %d\n", ret);
343 call->app_opcode = VLGETENTRYBYID;
345 /* we want to get event notifications from the call */
346 add_wait_queue(&call->waitq, &myself);
348 /* marshall the parameters */
349 param[0] = htonl(VLGETENTRYBYID);
350 param[1] = htonl(volid);
351 param[2] = htonl(voltype);
353 piov[0].iov_len = sizeof(param);
354 piov[0].iov_base = param;
356 /* send the parameters to the server */
357 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
362 /* wait for the reply to completely arrive */
363 bp = rxrpc_call_alloc_scratch(call, 384);
365 ret = rxrpc_call_read_data(call, bp, 384,
366 RXRPC_CALL_READ_BLOCK |
367 RXRPC_CALL_READ_ALL);
369 if (ret == -ECONNABORTED) {
370 ret = call->app_errno;
376 /* unmarshall the reply */
377 for (loop = 0; loop < 64; loop++)
378 entry->name[loop] = ntohl(*bp++);
379 bp++; /* final NUL */
382 entry->nservers = ntohl(*bp++);
384 for (loop = 0; loop < 8; loop++)
385 entry->servers[loop].s_addr = *bp++;
387 bp += 8; /* partition IDs */
389 for (loop = 0; loop < 8; loop++) {
391 if (tmp & AFS_VLSF_RWVOL)
392 entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
393 if (tmp & AFS_VLSF_ROVOL)
394 entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
395 if (tmp & AFS_VLSF_BACKVOL)
396 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
399 entry->vid[0] = ntohl(*bp++);
400 entry->vid[1] = ntohl(*bp++);
401 entry->vid[2] = ntohl(*bp++);
405 tmp = ntohl(*bp++); /* flags */
406 if (tmp & AFS_VLF_RWEXISTS)
407 entry->vidmask |= AFS_VOL_VTM_RW;
408 if (tmp & AFS_VLF_ROEXISTS)
409 entry->vidmask |= AFS_VOL_VTM_RO;
410 if (tmp & AFS_VLF_BACKEXISTS)
411 entry->vidmask |= AFS_VOL_VTM_BAK;
417 #if 0 /* TODO: remove */
419 entry->servers[0].s_addr = htonl(0xac101249);
420 entry->servers[1].s_addr = htonl(0xac101243);
421 entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
423 entry->srvtmask[0] = AFS_VOL_VTM_RO;
424 entry->srvtmask[1] = AFS_VOL_VTM_RO;
425 entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW;
429 entry->rtime = get_seconds();
433 set_current_state(TASK_RUNNING);
434 remove_wait_queue(&call->waitq, &myself);
435 rxrpc_put_call(call);
437 rxrpc_put_connection(conn);
439 _leave(" = %d", ret);
443 set_current_state(TASK_UNINTERRUPTIBLE);
444 rxrpc_call_abort(call, ret);
450 * look up a volume location database entry by ID asynchronously
452 int afs_rxvl_get_entry_by_id_async(struct afs_async_op *op,
454 afs_voltype_t voltype)
456 struct rxrpc_connection *conn;
457 struct rxrpc_call *call;
463 _enter(",%x,%d,", volid, voltype);
465 /* get hold of the vlserver connection */
466 ret = afs_server_get_vlconn(op->server, &conn);
468 _leave(" = %d", ret);
472 /* create a call through that connection */
473 ret = rxrpc_create_call(conn,
474 afs_rxvl_get_entry_by_id_attn,
475 afs_rxvl_get_entry_by_id_error,
478 rxrpc_put_connection(conn);
481 printk("kAFS: Unable to create call: %d\n", ret);
482 _leave(" = %d", ret);
486 op->call->app_opcode = VLGETENTRYBYID;
487 op->call->app_user = op;
490 rxrpc_get_call(call);
492 /* send event notifications from the call to kafsasyncd */
493 afs_kafsasyncd_begin_op(op);
495 /* marshall the parameters */
496 param[0] = htonl(VLGETENTRYBYID);
497 param[1] = htonl(volid);
498 param[2] = htonl(voltype);
500 piov[0].iov_len = sizeof(param);
501 piov[0].iov_base = param;
503 /* allocate result read buffer in scratch space */
504 call->app_scr_ptr = rxrpc_call_alloc_scratch(op->call, 384);
506 /* send the parameters to the server */
507 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
510 rxrpc_call_abort(call, ret); /* handle from kafsasyncd */
515 /* wait for the reply to completely arrive */
516 ret = rxrpc_call_read_data(call, call->app_scr_ptr, 384, 0);
522 break; /* all handled by kafsasyncd */
525 rxrpc_call_abort(call, ret); /* make kafsasyncd handle it */
531 rxrpc_put_call(call);
532 _leave(" = %d", ret);
537 * attend to the asynchronous get VLDB entry by ID
539 int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *op,
540 struct afs_cache_vlocation *entry)
546 _enter("{op=%p cst=%u}", op, op->call->app_call_state);
548 memset(entry, 0, sizeof(*entry));
550 if (op->call->app_call_state == RXRPC_CSTATE_COMPLETE) {
551 /* operation finished */
552 afs_kafsasyncd_terminate_op(op);
554 bp = op->call->app_scr_ptr;
556 /* unmarshall the reply */
557 for (loop = 0; loop < 64; loop++)
558 entry->name[loop] = ntohl(*bp++);
559 bp++; /* final NUL */
562 entry->nservers = ntohl(*bp++);
564 for (loop = 0; loop < 8; loop++)
565 entry->servers[loop].s_addr = *bp++;
567 bp += 8; /* partition IDs */
569 for (loop = 0; loop < 8; loop++) {
571 if (tmp & AFS_VLSF_RWVOL)
572 entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
573 if (tmp & AFS_VLSF_ROVOL)
574 entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
575 if (tmp & AFS_VLSF_BACKVOL)
576 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
579 entry->vid[0] = ntohl(*bp++);
580 entry->vid[1] = ntohl(*bp++);
581 entry->vid[2] = ntohl(*bp++);
585 tmp = ntohl(*bp++); /* flags */
586 if (tmp & AFS_VLF_RWEXISTS)
587 entry->vidmask |= AFS_VOL_VTM_RW;
588 if (tmp & AFS_VLF_ROEXISTS)
589 entry->vidmask |= AFS_VOL_VTM_RO;
590 if (tmp & AFS_VLF_BACKEXISTS)
591 entry->vidmask |= AFS_VOL_VTM_BAK;
594 if (!entry->vidmask) {
595 rxrpc_call_abort(op->call, ret);
599 #if 0 /* TODO: remove */
601 entry->servers[0].s_addr = htonl(0xac101249);
602 entry->servers[1].s_addr = htonl(0xac101243);
603 entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
605 entry->srvtmask[0] = AFS_VOL_VTM_RO;
606 entry->srvtmask[1] = AFS_VOL_VTM_RO;
607 entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW;
611 entry->rtime = get_seconds();
616 if (op->call->app_call_state == RXRPC_CSTATE_ERROR) {
617 /* operation error */
618 ret = op->call->app_errno;
622 _leave(" = -EAGAIN");
626 rxrpc_put_call(op->call);
628 _leave(" = %d", ret);
633 * handle attention events on an async get-entry-by-ID op
634 * - called from krxiod
636 static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call)
638 struct afs_async_op *op = call->app_user;
640 _enter("{op=%p cst=%u}", op, call->app_call_state);
642 switch (call->app_call_state) {
643 case RXRPC_CSTATE_COMPLETE:
644 afs_kafsasyncd_attend_op(op);
646 case RXRPC_CSTATE_CLNT_RCV_REPLY:
647 if (call->app_async_read)
649 case RXRPC_CSTATE_CLNT_GOT_REPLY:
650 if (call->app_read_count == 0)
652 printk("kAFS: Reply bigger than expected"
653 " {cst=%u asyn=%d mark=%Zu rdy=%Zu pr=%u%s}",
654 call->app_call_state,
655 call->app_async_read,
659 call->app_last_rcv ? " last" : "");
661 rxrpc_call_abort(call, -EBADMSG);
671 * handle error events on an async get-entry-by-ID op
672 * - called from krxiod
674 static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call)
676 struct afs_async_op *op = call->app_user;
678 _enter("{op=%p cst=%u}", op, call->app_call_state);
680 afs_kafsasyncd_attend_op(op);