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 32 /*****************************************************************************/ 33 /* 34 * map afs abort codes to/from Linux error codes 35 * - called with call->lock held 36 */ 37 static void afs_rxfs_aemap(struct rxrpc_call *call) 38 { 39 switch (call->app_err_state) { 40 case RXRPC_ESTATE_LOCAL_ABORT: 41 call->app_abort_code = -call->app_errno; 42 break; 43 case RXRPC_ESTATE_PEER_ABORT: 44 call->app_errno = afs_abort_to_error(call->app_abort_code); 45 break; 46 default: 47 break; 48 } 49 } /* end afs_rxfs_aemap() */ 50 51 /*****************************************************************************/ 52 /* 53 * get the root volume name from a fileserver 54 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2 55 */ 56 #if 0 57 int afs_rxfs_get_root_volume(struct afs_server *server, 58 char *buf, size_t *buflen) 59 { 60 struct rxrpc_connection *conn; 61 struct rxrpc_call *call; 62 struct kvec piov[2]; 63 size_t sent; 64 int ret; 65 u32 param[1]; 66 67 DECLARE_WAITQUEUE(myself, current); 68 69 kenter("%p,%p,%u",server, buf, *buflen); 70 71 /* get hold of the fileserver connection */ 72 ret = afs_server_get_fsconn(server, &conn); 73 if (ret < 0) 74 goto out; 75 76 /* create a call through that connection */ 77 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); 78 if (ret < 0) { 79 printk("kAFS: Unable to create call: %d\n", ret); 80 goto out_put_conn; 81 } 82 call->app_opcode = FSGETROOTVOLUME; 83 84 /* we want to get event notifications from the call */ 85 add_wait_queue(&call->waitq, &myself); 86 87 /* marshall the parameters */ 88 param[0] = htonl(FSGETROOTVOLUME); 89 90 piov[0].iov_len = sizeof(param); 91 piov[0].iov_base = param; 92 93 /* send the parameters to the server */ 94 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, 95 0, &sent); 96 if (ret < 0) 97 goto abort; 98 99 /* wait for the reply to completely arrive */ 100 for (;;) { 101 set_current_state(TASK_INTERRUPTIBLE); 102 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY || 103 signal_pending(current)) 104 break; 105 schedule(); 106 } 107 set_current_state(TASK_RUNNING); 108 109 ret = -EINTR; 110 if (signal_pending(current)) 111 goto abort; 112 113 switch (call->app_call_state) { 114 case RXRPC_CSTATE_ERROR: 115 ret = call->app_errno; 116 kdebug("Got Error: %d", ret); 117 goto out_unwait; 118 119 case RXRPC_CSTATE_CLNT_GOT_REPLY: 120 /* read the reply */ 121 kdebug("Got Reply: qty=%d", call->app_ready_qty); 122 123 ret = -EBADMSG; 124 if (call->app_ready_qty <= 4) 125 goto abort; 126 127 ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0); 128 if (ret < 0) 129 goto abort; 130 131 #if 0 132 /* unmarshall the reply */ 133 bp = buffer; 134 for (loop = 0; loop < 65; loop++) 135 entry->name[loop] = ntohl(*bp++); 136 entry->name[64] = 0; 137 138 entry->type = ntohl(*bp++); 139 entry->num_servers = ntohl(*bp++); 140 141 for (loop = 0; loop < 8; loop++) 142 entry->servers[loop].addr.s_addr = *bp++; 143 144 for (loop = 0; loop < 8; loop++) 145 entry->servers[loop].partition = ntohl(*bp++); 146 147 for (loop = 0; loop < 8; loop++) 148 entry->servers[loop].flags = ntohl(*bp++); 149 150 for (loop = 0; loop < 3; loop++) 151 entry->volume_ids[loop] = ntohl(*bp++); 152 153 entry->clone_id = ntohl(*bp++); 154 entry->flags = ntohl(*bp); 155 #endif 156 157 /* success */ 158 ret = 0; 159 goto out_unwait; 160 161 default: 162 BUG(); 163 } 164 165 abort: 166 set_current_state(TASK_UNINTERRUPTIBLE); 167 rxrpc_call_abort(call, ret); 168 schedule(); 169 out_unwait: 170 set_current_state(TASK_RUNNING); 171 remove_wait_queue(&call->waitq, &myself); 172 rxrpc_put_call(call); 173 out_put_conn: 174 afs_server_release_fsconn(server, conn); 175 out: 176 kleave(""); 177 return ret; 178 } /* end afs_rxfs_get_root_volume() */ 179 #endif 180 181 /*****************************************************************************/ 182 /* 183 * get information about a volume 184 */ 185 #if 0 186 int afs_rxfs_get_volume_info(struct afs_server *server, 187 const char *name, 188 struct afs_volume_info *vinfo) 189 { 190 struct rxrpc_connection *conn; 191 struct rxrpc_call *call; 192 struct kvec piov[3]; 193 size_t sent; 194 int ret; 195 u32 param[2], *bp, zero; 196 197 DECLARE_WAITQUEUE(myself, current); 198 199 _enter("%p,%s,%p", server, name, vinfo); 200 201 /* get hold of the fileserver connection */ 202 ret = afs_server_get_fsconn(server, &conn); 203 if (ret < 0) 204 goto out; 205 206 /* create a call through that connection */ 207 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); 208 if (ret < 0) { 209 printk("kAFS: Unable to create call: %d\n", ret); 210 goto out_put_conn; 211 } 212 call->app_opcode = FSGETVOLUMEINFO; 213 214 /* we want to get event notifications from the call */ 215 add_wait_queue(&call->waitq, &myself); 216 217 /* marshall the parameters */ 218 piov[1].iov_len = strlen(name); 219 piov[1].iov_base = (char *) name; 220 221 zero = 0; 222 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; 223 piov[2].iov_base = &zero; 224 225 param[0] = htonl(FSGETVOLUMEINFO); 226 param[1] = htonl(piov[1].iov_len); 227 228 piov[0].iov_len = sizeof(param); 229 piov[0].iov_base = param; 230 231 /* send the parameters to the server */ 232 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, 233 0, &sent); 234 if (ret < 0) 235 goto abort; 236 237 /* wait for the reply to completely arrive */ 238 bp = rxrpc_call_alloc_scratch(call, 64); 239 240 ret = rxrpc_call_read_data(call, bp, 64, 241 RXRPC_CALL_READ_BLOCK | 242 RXRPC_CALL_READ_ALL); 243 if (ret < 0) { 244 if (ret == -ECONNABORTED) { 245 ret = call->app_errno; 246 goto out_unwait; 247 } 248 goto abort; 249 } 250 251 /* unmarshall the reply */ 252 vinfo->vid = ntohl(*bp++); 253 vinfo->type = ntohl(*bp++); 254 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++); 260 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++; 270 271 ret = -EBADMSG; 272 if (vinfo->nservers > 8) 273 goto abort; 274 275 /* success */ 276 ret = 0; 277 278 out_unwait: 279 set_current_state(TASK_RUNNING); 280 remove_wait_queue(&call->waitq, &myself); 281 rxrpc_put_call(call); 282 out_put_conn: 283 afs_server_release_fsconn(server, conn); 284 out: 285 _leave(""); 286 return ret; 287 288 abort: 289 set_current_state(TASK_UNINTERRUPTIBLE); 290 rxrpc_call_abort(call, ret); 291 schedule(); 292 goto out_unwait; 293 294 } /* end afs_rxfs_get_volume_info() */ 295 #endif 296 297 /*****************************************************************************/ 298 /* 299 * fetch the status information for a file 300 */ 301 int afs_rxfs_fetch_file_status(struct afs_server *server, 302 struct afs_vnode *vnode, 303 struct afs_volsync *volsync) 304 { 305 struct afs_server_callslot callslot; 306 struct rxrpc_call *call; 307 struct kvec piov[1]; 308 size_t sent; 309 int ret; 310 __be32 *bp; 311 312 DECLARE_WAITQUEUE(myself, current); 313 314 _enter("%p,{%u,%u,%u}", 315 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); 316 317 /* get hold of the fileserver connection */ 318 ret = afs_server_request_callslot(server, &callslot); 319 if (ret < 0) 320 goto out; 321 322 /* create a call through that connection */ 323 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, 324 &call); 325 if (ret < 0) { 326 printk("kAFS: Unable to create call: %d\n", ret); 327 goto out_put_conn; 328 } 329 call->app_opcode = FSFETCHSTATUS; 330 331 /* we want to get event notifications from the call */ 332 add_wait_queue(&call->waitq, &myself); 333 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); 340 341 piov[0].iov_len = 16; 342 piov[0].iov_base = bp; 343 344 /* send the parameters to the server */ 345 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, 346 0, &sent); 347 if (ret < 0) 348 goto abort; 349 350 /* wait for the reply to completely arrive */ 351 bp = rxrpc_call_alloc_scratch(call, 120); 352 353 ret = rxrpc_call_read_data(call, bp, 120, 354 RXRPC_CALL_READ_BLOCK | 355 RXRPC_CALL_READ_ALL); 356 if (ret < 0) { 357 if (ret == -ECONNABORTED) { 358 ret = call->app_errno; 359 goto out_unwait; 360 } 361 goto abort; 362 } 363 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++); 378 bp++; /* seg size */ 379 vnode->status.mtime_client = ntohl(*bp++); 380 vnode->status.mtime_server = ntohl(*bp++); 381 bp++; /* group */ 382 bp++; /* sync counter */ 383 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; 384 bp++; /* spare2 */ 385 bp++; /* spare3 */ 386 bp++; /* spare4 */ 387 388 vnode->cb_version = ntohl(*bp++); 389 vnode->cb_expiry = ntohl(*bp++); 390 vnode->cb_type = ntohl(*bp++); 391 392 if (volsync) { 393 volsync->creation = ntohl(*bp++); 394 bp++; /* spare2 */ 395 bp++; /* spare3 */ 396 bp++; /* spare4 */ 397 bp++; /* spare5 */ 398 bp++; /* spare6 */ 399 } 400 401 /* success */ 402 ret = 0; 403 404 out_unwait: 405 set_current_state(TASK_RUNNING); 406 remove_wait_queue(&call->waitq, &myself); 407 rxrpc_put_call(call); 408 out_put_conn: 409 afs_server_release_callslot(server, &callslot); 410 out: 411 _leave(""); 412 return ret; 413 414 abort: 415 set_current_state(TASK_UNINTERRUPTIBLE); 416 rxrpc_call_abort(call, ret); 417 schedule(); 418 goto out_unwait; 419 } /* end afs_rxfs_fetch_file_status() */ 420 421 /*****************************************************************************/ 422 /* 423 * fetch the contents of a file or directory 424 */ 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) 429 { 430 struct afs_server_callslot callslot; 431 struct rxrpc_call *call; 432 struct kvec piov[1]; 433 size_t sent; 434 int ret; 435 __be32 *bp; 436 437 DECLARE_WAITQUEUE(myself, current); 438 439 _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}", 440 server, 441 desc->fid.vid, 442 desc->fid.vnode, 443 desc->fid.unique, 444 desc->size, 445 desc->offset); 446 447 /* get hold of the fileserver connection */ 448 ret = afs_server_request_callslot(server, &callslot); 449 if (ret < 0) 450 goto out; 451 452 /* create a call through that connection */ 453 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call); 454 if (ret < 0) { 455 printk("kAFS: Unable to create call: %d\n", ret); 456 goto out_put_conn; 457 } 458 call->app_opcode = FSFETCHDATA; 459 460 /* we want to get event notifications from the call */ 461 add_wait_queue(&call->waitq, &myself); 462 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); 471 472 piov[0].iov_len = 24; 473 piov[0].iov_base = bp; 474 475 /* send the parameters to the server */ 476 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, 477 0, &sent); 478 if (ret < 0) 479 goto abort; 480 481 /* wait for the data count to arrive */ 482 ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK); 483 if (ret < 0) 484 goto read_failed; 485 486 desc->actual = ntohl(bp[0]); 487 if (desc->actual != desc->size) { 488 ret = -EBADMSG; 489 goto abort; 490 } 491 492 /* call the app to read the actual data */ 493 rxrpc_call_reset_scratch(call); 494 495 ret = rxrpc_call_read_data(call, desc->buffer, desc->actual, 496 RXRPC_CALL_READ_BLOCK); 497 if (ret < 0) 498 goto read_failed; 499 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); 503 504 ret = rxrpc_call_read_data(call, bp, 120, 505 RXRPC_CALL_READ_BLOCK | 506 RXRPC_CALL_READ_ALL); 507 if (ret < 0) 508 goto read_failed; 509 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++); 524 bp++; /* seg size */ 525 vnode->status.mtime_client = ntohl(*bp++); 526 vnode->status.mtime_server = ntohl(*bp++); 527 bp++; /* group */ 528 bp++; /* sync counter */ 529 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; 530 bp++; /* spare2 */ 531 bp++; /* spare3 */ 532 bp++; /* spare4 */ 533 534 vnode->cb_version = ntohl(*bp++); 535 vnode->cb_expiry = ntohl(*bp++); 536 vnode->cb_type = ntohl(*bp++); 537 538 if (volsync) { 539 volsync->creation = ntohl(*bp++); 540 bp++; /* spare2 */ 541 bp++; /* spare3 */ 542 bp++; /* spare4 */ 543 bp++; /* spare5 */ 544 bp++; /* spare6 */ 545 } 546 547 /* success */ 548 ret = 0; 549 550 out_unwait: 551 set_current_state(TASK_RUNNING); 552 remove_wait_queue(&call->waitq,&myself); 553 rxrpc_put_call(call); 554 out_put_conn: 555 afs_server_release_callslot(server, &callslot); 556 out: 557 _leave(" = %d", ret); 558 return ret; 559 560 read_failed: 561 if (ret == -ECONNABORTED) { 562 ret = call->app_errno; 563 goto out_unwait; 564 } 565 566 abort: 567 set_current_state(TASK_UNINTERRUPTIBLE); 568 rxrpc_call_abort(call, ret); 569 schedule(); 570 goto out_unwait; 571 572 } /* end afs_rxfs_fetch_file_data() */ 573 574 /*****************************************************************************/ 575 /* 576 * ask the AFS fileserver to discard a callback request on a file 577 */ 578 int afs_rxfs_give_up_callback(struct afs_server *server, 579 struct afs_vnode *vnode) 580 { 581 struct afs_server_callslot callslot; 582 struct rxrpc_call *call; 583 struct kvec piov[1]; 584 size_t sent; 585 int ret; 586 __be32 *bp; 587 588 DECLARE_WAITQUEUE(myself, current); 589 590 _enter("%p,{%u,%u,%u}", 591 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); 592 593 /* get hold of the fileserver connection */ 594 ret = afs_server_request_callslot(server, &callslot); 595 if (ret < 0) 596 goto out; 597 598 /* create a call through that connection */ 599 ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call); 600 if (ret < 0) { 601 printk("kAFS: Unable to create call: %d\n", ret); 602 goto out_put_conn; 603 } 604 call->app_opcode = FSGIVEUPCALLBACKS; 605 606 /* we want to get event notifications from the call */ 607 add_wait_queue(&call->waitq, &myself); 608 609 /* marshall the parameters */ 610 bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4); 611 612 piov[0].iov_len = (1 + 4 + 4) * 4; 613 piov[0].iov_base = bp; 614 615 *bp++ = htonl(FSGIVEUPCALLBACKS); 616 *bp++ = htonl(1); 617 *bp++ = htonl(vnode->fid.vid); 618 *bp++ = htonl(vnode->fid.vnode); 619 *bp++ = htonl(vnode->fid.unique); 620 *bp++ = htonl(1); 621 *bp++ = htonl(vnode->cb_version); 622 *bp++ = htonl(vnode->cb_expiry); 623 *bp++ = htonl(vnode->cb_type); 624 625 /* send the parameters to the server */ 626 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, 627 0, &sent); 628 if (ret < 0) 629 goto abort; 630 631 /* wait for the reply to completely arrive */ 632 for (;;) { 633 set_current_state(TASK_INTERRUPTIBLE); 634 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY || 635 signal_pending(current)) 636 break; 637 schedule(); 638 } 639 set_current_state(TASK_RUNNING); 640 641 ret = -EINTR; 642 if (signal_pending(current)) 643 goto abort; 644 645 switch (call->app_call_state) { 646 case RXRPC_CSTATE_ERROR: 647 ret = call->app_errno; 648 goto out_unwait; 649 650 case RXRPC_CSTATE_CLNT_GOT_REPLY: 651 ret = 0; 652 goto out_unwait; 653 654 default: 655 BUG(); 656 } 657 658 out_unwait: 659 set_current_state(TASK_RUNNING); 660 remove_wait_queue(&call->waitq, &myself); 661 rxrpc_put_call(call); 662 out_put_conn: 663 afs_server_release_callslot(server, &callslot); 664 out: 665 _leave(""); 666 return ret; 667 668 abort: 669 set_current_state(TASK_UNINTERRUPTIBLE); 670 rxrpc_call_abort(call, ret); 671 schedule(); 672 goto out_unwait; 673 } /* end afs_rxfs_give_up_callback() */ 674 675 /*****************************************************************************/ 676 /* 677 * look a filename up in a directory 678 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2 679 */ 680 #if 0 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) 686 { 687 struct rxrpc_connection *conn; 688 struct rxrpc_call *call; 689 struct kvec piov[3]; 690 size_t sent; 691 int ret; 692 u32 *bp, zero; 693 694 DECLARE_WAITQUEUE(myself, current); 695 696 kenter("%p,{%u,%u,%u},%s", 697 server, fid->vid, fid->vnode, fid->unique, filename); 698 699 /* get hold of the fileserver connection */ 700 ret = afs_server_get_fsconn(server, &conn); 701 if (ret < 0) 702 goto out; 703 704 /* create a call through that connection */ 705 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); 706 if (ret < 0) { 707 printk("kAFS: Unable to create call: %d\n", ret); 708 goto out_put_conn; 709 } 710 call->app_opcode = FSLOOKUP; 711 712 /* we want to get event notifications from the call */ 713 add_wait_queue(&call->waitq,&myself); 714 715 /* marshall the parameters */ 716 bp = rxrpc_call_alloc_scratch(call, 20); 717 718 zero = 0; 719 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; 726 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); 732 733 /* send the parameters to the server */ 734 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, 735 0, &sent); 736 if (ret < 0) 737 goto abort; 738 739 /* wait for the reply to completely arrive */ 740 bp = rxrpc_call_alloc_scratch(call, 220); 741 742 ret = rxrpc_call_read_data(call, bp, 220, 743 RXRPC_CALL_READ_BLOCK | 744 RXRPC_CALL_READ_ALL); 745 if (ret < 0) { 746 if (ret == -ECONNABORTED) { 747 ret = call->app_errno; 748 goto out_unwait; 749 } 750 goto abort; 751 } 752 753 /* unmarshall the reply */ 754 fid->vid = ntohl(*bp++); 755 fid->vnode = ntohl(*bp++); 756 fid->unique = ntohl(*bp++); 757 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++); 771 bp++; /* seg size */ 772 vnode->status.mtime_client = ntohl(*bp++); 773 vnode->status.mtime_server = ntohl(*bp++); 774 bp++; /* group */ 775 bp++; /* sync counter */ 776 vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; 777 bp++; /* spare2 */ 778 bp++; /* spare3 */ 779 bp++; /* spare4 */ 780 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++); 794 bp++; /* seg size */ 795 dir->status.mtime_client = ntohl(*bp++); 796 dir->status.mtime_server = ntohl(*bp++); 797 bp++; /* group */ 798 bp++; /* sync counter */ 799 dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; 800 bp++; /* spare2 */ 801 bp++; /* spare3 */ 802 bp++; /* spare4 */ 803 804 callback->fid = *fid; 805 callback->version = ntohl(*bp++); 806 callback->expiry = ntohl(*bp++); 807 callback->type = ntohl(*bp++); 808 809 if (volsync) { 810 volsync->creation = ntohl(*bp++); 811 bp++; /* spare2 */ 812 bp++; /* spare3 */ 813 bp++; /* spare4 */ 814 bp++; /* spare5 */ 815 bp++; /* spare6 */ 816 } 817 818 /* success */ 819 ret = 0; 820 821 out_unwait: 822 set_current_state(TASK_RUNNING); 823 remove_wait_queue(&call->waitq, &myself); 824 rxrpc_put_call(call); 825 out_put_conn: 826 afs_server_release_fsconn(server, conn); 827 out: 828 kleave(""); 829 return ret; 830 831 abort: 832 set_current_state(TASK_UNINTERRUPTIBLE); 833 rxrpc_call_abort(call, ret); 834 schedule(); 835 goto out_unwait; 836 } /* end afs_rxfs_lookup() */ 837 #endif 838