1 /* vlclient.c: AFS Volume Location Service client 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 "server.h" 19 #include "volume.h" 20 #include "vlclient.h" 21 #include "kafsasyncd.h" 22 #include "kafstimod.h" 23 #include "errors.h" 24 #include "internal.h" 25 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 */ 29 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); 32 33 /*****************************************************************************/ 34 /* 35 * map afs VL abort codes to/from Linux error codes 36 * - called with call->lock held 37 */ 38 static void afs_rxvl_aemap(struct rxrpc_call *call) 39 { 40 int err; 41 42 _enter("{%u,%u,%d}", 43 call->app_err_state, call->app_abort_code, call->app_errno); 44 45 switch (call->app_err_state) { 46 case RXRPC_ESTATE_LOCAL_ABORT: 47 call->app_abort_code = -call->app_errno; 48 return; 49 50 case RXRPC_ESTATE_PEER_ABORT: 51 switch (call->app_abort_code) { 52 case AFSVL_IDEXIST: err = -EEXIST; break; 53 case AFSVL_IO: err = -EREMOTEIO; break; 54 case AFSVL_NAMEEXIST: err = -EEXIST; break; 55 case AFSVL_CREATEFAIL: err = -EREMOTEIO; break; 56 case AFSVL_NOENT: err = -ENOMEDIUM; break; 57 case AFSVL_EMPTY: err = -ENOMEDIUM; break; 58 case AFSVL_ENTDELETED: err = -ENOMEDIUM; break; 59 case AFSVL_BADNAME: err = -EINVAL; break; 60 case AFSVL_BADINDEX: err = -EINVAL; break; 61 case AFSVL_BADVOLTYPE: err = -EINVAL; break; 62 case AFSVL_BADSERVER: err = -EINVAL; break; 63 case AFSVL_BADPARTITION: err = -EINVAL; break; 64 case AFSVL_REPSFULL: err = -EFBIG; break; 65 case AFSVL_NOREPSERVER: err = -ENOENT; break; 66 case AFSVL_DUPREPSERVER: err = -EEXIST; break; 67 case AFSVL_RWNOTFOUND: err = -ENOENT; break; 68 case AFSVL_BADREFCOUNT: err = -EINVAL; break; 69 case AFSVL_SIZEEXCEEDED: err = -EINVAL; break; 70 case AFSVL_BADENTRY: err = -EINVAL; break; 71 case AFSVL_BADVOLIDBUMP: err = -EINVAL; break; 72 case AFSVL_IDALREADYHASHED: err = -EINVAL; break; 73 case AFSVL_ENTRYLOCKED: err = -EBUSY; break; 74 case AFSVL_BADVOLOPER: err = -EBADRQC; break; 75 case AFSVL_BADRELLOCKTYPE: err = -EINVAL; break; 76 case AFSVL_RERELEASE: err = -EREMOTEIO; break; 77 case AFSVL_BADSERVERFLAG: err = -EINVAL; break; 78 case AFSVL_PERM: err = -EACCES; break; 79 case AFSVL_NOMEM: err = -EREMOTEIO; break; 80 default: 81 err = afs_abort_to_error(call->app_abort_code); 82 break; 83 } 84 call->app_errno = err; 85 return; 86 87 default: 88 return; 89 } 90 } /* end afs_rxvl_aemap() */ 91 92 #if 0 93 /*****************************************************************************/ 94 /* 95 * probe a volume location server to see if it is still alive -- unused 96 */ 97 static int afs_rxvl_probe(struct afs_server *server, int alloc_flags) 98 { 99 struct rxrpc_connection *conn; 100 struct rxrpc_call *call; 101 struct kvec piov[1]; 102 size_t sent; 103 int ret; 104 __be32 param[1]; 105 106 DECLARE_WAITQUEUE(myself, current); 107 108 /* get hold of the vlserver connection */ 109 ret = afs_server_get_vlconn(server, &conn); 110 if (ret < 0) 111 goto out; 112 113 /* create a call through that connection */ 114 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call); 115 if (ret < 0) { 116 printk("kAFS: Unable to create call: %d\n", ret); 117 goto out_put_conn; 118 } 119 call->app_opcode = VLPROBE; 120 121 /* we want to get event notifications from the call */ 122 add_wait_queue(&call->waitq, &myself); 123 124 /* marshall the parameters */ 125 param[0] = htonl(VLPROBE); 126 piov[0].iov_len = sizeof(param); 127 piov[0].iov_base = param; 128 129 /* send the parameters to the server */ 130 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, 131 alloc_flags, 0, &sent); 132 if (ret < 0) 133 goto abort; 134 135 /* wait for the reply to completely arrive */ 136 for (;;) { 137 set_current_state(TASK_INTERRUPTIBLE); 138 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY || 139 signal_pending(current)) 140 break; 141 schedule(); 142 } 143 set_current_state(TASK_RUNNING); 144 145 ret = -EINTR; 146 if (signal_pending(current)) 147 goto abort; 148 149 switch (call->app_call_state) { 150 case RXRPC_CSTATE_ERROR: 151 ret = call->app_errno; 152 goto out_unwait; 153 154 case RXRPC_CSTATE_CLNT_GOT_REPLY: 155 ret = 0; 156 goto out_unwait; 157 158 default: 159 BUG(); 160 } 161 162 abort: 163 set_current_state(TASK_UNINTERRUPTIBLE); 164 rxrpc_call_abort(call, ret); 165 schedule(); 166 167 out_unwait: 168 set_current_state(TASK_RUNNING); 169 remove_wait_queue(&call->waitq, &myself); 170 rxrpc_put_call(call); 171 out_put_conn: 172 rxrpc_put_connection(conn); 173 out: 174 return ret; 175 176 } /* end afs_rxvl_probe() */ 177 #endif 178 179 /*****************************************************************************/ 180 /* 181 * look up a volume location database entry by name 182 */ 183 int afs_rxvl_get_entry_by_name(struct afs_server *server, 184 const char *volname, 185 unsigned volnamesz, 186 struct afs_cache_vlocation *entry) 187 { 188 DECLARE_WAITQUEUE(myself, current); 189 190 struct rxrpc_connection *conn; 191 struct rxrpc_call *call; 192 struct kvec piov[3]; 193 unsigned tmp; 194 size_t sent; 195 int ret, loop; 196 __be32 *bp, param[2], zero; 197 198 _enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz); 199 200 memset(entry, 0, sizeof(*entry)); 201 202 /* get hold of the vlserver connection */ 203 ret = afs_server_get_vlconn(server, &conn); 204 if (ret < 0) 205 goto out; 206 207 /* create a call through that connection */ 208 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call); 209 if (ret < 0) { 210 printk("kAFS: Unable to create call: %d\n", ret); 211 goto out_put_conn; 212 } 213 call->app_opcode = VLGETENTRYBYNAME; 214 215 /* we want to get event notifications from the call */ 216 add_wait_queue(&call->waitq, &myself); 217 218 /* marshall the parameters */ 219 piov[1].iov_len = volnamesz; 220 piov[1].iov_base = (char *) volname; 221 222 zero = 0; 223 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; 224 piov[2].iov_base = &zero; 225 226 param[0] = htonl(VLGETENTRYBYNAME); 227 param[1] = htonl(piov[1].iov_len); 228 229 piov[0].iov_len = sizeof(param); 230 piov[0].iov_base = param; 231 232 /* send the parameters to the server */ 233 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, 234 0, &sent); 235 if (ret < 0) 236 goto abort; 237 238 /* wait for the reply to completely arrive */ 239 bp = rxrpc_call_alloc_scratch(call, 384); 240 241 ret = rxrpc_call_read_data(call, bp, 384, 242 RXRPC_CALL_READ_BLOCK | 243 RXRPC_CALL_READ_ALL); 244 if (ret < 0) { 245 if (ret == -ECONNABORTED) { 246 ret = call->app_errno; 247 goto out_unwait; 248 } 249 goto abort; 250 } 251 252 /* unmarshall the reply */ 253 for (loop = 0; loop < 64; loop++) 254 entry->name[loop] = ntohl(*bp++); 255 bp++; /* final NUL */ 256 257 bp++; /* type */ 258 entry->nservers = ntohl(*bp++); 259 260 for (loop = 0; loop < 8; loop++) 261 entry->servers[loop].s_addr = *bp++; 262 263 bp += 8; /* partition IDs */ 264 265 for (loop = 0; loop < 8; loop++) { 266 tmp = ntohl(*bp++); 267 if (tmp & AFS_VLSF_RWVOL) 268 entry->srvtmask[loop] |= AFS_VOL_VTM_RW; 269 if (tmp & AFS_VLSF_ROVOL) 270 entry->srvtmask[loop] |= AFS_VOL_VTM_RO; 271 if (tmp & AFS_VLSF_BACKVOL) 272 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK; 273 } 274 275 entry->vid[0] = ntohl(*bp++); 276 entry->vid[1] = ntohl(*bp++); 277 entry->vid[2] = ntohl(*bp++); 278 279 bp++; /* clone ID */ 280 281 tmp = ntohl(*bp++); /* flags */ 282 if (tmp & AFS_VLF_RWEXISTS) 283 entry->vidmask |= AFS_VOL_VTM_RW; 284 if (tmp & AFS_VLF_ROEXISTS) 285 entry->vidmask |= AFS_VOL_VTM_RO; 286 if (tmp & AFS_VLF_BACKEXISTS) 287 entry->vidmask |= AFS_VOL_VTM_BAK; 288 289 ret = -ENOMEDIUM; 290 if (!entry->vidmask) 291 goto abort; 292 293 /* success */ 294 entry->rtime = get_seconds(); 295 ret = 0; 296 297 out_unwait: 298 set_current_state(TASK_RUNNING); 299 remove_wait_queue(&call->waitq, &myself); 300 rxrpc_put_call(call); 301 out_put_conn: 302 rxrpc_put_connection(conn); 303 out: 304 _leave(" = %d", ret); 305 return ret; 306 307 abort: 308 set_current_state(TASK_UNINTERRUPTIBLE); 309 rxrpc_call_abort(call, ret); 310 schedule(); 311 goto out_unwait; 312 } /* end afs_rxvl_get_entry_by_name() */ 313 314 /*****************************************************************************/ 315 /* 316 * look up a volume location database entry by ID 317 */ 318 int afs_rxvl_get_entry_by_id(struct afs_server *server, 319 afs_volid_t volid, 320 afs_voltype_t voltype, 321 struct afs_cache_vlocation *entry) 322 { 323 DECLARE_WAITQUEUE(myself, current); 324 325 struct rxrpc_connection *conn; 326 struct rxrpc_call *call; 327 struct kvec piov[1]; 328 unsigned tmp; 329 size_t sent; 330 int ret, loop; 331 __be32 *bp, param[3]; 332 333 _enter(",%x,%d,", volid, voltype); 334 335 memset(entry, 0, sizeof(*entry)); 336 337 /* get hold of the vlserver connection */ 338 ret = afs_server_get_vlconn(server, &conn); 339 if (ret < 0) 340 goto out; 341 342 /* create a call through that connection */ 343 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call); 344 if (ret < 0) { 345 printk("kAFS: Unable to create call: %d\n", ret); 346 goto out_put_conn; 347 } 348 call->app_opcode = VLGETENTRYBYID; 349 350 /* we want to get event notifications from the call */ 351 add_wait_queue(&call->waitq, &myself); 352 353 /* marshall the parameters */ 354 param[0] = htonl(VLGETENTRYBYID); 355 param[1] = htonl(volid); 356 param[2] = htonl(voltype); 357 358 piov[0].iov_len = sizeof(param); 359 piov[0].iov_base = param; 360 361 /* send the parameters to the server */ 362 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, 363 0, &sent); 364 if (ret < 0) 365 goto abort; 366 367 /* wait for the reply to completely arrive */ 368 bp = rxrpc_call_alloc_scratch(call, 384); 369 370 ret = rxrpc_call_read_data(call, bp, 384, 371 RXRPC_CALL_READ_BLOCK | 372 RXRPC_CALL_READ_ALL); 373 if (ret < 0) { 374 if (ret == -ECONNABORTED) { 375 ret = call->app_errno; 376 goto out_unwait; 377 } 378 goto abort; 379 } 380 381 /* unmarshall the reply */ 382 for (loop = 0; loop < 64; loop++) 383 entry->name[loop] = ntohl(*bp++); 384 bp++; /* final NUL */ 385 386 bp++; /* type */ 387 entry->nservers = ntohl(*bp++); 388 389 for (loop = 0; loop < 8; loop++) 390 entry->servers[loop].s_addr = *bp++; 391 392 bp += 8; /* partition IDs */ 393 394 for (loop = 0; loop < 8; loop++) { 395 tmp = ntohl(*bp++); 396 if (tmp & AFS_VLSF_RWVOL) 397 entry->srvtmask[loop] |= AFS_VOL_VTM_RW; 398 if (tmp & AFS_VLSF_ROVOL) 399 entry->srvtmask[loop] |= AFS_VOL_VTM_RO; 400 if (tmp & AFS_VLSF_BACKVOL) 401 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK; 402 } 403 404 entry->vid[0] = ntohl(*bp++); 405 entry->vid[1] = ntohl(*bp++); 406 entry->vid[2] = ntohl(*bp++); 407 408 bp++; /* clone ID */ 409 410 tmp = ntohl(*bp++); /* flags */ 411 if (tmp & AFS_VLF_RWEXISTS) 412 entry->vidmask |= AFS_VOL_VTM_RW; 413 if (tmp & AFS_VLF_ROEXISTS) 414 entry->vidmask |= AFS_VOL_VTM_RO; 415 if (tmp & AFS_VLF_BACKEXISTS) 416 entry->vidmask |= AFS_VOL_VTM_BAK; 417 418 ret = -ENOMEDIUM; 419 if (!entry->vidmask) 420 goto abort; 421 422 #if 0 /* TODO: remove */ 423 entry->nservers = 3; 424 entry->servers[0].s_addr = htonl(0xac101249); 425 entry->servers[1].s_addr = htonl(0xac101243); 426 entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/); 427 428 entry->srvtmask[0] = AFS_VOL_VTM_RO; 429 entry->srvtmask[1] = AFS_VOL_VTM_RO; 430 entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW; 431 #endif 432 433 /* success */ 434 entry->rtime = get_seconds(); 435 ret = 0; 436 437 out_unwait: 438 set_current_state(TASK_RUNNING); 439 remove_wait_queue(&call->waitq, &myself); 440 rxrpc_put_call(call); 441 out_put_conn: 442 rxrpc_put_connection(conn); 443 out: 444 _leave(" = %d", ret); 445 return ret; 446 447 abort: 448 set_current_state(TASK_UNINTERRUPTIBLE); 449 rxrpc_call_abort(call, ret); 450 schedule(); 451 goto out_unwait; 452 } /* end afs_rxvl_get_entry_by_id() */ 453 454 /*****************************************************************************/ 455 /* 456 * look up a volume location database entry by ID asynchronously 457 */ 458 int afs_rxvl_get_entry_by_id_async(struct afs_async_op *op, 459 afs_volid_t volid, 460 afs_voltype_t voltype) 461 { 462 struct rxrpc_connection *conn; 463 struct rxrpc_call *call; 464 struct kvec piov[1]; 465 size_t sent; 466 int ret; 467 __be32 param[3]; 468 469 _enter(",%x,%d,", volid, voltype); 470 471 /* get hold of the vlserver connection */ 472 ret = afs_server_get_vlconn(op->server, &conn); 473 if (ret < 0) { 474 _leave(" = %d", ret); 475 return ret; 476 } 477 478 /* create a call through that connection */ 479 ret = rxrpc_create_call(conn, 480 afs_rxvl_get_entry_by_id_attn, 481 afs_rxvl_get_entry_by_id_error, 482 afs_rxvl_aemap, 483 &op->call); 484 rxrpc_put_connection(conn); 485 486 if (ret < 0) { 487 printk("kAFS: Unable to create call: %d\n", ret); 488 _leave(" = %d", ret); 489 return ret; 490 } 491 492 op->call->app_opcode = VLGETENTRYBYID; 493 op->call->app_user = op; 494 495 call = op->call; 496 rxrpc_get_call(call); 497 498 /* send event notifications from the call to kafsasyncd */ 499 afs_kafsasyncd_begin_op(op); 500 501 /* marshall the parameters */ 502 param[0] = htonl(VLGETENTRYBYID); 503 param[1] = htonl(volid); 504 param[2] = htonl(voltype); 505 506 piov[0].iov_len = sizeof(param); 507 piov[0].iov_base = param; 508 509 /* allocate result read buffer in scratch space */ 510 call->app_scr_ptr = rxrpc_call_alloc_scratch(op->call, 384); 511 512 /* send the parameters to the server */ 513 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, 514 0, &sent); 515 if (ret < 0) { 516 rxrpc_call_abort(call, ret); /* handle from kafsasyncd */ 517 ret = 0; 518 goto out; 519 } 520 521 /* wait for the reply to completely arrive */ 522 ret = rxrpc_call_read_data(call, call->app_scr_ptr, 384, 0); 523 switch (ret) { 524 case 0: 525 case -EAGAIN: 526 case -ECONNABORTED: 527 ret = 0; 528 break; /* all handled by kafsasyncd */ 529 530 default: 531 rxrpc_call_abort(call, ret); /* make kafsasyncd handle it */ 532 ret = 0; 533 break; 534 } 535 536 out: 537 rxrpc_put_call(call); 538 _leave(" = %d", ret); 539 return ret; 540 541 } /* end afs_rxvl_get_entry_by_id_async() */ 542 543 /*****************************************************************************/ 544 /* 545 * attend to the asynchronous get VLDB entry by ID 546 */ 547 int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *op, 548 struct afs_cache_vlocation *entry) 549 { 550 __be32 *bp; 551 __u32 tmp; 552 int loop, ret; 553 554 _enter("{op=%p cst=%u}", op, op->call->app_call_state); 555 556 memset(entry, 0, sizeof(*entry)); 557 558 if (op->call->app_call_state == RXRPC_CSTATE_COMPLETE) { 559 /* operation finished */ 560 afs_kafsasyncd_terminate_op(op); 561 562 bp = op->call->app_scr_ptr; 563 564 /* unmarshall the reply */ 565 for (loop = 0; loop < 64; loop++) 566 entry->name[loop] = ntohl(*bp++); 567 bp++; /* final NUL */ 568 569 bp++; /* type */ 570 entry->nservers = ntohl(*bp++); 571 572 for (loop = 0; loop < 8; loop++) 573 entry->servers[loop].s_addr = *bp++; 574 575 bp += 8; /* partition IDs */ 576 577 for (loop = 0; loop < 8; loop++) { 578 tmp = ntohl(*bp++); 579 if (tmp & AFS_VLSF_RWVOL) 580 entry->srvtmask[loop] |= AFS_VOL_VTM_RW; 581 if (tmp & AFS_VLSF_ROVOL) 582 entry->srvtmask[loop] |= AFS_VOL_VTM_RO; 583 if (tmp & AFS_VLSF_BACKVOL) 584 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK; 585 } 586 587 entry->vid[0] = ntohl(*bp++); 588 entry->vid[1] = ntohl(*bp++); 589 entry->vid[2] = ntohl(*bp++); 590 591 bp++; /* clone ID */ 592 593 tmp = ntohl(*bp++); /* flags */ 594 if (tmp & AFS_VLF_RWEXISTS) 595 entry->vidmask |= AFS_VOL_VTM_RW; 596 if (tmp & AFS_VLF_ROEXISTS) 597 entry->vidmask |= AFS_VOL_VTM_RO; 598 if (tmp & AFS_VLF_BACKEXISTS) 599 entry->vidmask |= AFS_VOL_VTM_BAK; 600 601 ret = -ENOMEDIUM; 602 if (!entry->vidmask) { 603 rxrpc_call_abort(op->call, ret); 604 goto done; 605 } 606 607 #if 0 /* TODO: remove */ 608 entry->nservers = 3; 609 entry->servers[0].s_addr = htonl(0xac101249); 610 entry->servers[1].s_addr = htonl(0xac101243); 611 entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/); 612 613 entry->srvtmask[0] = AFS_VOL_VTM_RO; 614 entry->srvtmask[1] = AFS_VOL_VTM_RO; 615 entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW; 616 #endif 617 618 /* success */ 619 entry->rtime = get_seconds(); 620 ret = 0; 621 goto done; 622 } 623 624 if (op->call->app_call_state == RXRPC_CSTATE_ERROR) { 625 /* operation error */ 626 ret = op->call->app_errno; 627 goto done; 628 } 629 630 _leave(" = -EAGAIN"); 631 return -EAGAIN; 632 633 done: 634 rxrpc_put_call(op->call); 635 op->call = NULL; 636 _leave(" = %d", ret); 637 return ret; 638 } /* end afs_rxvl_get_entry_by_id_async2() */ 639 640 /*****************************************************************************/ 641 /* 642 * handle attention events on an async get-entry-by-ID op 643 * - called from krxiod 644 */ 645 static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call) 646 { 647 struct afs_async_op *op = call->app_user; 648 649 _enter("{op=%p cst=%u}", op, call->app_call_state); 650 651 switch (call->app_call_state) { 652 case RXRPC_CSTATE_COMPLETE: 653 afs_kafsasyncd_attend_op(op); 654 break; 655 case RXRPC_CSTATE_CLNT_RCV_REPLY: 656 if (call->app_async_read) 657 break; 658 case RXRPC_CSTATE_CLNT_GOT_REPLY: 659 if (call->app_read_count == 0) 660 break; 661 printk("kAFS: Reply bigger than expected" 662 " {cst=%u asyn=%d mark=%Zu rdy=%Zu pr=%u%s}", 663 call->app_call_state, 664 call->app_async_read, 665 call->app_mark, 666 call->app_ready_qty, 667 call->pkt_rcv_count, 668 call->app_last_rcv ? " last" : ""); 669 670 rxrpc_call_abort(call, -EBADMSG); 671 break; 672 default: 673 BUG(); 674 } 675 676 _leave(""); 677 678 } /* end afs_rxvl_get_entry_by_id_attn() */ 679 680 /*****************************************************************************/ 681 /* 682 * handle error events on an async get-entry-by-ID op 683 * - called from krxiod 684 */ 685 static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call) 686 { 687 struct afs_async_op *op = call->app_user; 688 689 _enter("{op=%p cst=%u}", op, call->app_call_state); 690 691 afs_kafsasyncd_attend_op(op); 692 693 _leave(""); 694 695 } /* end afs_rxvl_get_entry_by_id_error() */ 696