1 /* 2 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "Compatibility.h" 7 #include "Debug.h" 8 #include "FileSystem.h" 9 #include "KernelRequestHandler.h" 10 #include "RequestPort.h" 11 #include "Requests.h" 12 #include "SingleReplyRequestHandler.h" 13 #include "Volume.h" 14 15 #include <NodeMonitor.h> 16 17 #include <AutoDeleter.h> 18 19 20 // VolumePutter 21 class VolumePutter { 22 public: 23 VolumePutter(Volume* volume) : fVolume(volume) {} 24 ~VolumePutter() 25 { 26 if (fVolume) 27 fVolume->RemoveReference(); 28 } 29 30 private: 31 Volume *fVolume; 32 }; 33 34 // constructor 35 KernelRequestHandler::KernelRequestHandler(Volume* volume, uint32 expectedReply) 36 : RequestHandler(), 37 fFileSystem(volume->GetFileSystem()), 38 fVolume(volume), 39 fExpectedReply(expectedReply) 40 { 41 } 42 43 // constructor 44 KernelRequestHandler::KernelRequestHandler(FileSystem* fileSystem, 45 uint32 expectedReply) 46 : RequestHandler(), 47 fFileSystem(fileSystem), 48 fVolume(NULL), 49 fExpectedReply(expectedReply) 50 { 51 } 52 53 // destructor 54 KernelRequestHandler::~KernelRequestHandler() 55 { 56 } 57 58 // HandleRequest 59 status_t 60 KernelRequestHandler::HandleRequest(Request* request) 61 { 62 if (request->GetType() == fExpectedReply) { 63 fDone = true; 64 return B_OK; 65 } 66 switch (request->GetType()) { 67 // notifications 68 case NOTIFY_LISTENER_REQUEST: 69 return _HandleRequest((NotifyListenerRequest*)request); 70 case NOTIFY_SELECT_EVENT_REQUEST: 71 return _HandleRequest((NotifySelectEventRequest*)request); 72 case NOTIFY_QUERY_REQUEST: 73 return _HandleRequest((NotifyQueryRequest*)request); 74 // vnodes 75 case GET_VNODE_REQUEST: 76 return _HandleRequest((GetVNodeRequest*)request); 77 case PUT_VNODE_REQUEST: 78 return _HandleRequest((PutVNodeRequest*)request); 79 case ACQUIRE_VNODE_REQUEST: 80 return _HandleRequest((AcquireVNodeRequest*)request); 81 case NEW_VNODE_REQUEST: 82 return _HandleRequest((NewVNodeRequest*)request); 83 case PUBLISH_VNODE_REQUEST: 84 return _HandleRequest((PublishVNodeRequest*)request); 85 case REMOVE_VNODE_REQUEST: 86 return _HandleRequest((RemoveVNodeRequest*)request); 87 case UNREMOVE_VNODE_REQUEST: 88 return _HandleRequest((UnremoveVNodeRequest*)request); 89 case GET_VNODE_REMOVED_REQUEST: 90 return _HandleRequest((GetVNodeRemovedRequest*)request); 91 // file cache 92 case FILE_CACHE_CREATE_REQUEST: 93 return _HandleRequest((FileCacheCreateRequest*)request); 94 case FILE_CACHE_DELETE_REQUEST: 95 return _HandleRequest((FileCacheDeleteRequest*)request); 96 case FILE_CACHE_SET_ENABLED_REQUEST: 97 return _HandleRequest((FileCacheSetEnabledRequest*)request); 98 case FILE_CACHE_SET_SIZE_REQUEST: 99 return _HandleRequest((FileCacheSetSizeRequest*)request); 100 case FILE_CACHE_SYNC_REQUEST: 101 return _HandleRequest((FileCacheSyncRequest*)request); 102 case FILE_CACHE_READ_REQUEST: 103 return _HandleRequest((FileCacheReadRequest*)request); 104 case FILE_CACHE_WRITE_REQUEST: 105 return _HandleRequest((FileCacheWriteRequest*)request); 106 // I/O 107 case DO_ITERATIVE_FD_IO_REQUEST: 108 return _HandleRequest((DoIterativeFDIORequest*)request); 109 case NOTIFY_IO_REQUEST_REQUEST: 110 return _HandleRequest((NotifyIORequestRequest*)request); 111 } 112 PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %lu\n", 113 request->GetType())); 114 return B_BAD_DATA; 115 } 116 117 // #pragma mark - 118 // #pragma mark ----- notifications ----- 119 120 // _HandleRequest 121 status_t 122 KernelRequestHandler::_HandleRequest(NotifyListenerRequest* request) 123 { 124 // check and execute the request 125 status_t result = B_OK; 126 if (fVolume && request->device != fVolume->GetID()) 127 result = B_BAD_VALUE; 128 129 // get the names 130 // name 131 char* name = (char*)request->name.GetData(); 132 int32 nameLen = request->name.GetSize(); 133 if (name && (nameLen <= 0)) 134 name = NULL; 135 else if (name) 136 name[nameLen - 1] = '\0'; // NULL-terminate to be safe 137 138 // old name 139 char* oldName = (char*)request->oldName.GetData(); 140 int32 oldNameLen = request->oldName.GetSize(); 141 if (oldName && (oldNameLen <= 0)) 142 oldName = NULL; 143 else if (oldName) 144 oldName[oldNameLen - 1] = '\0'; // NULL-terminate to be safe 145 146 // check the names 147 if (result == B_OK) { 148 switch (request->operation) { 149 case B_ENTRY_MOVED: 150 if (!oldName) { 151 ERROR(("NotifyListenerRequest: NULL oldName for " 152 "B_ENTRY_MOVED\n")); 153 result = B_BAD_VALUE; 154 break; 155 } 156 // fall through... 157 case B_ENTRY_CREATED: 158 case B_ENTRY_REMOVED: 159 case B_ATTR_CHANGED: 160 if (!name) { 161 ERROR(("NotifyListenerRequest: NULL name for opcode: %ld\n", 162 request->operation)); 163 result = B_BAD_VALUE; 164 } 165 break; 166 case B_STAT_CHANGED: 167 break; 168 } 169 } 170 171 // execute the request 172 if (result == B_OK) { 173 switch (request->operation) { 174 case B_ENTRY_CREATED: 175 PRINT(("notify_entry_created(%ld, %lld, \"%s\", %lld)\n", 176 request->device, request->directory, name, request->node)); 177 result = notify_entry_created(request->device, 178 request->directory, name, request->node); 179 break; 180 181 case B_ENTRY_REMOVED: 182 PRINT(("notify_entry_removed(%ld, %lld, \"%s\", %lld)\n", 183 request->device, request->directory, name, request->node)); 184 result = notify_entry_removed(request->device, 185 request->directory, name, request->node); 186 break; 187 188 case B_ENTRY_MOVED: 189 PRINT(("notify_entry_moved(%ld, %lld, \"%s\", %lld, \"%s\", " 190 "%lld)\n", request->device, request->oldDirectory, oldName, 191 request->directory, name, request->node)); 192 result = notify_entry_moved(request->device, 193 request->oldDirectory, oldName, request->directory, name, 194 request->node); 195 break; 196 197 case B_STAT_CHANGED: 198 PRINT(("notify_stat_changed(%ld, %lld, 0x%lx)\n", 199 request->device, request->node, request->details)); 200 result = notify_stat_changed(request->device, request->node, 201 request->details); 202 break; 203 204 case B_ATTR_CHANGED: 205 PRINT(("notify_attribute_changed(%ld, %lld, \"%s\", 0x%lx)\n", 206 request->device, request->node, name, 207 (int32)request->details)); 208 result = notify_attribute_changed(request->device, 209 request->node, name, (int32)request->details); 210 break; 211 212 default: 213 ERROR(("NotifyQueryRequest: unsupported operation: %ld\n", 214 request->operation)); 215 result = B_BAD_VALUE; 216 break; 217 } 218 } 219 220 // prepare the reply 221 RequestAllocator allocator(fPort->GetPort()); 222 NotifyListenerReply* reply; 223 status_t error = AllocateRequest(allocator, &reply); 224 if (error != B_OK) 225 return error; 226 227 reply->error = result; 228 229 // send the reply 230 return fPort->SendRequest(&allocator); 231 } 232 233 // _HandleRequest 234 status_t 235 KernelRequestHandler::_HandleRequest(NotifySelectEventRequest* request) 236 { 237 // check and execute the request 238 status_t result = B_OK; 239 if (fFileSystem->KnowsSelectSyncEntry(request->sync)) { 240 if (request->unspecifiedEvent) { 241 // old style add-ons can't provide an event argument; we shoot 242 // all events 243 notify_select_event(request->sync, B_SELECT_READ); 244 notify_select_event(request->sync, B_SELECT_WRITE); 245 notify_select_event(request->sync, B_SELECT_ERROR); 246 } else { 247 PRINT(("notify_select_event(%p, %d)\n", request->sync, 248 (int)request->event)); 249 notify_select_event(request->sync, request->event); 250 } 251 } else 252 result = B_BAD_VALUE; 253 254 // prepare the reply 255 RequestAllocator allocator(fPort->GetPort()); 256 NotifySelectEventReply* reply; 257 status_t error = AllocateRequest(allocator, &reply); 258 if (error != B_OK) 259 return error; 260 261 reply->error = result; 262 263 // send the reply 264 return fPort->SendRequest(&allocator); 265 } 266 267 // _HandleRequest 268 status_t 269 KernelRequestHandler::_HandleRequest(NotifyQueryRequest* request) 270 { 271 // check and execute the request 272 status_t result = B_OK; 273 if (fVolume && request->device != fVolume->GetID()) 274 result = B_BAD_VALUE; 275 276 // check the name 277 char* name = (char*)request->name.GetData(); 278 int32 nameLen = request->name.GetSize(); 279 if (!name || nameLen <= 0) { 280 ERROR(("NotifyQueryRequest: NULL name!\n")); 281 result = B_BAD_VALUE; 282 } else 283 name[nameLen - 1] = '\0'; // NULL-terminate to be safe 284 285 // execute the request 286 if (result == B_OK) { 287 switch (request->operation) { 288 case B_ENTRY_CREATED: 289 PRINT(("notify_query_entry_created(%ld, %ld, %ld, %lld," 290 " \"%s\", %lld)\n", request->port, request->token, 291 request->device, request->directory, name, request->node)); 292 result = notify_query_entry_created(request->port, 293 request->token, request->device, request->directory, name, 294 request->node); 295 break; 296 297 case B_ENTRY_REMOVED: 298 PRINT(("notify_query_entry_removed(%ld, %ld, %ld, %lld," 299 " \"%s\", %lld)\n", request->port, request->token, 300 request->device, request->directory, name, request->node)); 301 result = notify_query_entry_removed(request->port, 302 request->token, request->device, request->directory, name, 303 request->node); 304 break; 305 306 case B_ENTRY_MOVED: 307 default: 308 ERROR(("NotifyQueryRequest: unsupported operation: %ld\n", 309 request->operation)); 310 result = B_BAD_VALUE; 311 break; 312 } 313 } 314 315 // prepare the reply 316 RequestAllocator allocator(fPort->GetPort()); 317 NotifyQueryReply* reply; 318 status_t error = AllocateRequest(allocator, &reply); 319 if (error != B_OK) 320 return error; 321 322 reply->error = result; 323 324 // send the reply 325 return fPort->SendRequest(&allocator); 326 } 327 328 // #pragma mark - 329 // #pragma mark ----- vnodes ----- 330 331 // _HandleRequest 332 status_t 333 KernelRequestHandler::_HandleRequest(GetVNodeRequest* request) 334 { 335 // check and execute the request 336 Volume* volume = NULL; 337 status_t result = _GetVolume(request->nsid, &volume); 338 VolumePutter _(volume); 339 void* node; 340 if (result == B_OK) 341 result = volume->GetVNode(request->vnid, &node); 342 // prepare the reply 343 RequestAllocator allocator(fPort->GetPort()); 344 GetVNodeReply* reply; 345 status_t error = AllocateRequest(allocator, &reply); 346 if (error != B_OK) 347 return error; 348 reply->error = result; 349 reply->node = node; 350 // send the reply 351 return fPort->SendRequest(&allocator); 352 } 353 354 // _HandleRequest 355 status_t 356 KernelRequestHandler::_HandleRequest(PutVNodeRequest* request) 357 { 358 // check and execute the request 359 Volume* volume = NULL; 360 status_t result = _GetVolume(request->nsid, &volume); 361 VolumePutter _(volume); 362 if (result == B_OK) 363 result = volume->PutVNode(request->vnid); 364 // prepare the reply 365 RequestAllocator allocator(fPort->GetPort()); 366 PutVNodeReply* reply; 367 status_t error = AllocateRequest(allocator, &reply); 368 if (error != B_OK) 369 return error; 370 reply->error = result; 371 // send the reply 372 return fPort->SendRequest(&allocator); 373 } 374 375 376 // _HandleRequest 377 status_t 378 KernelRequestHandler::_HandleRequest(AcquireVNodeRequest* request) 379 { 380 // check and execute the request 381 Volume* volume = NULL; 382 status_t result = _GetVolume(request->nsid, &volume); 383 VolumePutter _(volume); 384 if (result == B_OK) 385 result = volume->AcquireVNode(request->vnid); 386 387 // prepare the reply 388 RequestAllocator allocator(fPort->GetPort()); 389 AcquireVNodeReply* reply; 390 status_t error = AllocateRequest(allocator, &reply); 391 if (error != B_OK) 392 return error; 393 reply->error = result; 394 395 // send the reply 396 return fPort->SendRequest(&allocator); 397 } 398 399 400 // _HandleRequest 401 status_t 402 KernelRequestHandler::_HandleRequest(NewVNodeRequest* request) 403 { 404 // check and execute the request 405 Volume* volume = NULL; 406 status_t result = _GetVolume(request->nsid, &volume); 407 VolumePutter _(volume); 408 if (result == B_OK) { 409 result = volume->NewVNode(request->vnid, request->node, 410 request->capabilities); 411 } 412 413 // prepare the reply 414 RequestAllocator allocator(fPort->GetPort()); 415 NewVNodeReply* reply; 416 status_t error = AllocateRequest(allocator, &reply); 417 if (error != B_OK) 418 return error; 419 reply->error = result; 420 421 // send the reply 422 return fPort->SendRequest(&allocator); 423 } 424 425 // _HandleRequest 426 status_t 427 KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request) 428 { 429 // check and execute the request 430 Volume* volume = NULL; 431 status_t result = _GetVolume(request->nsid, &volume); 432 VolumePutter _(volume); 433 if (result == B_OK) { 434 result = volume->PublishVNode(request->vnid, request->node, 435 request->type, request->flags, request->capabilities); 436 } 437 438 // prepare the reply 439 RequestAllocator allocator(fPort->GetPort()); 440 PublishVNodeReply* reply; 441 status_t error = AllocateRequest(allocator, &reply); 442 if (error != B_OK) 443 return error; 444 445 reply->error = result; 446 447 // send the reply 448 return fPort->SendRequest(&allocator); 449 } 450 451 // _HandleRequest 452 status_t 453 KernelRequestHandler::_HandleRequest(RemoveVNodeRequest* request) 454 { 455 // check and execute the request 456 Volume* volume = NULL; 457 status_t result = _GetVolume(request->nsid, &volume); 458 VolumePutter _(volume); 459 if (result == B_OK) 460 result = volume->RemoveVNode(request->vnid); 461 // prepare the reply 462 RequestAllocator allocator(fPort->GetPort()); 463 RemoveVNodeReply* reply; 464 status_t error = AllocateRequest(allocator, &reply); 465 if (error != B_OK) 466 return error; 467 reply->error = result; 468 // send the reply 469 return fPort->SendRequest(&allocator); 470 } 471 472 // _HandleRequest 473 status_t 474 KernelRequestHandler::_HandleRequest(UnremoveVNodeRequest* request) 475 { 476 // check and execute the request 477 Volume* volume = NULL; 478 status_t result = _GetVolume(request->nsid, &volume); 479 VolumePutter _(volume); 480 if (result == B_OK) 481 result = volume->UnremoveVNode(request->vnid); 482 // prepare the reply 483 RequestAllocator allocator(fPort->GetPort()); 484 UnremoveVNodeReply* reply; 485 status_t error = AllocateRequest(allocator, &reply); 486 if (error != B_OK) 487 return error; 488 reply->error = result; 489 // send the reply 490 return fPort->SendRequest(&allocator); 491 } 492 493 // _HandleRequest 494 status_t 495 KernelRequestHandler::_HandleRequest(GetVNodeRemovedRequest* request) 496 { 497 // check and execute the request 498 Volume* volume = NULL; 499 status_t result = _GetVolume(request->nsid, &volume); 500 VolumePutter _(volume); 501 bool removed = false; 502 if (result == B_OK) 503 result = volume->GetVNodeRemoved(request->vnid, &removed); 504 505 // prepare the reply 506 RequestAllocator allocator(fPort->GetPort()); 507 GetVNodeRemovedReply* reply; 508 status_t error = AllocateRequest(allocator, &reply); 509 if (error != B_OK) 510 return error; 511 512 reply->error = result; 513 reply->removed = removed; 514 515 // send the reply 516 return fPort->SendRequest(&allocator); 517 } 518 519 520 // _HandleRequest 521 status_t 522 KernelRequestHandler::_HandleRequest(FileCacheCreateRequest* request) 523 { 524 // check and execute the request 525 Volume* volume = NULL; 526 status_t result = _GetVolume(request->nsid, &volume); 527 VolumePutter _(volume); 528 529 if (result == B_OK) 530 result = volume->CreateFileCache(request->vnid, request->size); 531 532 // prepare the reply 533 RequestAllocator allocator(fPort->GetPort()); 534 FileCacheCreateReply* reply; 535 status_t error = AllocateRequest(allocator, &reply); 536 if (error != B_OK) 537 return error; 538 reply->error = result; 539 540 // send the reply 541 return fPort->SendRequest(&allocator); 542 } 543 544 545 // _HandleRequest 546 status_t 547 KernelRequestHandler::_HandleRequest(FileCacheDeleteRequest* request) 548 { 549 // check and execute the request 550 Volume* volume = NULL; 551 status_t result = _GetVolume(request->nsid, &volume); 552 VolumePutter _(volume); 553 554 if (result == B_OK) 555 result = volume->DeleteFileCache(request->vnid); 556 557 // prepare the reply 558 RequestAllocator allocator(fPort->GetPort()); 559 FileCacheDeleteReply* reply; 560 status_t error = AllocateRequest(allocator, &reply); 561 if (error != B_OK) 562 return error; 563 reply->error = result; 564 565 // send the reply 566 return fPort->SendRequest(&allocator); 567 } 568 569 570 // _HandleRequest 571 status_t 572 KernelRequestHandler::_HandleRequest(FileCacheSetEnabledRequest* request) 573 { 574 // check and execute the request 575 Volume* volume = NULL; 576 status_t result = _GetVolume(request->nsid, &volume); 577 VolumePutter _(volume); 578 579 if (result == B_OK) 580 result = volume->SetFileCacheEnabled(request->vnid, request->enabled); 581 582 // prepare the reply 583 RequestAllocator allocator(fPort->GetPort()); 584 FileCacheSetEnabledReply* reply; 585 status_t error = AllocateRequest(allocator, &reply); 586 if (error != B_OK) 587 return error; 588 reply->error = result; 589 590 // send the reply 591 return fPort->SendRequest(&allocator); 592 } 593 594 595 // _HandleRequest 596 status_t 597 KernelRequestHandler::_HandleRequest(FileCacheSetSizeRequest* request) 598 { 599 // check and execute the request 600 Volume* volume = NULL; 601 status_t result = _GetVolume(request->nsid, &volume); 602 VolumePutter _(volume); 603 604 if (result == B_OK) 605 result = volume->SetFileCacheSize(request->vnid, request->size); 606 607 // prepare the reply 608 RequestAllocator allocator(fPort->GetPort()); 609 FileCacheSetSizeReply* reply; 610 status_t error = AllocateRequest(allocator, &reply); 611 if (error != B_OK) 612 return error; 613 reply->error = result; 614 615 // send the reply 616 return fPort->SendRequest(&allocator); 617 } 618 619 620 // _HandleRequest 621 status_t 622 KernelRequestHandler::_HandleRequest(FileCacheSyncRequest* request) 623 { 624 // check and execute the request 625 Volume* volume = NULL; 626 status_t result = _GetVolume(request->nsid, &volume); 627 VolumePutter _(volume); 628 629 if (result == B_OK) 630 result = volume->SyncFileCache(request->vnid); 631 632 // prepare the reply 633 RequestAllocator allocator(fPort->GetPort()); 634 FileCacheSyncReply* reply; 635 status_t error = AllocateRequest(allocator, &reply); 636 if (error != B_OK) 637 return error; 638 reply->error = result; 639 640 // send the reply 641 return fPort->SendRequest(&allocator); 642 } 643 644 645 // _HandleRequest 646 status_t 647 KernelRequestHandler::_HandleRequest(FileCacheReadRequest* request) 648 { 649 // check the request 650 Volume* volume = NULL; 651 status_t result = _GetVolume(request->nsid, &volume); 652 VolumePutter _(volume); 653 654 size_t size = request->size; 655 656 // allocate the reply 657 RequestAllocator allocator(fPort->GetPort()); 658 FileCacheReadReply* reply; 659 status_t error = AllocateRequest(allocator, &reply); 660 if (error != B_OK) 661 RETURN_ERROR(error); 662 663 void* buffer; 664 if (result == B_OK) { 665 result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer, 666 true); 667 } 668 669 // execute the request 670 if (result == B_OK) { 671 result = volume->ReadFileCache(request->vnid, request->cookie, 672 request->pos, buffer, &size); 673 } 674 675 // prepare the reply 676 reply->error = result; 677 reply->bytesRead = size; 678 679 // send the reply 680 if (reply->error == B_OK && reply->bytesRead > 0) { 681 SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY); 682 return fPort->SendRequest(&allocator, &handler); 683 } 684 685 return fPort->SendRequest(&allocator); 686 } 687 688 689 // _HandleRequest 690 status_t 691 KernelRequestHandler::_HandleRequest(FileCacheWriteRequest* request) 692 { 693 // check and execute the request 694 Volume* volume = NULL; 695 status_t result = _GetVolume(request->nsid, &volume); 696 VolumePutter _(volume); 697 698 size_t size = 0; 699 if (result == B_OK) { 700 size = request->buffer.GetSize(); 701 result = volume->WriteFileCache(request->vnid, request->cookie, 702 request->pos, request->buffer.GetData(), &size); 703 } 704 705 // prepare the reply 706 RequestAllocator allocator(fPort->GetPort()); 707 FileCacheWriteReply* reply; 708 status_t error = AllocateRequest(allocator, &reply); 709 if (error != B_OK) 710 return error; 711 reply->error = result; 712 reply->bytesWritten = size; 713 714 // send the reply 715 return fPort->SendRequest(&allocator); 716 } 717 718 719 // _HandleRequest 720 status_t 721 KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request) 722 { 723 // check and execute the request 724 Volume* volume = NULL; 725 status_t result = _GetVolume(request->nsid, &volume); 726 VolumePutter _(volume); 727 728 uint32 vecCount = request->vecCount; 729 if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS) 730 result = B_BAD_VALUE; 731 732 if (result == B_OK) { 733 result = volume->DoIterativeFDIO(request->fd, request->request, 734 request->cookie, request->vecs, vecCount); 735 } 736 737 // prepare the reply 738 RequestAllocator allocator(fPort->GetPort()); 739 DoIterativeFDIOReply* reply; 740 status_t error = AllocateRequest(allocator, &reply); 741 if (error != B_OK) 742 return error; 743 reply->error = result; 744 745 // send the reply 746 return fPort->SendRequest(&allocator); 747 } 748 749 750 // _HandleRequest 751 status_t 752 KernelRequestHandler::_HandleRequest(NotifyIORequestRequest* request) 753 { 754 // check and execute the request 755 Volume* volume = NULL; 756 status_t result = _GetVolume(request->nsid, &volume); 757 VolumePutter _(volume); 758 759 if (result == B_OK) 760 result = volume->NotifyIORequest(request->request, request->status); 761 762 // prepare the reply 763 RequestAllocator allocator(fPort->GetPort()); 764 NotifyIORequestReply* reply; 765 status_t error = AllocateRequest(allocator, &reply); 766 if (error != B_OK) 767 return error; 768 reply->error = result; 769 770 // send the reply 771 return fPort->SendRequest(&allocator); 772 } 773 774 775 // _GetVolume 776 status_t 777 KernelRequestHandler::_GetVolume(dev_t id, Volume** volume) 778 { 779 if (fVolume) { 780 if (fVolume->GetID() != id) { 781 *volume = NULL; 782 return B_BAD_VALUE; 783 } 784 fVolume->AddReference(); 785 *volume = fVolume; 786 return B_OK; 787 } 788 *volume = fFileSystem->GetVolume(id); 789 return (*volume ? B_OK : B_BAD_VALUE); 790 } 791 792