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