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