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 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 size = request->buffer.GetSize(); 710 result = volume->WriteFileCache(request->vnid, request->cookie, 711 request->pos, request->buffer.GetData(), &size); 712 } 713 714 // prepare the reply 715 RequestAllocator allocator(fPort->GetPort()); 716 FileCacheWriteReply* reply; 717 status_t error = AllocateRequest(allocator, &reply); 718 if (error != B_OK) 719 return error; 720 reply->error = result; 721 reply->bytesWritten = size; 722 723 // send the reply 724 return fPort->SendRequest(&allocator); 725 } 726 727 728 // _HandleRequest 729 status_t 730 KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request) 731 { 732 // check and execute the request 733 Volume* volume = NULL; 734 status_t result = _GetVolume(request->nsid, &volume); 735 VolumePutter _(volume); 736 737 uint32 vecCount = request->vecCount; 738 if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS) 739 result = B_BAD_VALUE; 740 741 if (result == B_OK) { 742 result = volume->DoIterativeFDIO(request->fd, request->request, 743 request->cookie, request->vecs, vecCount); 744 } 745 746 // prepare the reply 747 RequestAllocator allocator(fPort->GetPort()); 748 DoIterativeFDIOReply* reply; 749 status_t error = AllocateRequest(allocator, &reply); 750 if (error != B_OK) 751 return error; 752 reply->error = result; 753 754 // send the reply 755 return fPort->SendRequest(&allocator); 756 } 757 758 759 status_t 760 KernelRequestHandler::_HandleRequest(ReadFromIORequestRequest* request) 761 { 762 // check the request 763 Volume* volume = NULL; 764 status_t result = _GetVolume(request->nsid, &volume); 765 VolumePutter _(volume); 766 767 size_t size = request->size; 768 769 // allocate the reply 770 RequestAllocator allocator(fPort->GetPort()); 771 ReadFromIORequestReply* reply; 772 status_t error = AllocateRequest(allocator, &reply); 773 if (error != B_OK) 774 RETURN_ERROR(error); 775 776 void* buffer; 777 if (result == B_OK) { 778 result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer, 779 true); 780 } 781 782 // execute the request 783 if (result == B_OK) 784 result = volume->ReadFromIORequest(request->request, buffer, size); 785 786 // prepare the reply 787 reply->error = result; 788 789 // send the reply 790 if (reply->error == B_OK && size > 0) { 791 SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY); 792 return fPort->SendRequest(&allocator, &handler); 793 } 794 795 return fPort->SendRequest(&allocator); 796 } 797 798 799 status_t 800 KernelRequestHandler::_HandleRequest(WriteToIORequestRequest* request) 801 { 802 // check and execute the request 803 Volume* volume = NULL; 804 status_t result = _GetVolume(request->nsid, &volume); 805 VolumePutter _(volume); 806 807 if (result == B_OK) { 808 result = volume->WriteToIORequest(request->request, 809 request->buffer.GetData(), request->buffer.GetSize()); 810 } 811 812 // prepare the reply 813 RequestAllocator allocator(fPort->GetPort()); 814 WriteToIORequestReply* reply; 815 status_t error = AllocateRequest(allocator, &reply); 816 if (error != B_OK) 817 return error; 818 reply->error = result; 819 820 // send the reply 821 return fPort->SendRequest(&allocator); 822 } 823 824 825 // _HandleRequest 826 status_t 827 KernelRequestHandler::_HandleRequest(NotifyIORequestRequest* request) 828 { 829 // check and execute the request 830 Volume* volume = NULL; 831 status_t result = _GetVolume(request->nsid, &volume); 832 VolumePutter _(volume); 833 834 if (result == B_OK) 835 result = volume->NotifyIORequest(request->request, request->status); 836 837 // prepare the reply 838 RequestAllocator allocator(fPort->GetPort()); 839 NotifyIORequestReply* reply; 840 status_t error = AllocateRequest(allocator, &reply); 841 if (error != B_OK) 842 return error; 843 reply->error = result; 844 845 // send the reply 846 return fPort->SendRequest(&allocator); 847 } 848 849 850 status_t 851 KernelRequestHandler::_HandleRequest(AddNodeListenerRequest* request) 852 { 853 // check and execute the request 854 status_t result = fFileSystem->AddNodeListener(request->device, 855 request->node, request->flags, request->listener); 856 857 // prepare the reply 858 RequestAllocator allocator(fPort->GetPort()); 859 AddNodeListenerReply* reply; 860 status_t error = AllocateRequest(allocator, &reply); 861 if (error != B_OK) 862 return error; 863 864 reply->error = result; 865 866 // send the reply 867 return fPort->SendRequest(&allocator); 868 } 869 870 871 status_t 872 KernelRequestHandler::_HandleRequest(RemoveNodeListenerRequest* request) 873 { 874 // check and execute the request 875 status_t result = fFileSystem->RemoveNodeListener(request->device, 876 request->node, request->listener); 877 878 // prepare the reply 879 RequestAllocator allocator(fPort->GetPort()); 880 RemoveNodeListenerReply* reply; 881 status_t error = AllocateRequest(allocator, &reply); 882 if (error != B_OK) 883 return error; 884 885 reply->error = result; 886 887 // send the reply 888 return fPort->SendRequest(&allocator); 889 } 890 891 892 // _GetVolume 893 status_t 894 KernelRequestHandler::_GetVolume(dev_t id, Volume** volume) 895 { 896 if (fVolume) { 897 if (fVolume->GetID() != id) { 898 *volume = NULL; 899 return B_BAD_VALUE; 900 } 901 fVolume->AddReference(); 902 *volume = fVolume; 903 return B_OK; 904 } 905 *volume = fFileSystem->GetVolume(id); 906 return (*volume ? B_OK : B_BAD_VALUE); 907 } 908 909