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->ReleaseReference(); 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 READ_FROM_IO_REQUEST_REQUEST: 110 return _HandleRequest((ReadFromIORequestRequest*)request); 111 case WRITE_TO_IO_REQUEST_REQUEST: 112 return _HandleRequest((WriteToIORequestRequest*)request); 113 case NOTIFY_IO_REQUEST_REQUEST: 114 return _HandleRequest((NotifyIORequestRequest*)request); 115 // node monitoring 116 case ADD_NODE_LISTENER_REQUEST: 117 return _HandleRequest((AddNodeListenerRequest*)request); 118 case REMOVE_NODE_LISTENER_REQUEST: 119 return _HandleRequest((RemoveNodeListenerRequest*)request); 120 } 121 PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %lu\n", 122 request->GetType())); 123 return B_BAD_DATA; 124 } 125 126 // #pragma mark - 127 // #pragma mark ----- notifications ----- 128 129 // _HandleRequest 130 status_t 131 KernelRequestHandler::_HandleRequest(NotifyListenerRequest* request) 132 { 133 // check and execute the request 134 status_t result = B_OK; 135 if (fVolume && request->device != fVolume->GetID()) 136 result = B_BAD_VALUE; 137 138 // get the names 139 // name 140 char* name = (char*)request->name.GetData(); 141 int32 nameLen = request->name.GetSize(); 142 if (name && (nameLen <= 0)) 143 name = NULL; 144 else if (name) 145 name[nameLen - 1] = '\0'; // NULL-terminate to be safe 146 147 // old name 148 char* oldName = (char*)request->oldName.GetData(); 149 int32 oldNameLen = request->oldName.GetSize(); 150 if (oldName && (oldNameLen <= 0)) 151 oldName = NULL; 152 else if (oldName) 153 oldName[oldNameLen - 1] = '\0'; // NULL-terminate to be safe 154 155 // check the names 156 if (result == B_OK) { 157 switch (request->operation) { 158 case B_ENTRY_MOVED: 159 if (!oldName) { 160 ERROR(("NotifyListenerRequest: NULL oldName for " 161 "B_ENTRY_MOVED\n")); 162 result = B_BAD_VALUE; 163 break; 164 } 165 // fall through... 166 case B_ENTRY_CREATED: 167 case B_ENTRY_REMOVED: 168 case B_ATTR_CHANGED: 169 if (!name) { 170 ERROR(("NotifyListenerRequest: NULL name for opcode: %ld\n", 171 request->operation)); 172 result = B_BAD_VALUE; 173 } 174 break; 175 case B_STAT_CHANGED: 176 break; 177 } 178 } 179 180 // execute the request 181 if (result == B_OK) { 182 switch (request->operation) { 183 case B_ENTRY_CREATED: 184 PRINT(("notify_entry_created(%ld, %lld, \"%s\", %lld)\n", 185 request->device, request->directory, name, request->node)); 186 result = notify_entry_created(request->device, 187 request->directory, name, request->node); 188 break; 189 190 case B_ENTRY_REMOVED: 191 PRINT(("notify_entry_removed(%ld, %lld, \"%s\", %lld)\n", 192 request->device, request->directory, name, request->node)); 193 result = notify_entry_removed(request->device, 194 request->directory, name, request->node); 195 break; 196 197 case B_ENTRY_MOVED: 198 PRINT(("notify_entry_moved(%ld, %lld, \"%s\", %lld, \"%s\", " 199 "%lld)\n", request->device, request->oldDirectory, oldName, 200 request->directory, name, request->node)); 201 result = notify_entry_moved(request->device, 202 request->oldDirectory, oldName, request->directory, name, 203 request->node); 204 break; 205 206 case B_STAT_CHANGED: 207 PRINT(("notify_stat_changed(%ld, %lld, 0x%lx)\n", 208 request->device, request->node, request->details)); 209 result = notify_stat_changed(request->device, request->node, 210 request->details); 211 break; 212 213 case B_ATTR_CHANGED: 214 PRINT(("notify_attribute_changed(%ld, %lld, \"%s\", 0x%lx)\n", 215 request->device, request->node, name, 216 (int32)request->details)); 217 result = notify_attribute_changed(request->device, 218 request->node, name, (int32)request->details); 219 break; 220 221 default: 222 ERROR(("NotifyQueryRequest: unsupported operation: %ld\n", 223 request->operation)); 224 result = B_BAD_VALUE; 225 break; 226 } 227 } 228 229 // prepare the reply 230 RequestAllocator allocator(fPort->GetPort()); 231 NotifyListenerReply* reply; 232 status_t error = AllocateRequest(allocator, &reply); 233 if (error != B_OK) 234 return error; 235 236 reply->error = result; 237 238 // send the reply 239 return fPort->SendRequest(&allocator); 240 } 241 242 // _HandleRequest 243 status_t 244 KernelRequestHandler::_HandleRequest(NotifySelectEventRequest* request) 245 { 246 // check and execute the request 247 status_t result = B_OK; 248 if (fFileSystem->KnowsSelectSyncEntry(request->sync)) { 249 if (request->unspecifiedEvent) { 250 // old style add-ons can't provide an event argument; we shoot 251 // all events 252 notify_select_event(request->sync, B_SELECT_READ); 253 notify_select_event(request->sync, B_SELECT_WRITE); 254 notify_select_event(request->sync, B_SELECT_ERROR); 255 } else { 256 PRINT(("notify_select_event(%p, %d)\n", request->sync, 257 (int)request->event)); 258 notify_select_event(request->sync, request->event); 259 } 260 } else 261 result = B_BAD_VALUE; 262 263 // prepare the reply 264 RequestAllocator allocator(fPort->GetPort()); 265 NotifySelectEventReply* reply; 266 status_t error = AllocateRequest(allocator, &reply); 267 if (error != B_OK) 268 return error; 269 270 reply->error = result; 271 272 // send the reply 273 return fPort->SendRequest(&allocator); 274 } 275 276 // _HandleRequest 277 status_t 278 KernelRequestHandler::_HandleRequest(NotifyQueryRequest* request) 279 { 280 // check and execute the request 281 status_t result = B_OK; 282 if (fVolume && request->device != fVolume->GetID()) 283 result = B_BAD_VALUE; 284 285 // check the name 286 char* name = (char*)request->name.GetData(); 287 int32 nameLen = request->name.GetSize(); 288 if (!name || nameLen <= 0) { 289 ERROR(("NotifyQueryRequest: NULL name!\n")); 290 result = B_BAD_VALUE; 291 } else 292 name[nameLen - 1] = '\0'; // NULL-terminate to be safe 293 294 // execute the request 295 if (result == B_OK) { 296 switch (request->operation) { 297 case B_ENTRY_CREATED: 298 PRINT(("notify_query_entry_created(%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_created(request->port, 302 request->token, request->device, request->directory, name, 303 request->node); 304 break; 305 306 case B_ENTRY_REMOVED: 307 PRINT(("notify_query_entry_removed(%ld, %ld, %ld, %lld," 308 " \"%s\", %lld)\n", request->port, request->token, 309 request->device, request->directory, name, request->node)); 310 result = notify_query_entry_removed(request->port, 311 request->token, request->device, request->directory, name, 312 request->node); 313 break; 314 315 case B_ENTRY_MOVED: 316 default: 317 ERROR(("NotifyQueryRequest: unsupported operation: %ld\n", 318 request->operation)); 319 result = B_BAD_VALUE; 320 break; 321 } 322 } 323 324 // prepare the reply 325 RequestAllocator allocator(fPort->GetPort()); 326 NotifyQueryReply* reply; 327 status_t error = AllocateRequest(allocator, &reply); 328 if (error != B_OK) 329 return error; 330 331 reply->error = result; 332 333 // send the reply 334 return fPort->SendRequest(&allocator); 335 } 336 337 // #pragma mark - 338 // #pragma mark ----- vnodes ----- 339 340 // _HandleRequest 341 status_t 342 KernelRequestHandler::_HandleRequest(GetVNodeRequest* request) 343 { 344 // check and execute the request 345 Volume* volume = NULL; 346 status_t result = _GetVolume(request->nsid, &volume); 347 VolumePutter _(volume); 348 void* node; 349 if (result == B_OK) 350 result = volume->GetVNode(request->vnid, &node); 351 // prepare the reply 352 RequestAllocator allocator(fPort->GetPort()); 353 GetVNodeReply* reply; 354 status_t error = AllocateRequest(allocator, &reply); 355 if (error != B_OK) 356 return error; 357 reply->error = result; 358 reply->node = node; 359 // send the reply 360 return fPort->SendRequest(&allocator); 361 } 362 363 // _HandleRequest 364 status_t 365 KernelRequestHandler::_HandleRequest(PutVNodeRequest* request) 366 { 367 // check and execute the request 368 Volume* volume = NULL; 369 status_t result = _GetVolume(request->nsid, &volume); 370 VolumePutter _(volume); 371 if (result == B_OK) 372 result = volume->PutVNode(request->vnid); 373 // prepare the reply 374 RequestAllocator allocator(fPort->GetPort()); 375 PutVNodeReply* reply; 376 status_t error = AllocateRequest(allocator, &reply); 377 if (error != B_OK) 378 return error; 379 reply->error = result; 380 // send the reply 381 return fPort->SendRequest(&allocator); 382 } 383 384 385 // _HandleRequest 386 status_t 387 KernelRequestHandler::_HandleRequest(AcquireVNodeRequest* request) 388 { 389 // check and execute the request 390 Volume* volume = NULL; 391 status_t result = _GetVolume(request->nsid, &volume); 392 VolumePutter _(volume); 393 if (result == B_OK) 394 result = volume->AcquireVNode(request->vnid); 395 396 // prepare the reply 397 RequestAllocator allocator(fPort->GetPort()); 398 AcquireVNodeReply* reply; 399 status_t error = AllocateRequest(allocator, &reply); 400 if (error != B_OK) 401 return error; 402 reply->error = result; 403 404 // send the reply 405 return fPort->SendRequest(&allocator); 406 } 407 408 409 // _HandleRequest 410 status_t 411 KernelRequestHandler::_HandleRequest(NewVNodeRequest* request) 412 { 413 // check and execute the request 414 Volume* volume = NULL; 415 status_t result = _GetVolume(request->nsid, &volume); 416 VolumePutter _(volume); 417 if (result == B_OK) { 418 result = volume->NewVNode(request->vnid, request->node, 419 request->capabilities); 420 } 421 422 // prepare the reply 423 RequestAllocator allocator(fPort->GetPort()); 424 NewVNodeReply* reply; 425 status_t error = AllocateRequest(allocator, &reply); 426 if (error != B_OK) 427 return error; 428 reply->error = result; 429 430 // send the reply 431 return fPort->SendRequest(&allocator); 432 } 433 434 // _HandleRequest 435 status_t 436 KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request) 437 { 438 // check and execute the request 439 Volume* volume = NULL; 440 status_t result = _GetVolume(request->nsid, &volume); 441 VolumePutter _(volume); 442 if (result == B_OK) { 443 result = volume->PublishVNode(request->vnid, request->node, 444 request->type, request->flags, request->capabilities); 445 } 446 447 // prepare the reply 448 RequestAllocator allocator(fPort->GetPort()); 449 PublishVNodeReply* reply; 450 status_t error = AllocateRequest(allocator, &reply); 451 if (error != B_OK) 452 return error; 453 454 reply->error = result; 455 456 // send the reply 457 return fPort->SendRequest(&allocator); 458 } 459 460 // _HandleRequest 461 status_t 462 KernelRequestHandler::_HandleRequest(RemoveVNodeRequest* request) 463 { 464 // check and execute the request 465 Volume* volume = NULL; 466 status_t result = _GetVolume(request->nsid, &volume); 467 VolumePutter _(volume); 468 if (result == B_OK) 469 result = volume->RemoveVNode(request->vnid); 470 // prepare the reply 471 RequestAllocator allocator(fPort->GetPort()); 472 RemoveVNodeReply* reply; 473 status_t error = AllocateRequest(allocator, &reply); 474 if (error != B_OK) 475 return error; 476 reply->error = result; 477 // send the reply 478 return fPort->SendRequest(&allocator); 479 } 480 481 // _HandleRequest 482 status_t 483 KernelRequestHandler::_HandleRequest(UnremoveVNodeRequest* request) 484 { 485 // check and execute the request 486 Volume* volume = NULL; 487 status_t result = _GetVolume(request->nsid, &volume); 488 VolumePutter _(volume); 489 if (result == B_OK) 490 result = volume->UnremoveVNode(request->vnid); 491 // prepare the reply 492 RequestAllocator allocator(fPort->GetPort()); 493 UnremoveVNodeReply* reply; 494 status_t error = AllocateRequest(allocator, &reply); 495 if (error != B_OK) 496 return error; 497 reply->error = result; 498 // send the reply 499 return fPort->SendRequest(&allocator); 500 } 501 502 // _HandleRequest 503 status_t 504 KernelRequestHandler::_HandleRequest(GetVNodeRemovedRequest* request) 505 { 506 // check and execute the request 507 Volume* volume = NULL; 508 status_t result = _GetVolume(request->nsid, &volume); 509 VolumePutter _(volume); 510 bool removed = false; 511 if (result == B_OK) 512 result = volume->GetVNodeRemoved(request->vnid, &removed); 513 514 // prepare the reply 515 RequestAllocator allocator(fPort->GetPort()); 516 GetVNodeRemovedReply* reply; 517 status_t error = AllocateRequest(allocator, &reply); 518 if (error != B_OK) 519 return error; 520 521 reply->error = result; 522 reply->removed = removed; 523 524 // send the reply 525 return fPort->SendRequest(&allocator); 526 } 527 528 529 // _HandleRequest 530 status_t 531 KernelRequestHandler::_HandleRequest(FileCacheCreateRequest* request) 532 { 533 // check and execute the request 534 Volume* volume = NULL; 535 status_t result = _GetVolume(request->nsid, &volume); 536 VolumePutter _(volume); 537 538 if (result == B_OK) 539 result = volume->CreateFileCache(request->vnid, request->size); 540 541 // prepare the reply 542 RequestAllocator allocator(fPort->GetPort()); 543 FileCacheCreateReply* reply; 544 status_t error = AllocateRequest(allocator, &reply); 545 if (error != B_OK) 546 return error; 547 reply->error = result; 548 549 // send the reply 550 return fPort->SendRequest(&allocator); 551 } 552 553 554 // _HandleRequest 555 status_t 556 KernelRequestHandler::_HandleRequest(FileCacheDeleteRequest* request) 557 { 558 // check and execute the request 559 Volume* volume = NULL; 560 status_t result = _GetVolume(request->nsid, &volume); 561 VolumePutter _(volume); 562 563 if (result == B_OK) 564 result = volume->DeleteFileCache(request->vnid); 565 566 // prepare the reply 567 RequestAllocator allocator(fPort->GetPort()); 568 FileCacheDeleteReply* reply; 569 status_t error = AllocateRequest(allocator, &reply); 570 if (error != B_OK) 571 return error; 572 reply->error = result; 573 574 // send the reply 575 return fPort->SendRequest(&allocator); 576 } 577 578 579 // _HandleRequest 580 status_t 581 KernelRequestHandler::_HandleRequest(FileCacheSetEnabledRequest* request) 582 { 583 // check and execute the request 584 Volume* volume = NULL; 585 status_t result = _GetVolume(request->nsid, &volume); 586 VolumePutter _(volume); 587 588 if (result == B_OK) 589 result = volume->SetFileCacheEnabled(request->vnid, request->enabled); 590 591 // prepare the reply 592 RequestAllocator allocator(fPort->GetPort()); 593 FileCacheSetEnabledReply* reply; 594 status_t error = AllocateRequest(allocator, &reply); 595 if (error != B_OK) 596 return error; 597 reply->error = result; 598 599 // send the reply 600 return fPort->SendRequest(&allocator); 601 } 602 603 604 // _HandleRequest 605 status_t 606 KernelRequestHandler::_HandleRequest(FileCacheSetSizeRequest* request) 607 { 608 // check and execute the request 609 Volume* volume = NULL; 610 status_t result = _GetVolume(request->nsid, &volume); 611 VolumePutter _(volume); 612 613 if (result == B_OK) 614 result = volume->SetFileCacheSize(request->vnid, request->size); 615 616 // prepare the reply 617 RequestAllocator allocator(fPort->GetPort()); 618 FileCacheSetSizeReply* reply; 619 status_t error = AllocateRequest(allocator, &reply); 620 if (error != B_OK) 621 return error; 622 reply->error = result; 623 624 // send the reply 625 return fPort->SendRequest(&allocator); 626 } 627 628 629 // _HandleRequest 630 status_t 631 KernelRequestHandler::_HandleRequest(FileCacheSyncRequest* request) 632 { 633 // check and execute the request 634 Volume* volume = NULL; 635 status_t result = _GetVolume(request->nsid, &volume); 636 VolumePutter _(volume); 637 638 if (result == B_OK) 639 result = volume->SyncFileCache(request->vnid); 640 641 // prepare the reply 642 RequestAllocator allocator(fPort->GetPort()); 643 FileCacheSyncReply* reply; 644 status_t error = AllocateRequest(allocator, &reply); 645 if (error != B_OK) 646 return error; 647 reply->error = result; 648 649 // send the reply 650 return fPort->SendRequest(&allocator); 651 } 652 653 654 // _HandleRequest 655 status_t 656 KernelRequestHandler::_HandleRequest(FileCacheReadRequest* request) 657 { 658 // check the request 659 Volume* volume = NULL; 660 status_t result = _GetVolume(request->nsid, &volume); 661 VolumePutter _(volume); 662 663 size_t size = request->size; 664 665 // allocate the reply 666 RequestAllocator allocator(fPort->GetPort()); 667 FileCacheReadReply* reply; 668 status_t error = AllocateRequest(allocator, &reply); 669 if (error != B_OK) 670 RETURN_ERROR(error); 671 672 void* buffer; 673 if (result == B_OK) { 674 result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer, 675 true); 676 } 677 678 // execute the request 679 if (result == B_OK) { 680 result = volume->ReadFileCache(request->vnid, request->cookie, 681 request->pos, buffer, &size); 682 } 683 684 // prepare the reply 685 reply->error = result; 686 reply->bytesRead = size; 687 688 // send the reply 689 if (reply->error == B_OK && reply->bytesRead > 0) { 690 SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY); 691 return fPort->SendRequest(&allocator, &handler); 692 } 693 694 return fPort->SendRequest(&allocator); 695 } 696 697 698 // _HandleRequest 699 status_t 700 KernelRequestHandler::_HandleRequest(FileCacheWriteRequest* request) 701 { 702 // check and execute the request 703 Volume* volume = NULL; 704 status_t result = _GetVolume(request->nsid, &volume); 705 VolumePutter _(volume); 706 707 size_t size = 0; 708 if (result == B_OK) { 709 const void* data = request->buffer.GetData(); 710 size = request->size; 711 if (data != NULL) { 712 if (size != (size_t)request->buffer.GetSize()) 713 result = B_BAD_DATA; 714 } 715 716 if (result == B_OK) { 717 result = volume->WriteFileCache(request->vnid, request->cookie, 718 request->pos, data, &size); 719 } 720 } 721 722 // prepare the reply 723 RequestAllocator allocator(fPort->GetPort()); 724 FileCacheWriteReply* reply; 725 status_t error = AllocateRequest(allocator, &reply); 726 if (error != B_OK) 727 return error; 728 reply->error = result; 729 reply->bytesWritten = size; 730 731 // send the reply 732 return fPort->SendRequest(&allocator); 733 } 734 735 736 // _HandleRequest 737 status_t 738 KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request) 739 { 740 // check and execute the request 741 Volume* volume = NULL; 742 status_t result = _GetVolume(request->nsid, &volume); 743 VolumePutter _(volume); 744 745 uint32 vecCount = request->vecCount; 746 if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS) 747 result = B_BAD_VALUE; 748 749 if (result == B_OK) { 750 result = volume->DoIterativeFDIO(request->fd, request->request, 751 request->cookie, request->vecs, vecCount); 752 } 753 754 // prepare the reply 755 RequestAllocator allocator(fPort->GetPort()); 756 DoIterativeFDIOReply* reply; 757 status_t error = AllocateRequest(allocator, &reply); 758 if (error != B_OK) 759 return error; 760 reply->error = result; 761 762 // send the reply 763 return fPort->SendRequest(&allocator); 764 } 765 766 767 status_t 768 KernelRequestHandler::_HandleRequest(ReadFromIORequestRequest* request) 769 { 770 // check the request 771 Volume* volume = NULL; 772 status_t result = _GetVolume(request->nsid, &volume); 773 VolumePutter _(volume); 774 775 size_t size = request->size; 776 777 // allocate the reply 778 RequestAllocator allocator(fPort->GetPort()); 779 ReadFromIORequestReply* reply; 780 status_t error = AllocateRequest(allocator, &reply); 781 if (error != B_OK) 782 RETURN_ERROR(error); 783 784 void* buffer; 785 if (result == B_OK) { 786 result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer, 787 true); 788 } 789 790 // execute the request 791 if (result == B_OK) 792 result = volume->ReadFromIORequest(request->request, buffer, size); 793 794 // prepare the reply 795 reply->error = result; 796 797 // send the reply 798 if (reply->error == B_OK && size > 0) { 799 SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY); 800 return fPort->SendRequest(&allocator, &handler); 801 } 802 803 return fPort->SendRequest(&allocator); 804 } 805 806 807 status_t 808 KernelRequestHandler::_HandleRequest(WriteToIORequestRequest* request) 809 { 810 // check and execute the request 811 Volume* volume = NULL; 812 status_t result = _GetVolume(request->nsid, &volume); 813 VolumePutter _(volume); 814 815 if (result == B_OK) { 816 result = volume->WriteToIORequest(request->request, 817 request->buffer.GetData(), request->buffer.GetSize()); 818 } 819 820 // prepare the reply 821 RequestAllocator allocator(fPort->GetPort()); 822 WriteToIORequestReply* reply; 823 status_t error = AllocateRequest(allocator, &reply); 824 if (error != B_OK) 825 return error; 826 reply->error = result; 827 828 // send the reply 829 return fPort->SendRequest(&allocator); 830 } 831 832 833 // _HandleRequest 834 status_t 835 KernelRequestHandler::_HandleRequest(NotifyIORequestRequest* request) 836 { 837 // check and execute the request 838 Volume* volume = NULL; 839 status_t result = _GetVolume(request->nsid, &volume); 840 VolumePutter _(volume); 841 842 if (result == B_OK) 843 result = volume->NotifyIORequest(request->request, request->status); 844 845 // prepare the reply 846 RequestAllocator allocator(fPort->GetPort()); 847 NotifyIORequestReply* reply; 848 status_t error = AllocateRequest(allocator, &reply); 849 if (error != B_OK) 850 return error; 851 reply->error = result; 852 853 // send the reply 854 return fPort->SendRequest(&allocator); 855 } 856 857 858 status_t 859 KernelRequestHandler::_HandleRequest(AddNodeListenerRequest* request) 860 { 861 // check and execute the request 862 status_t result = fFileSystem->AddNodeListener(request->device, 863 request->node, request->flags, request->listener); 864 865 // prepare the reply 866 RequestAllocator allocator(fPort->GetPort()); 867 AddNodeListenerReply* reply; 868 status_t error = AllocateRequest(allocator, &reply); 869 if (error != B_OK) 870 return error; 871 872 reply->error = result; 873 874 // send the reply 875 return fPort->SendRequest(&allocator); 876 } 877 878 879 status_t 880 KernelRequestHandler::_HandleRequest(RemoveNodeListenerRequest* request) 881 { 882 // check and execute the request 883 status_t result = fFileSystem->RemoveNodeListener(request->device, 884 request->node, request->listener); 885 886 // prepare the reply 887 RequestAllocator allocator(fPort->GetPort()); 888 RemoveNodeListenerReply* reply; 889 status_t error = AllocateRequest(allocator, &reply); 890 if (error != B_OK) 891 return error; 892 893 reply->error = result; 894 895 // send the reply 896 return fPort->SendRequest(&allocator); 897 } 898 899 900 // _GetVolume 901 status_t 902 KernelRequestHandler::_GetVolume(dev_t id, Volume** volume) 903 { 904 if (fVolume) { 905 if (fVolume->GetID() != id) { 906 *volume = NULL; 907 return B_BAD_VALUE; 908 } 909 fVolume->AcquireReference(); 910 *volume = fVolume; 911 return B_OK; 912 } 913 *volume = fFileSystem->GetVolume(id); 914 return (*volume ? B_OK : B_BAD_VALUE); 915 } 916 917