1/* 2 * Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include "HaikuKernelVolume.h" 7 8#include <new> 9 10#include <fcntl.h> 11#include <string.h> 12#include <unistd.h> 13 14#include "AutoDeleter.h" 15#include "AutoLocker.h" 16#include "Debug.h" 17#include "HashMap.h" 18 19#include "../IORequestInfo.h" 20#include "../kernel_emu.h" 21 22#include "HaikuKernelFileSystem.h" 23#include "HaikuKernelIORequest.h" 24#include "HaikuKernelNode.h" 25 26 27// NodeMap 28class HaikuKernelVolume::NodeMap 29 : public SynchronizedHashMap<HashKey64<ino_t>, HaikuKernelNode*, Locker> { 30}; 31 32 33// _FileSystem 34inline HaikuKernelFileSystem* 35HaikuKernelVolume::_FileSystem() const 36{ 37 return static_cast<HaikuKernelFileSystem*>(fFileSystem); 38} 39 40 41// constructor 42HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id, 43 file_system_module_info* fsModule) 44 : 45 Volume(fileSystem, id), 46 fFSModule(fsModule), 47 fNodes(NULL) 48{ 49 fVolume.id = id; 50 fVolume.partition = -1; 51 fVolume.layer = 0; 52 fVolume.private_volume = NULL; // filled in by the FS 53 fVolume.ops = NULL; // filled in by the FS 54 fVolume.sub_volume = NULL; 55 fVolume.super_volume = NULL; 56 fVolume.file_system = fFSModule; 57 fVolume.file_system_name = const_cast<char*>(fileSystem->GetName()); 58 fVolume.haikuVolume = this; 59} 60 61// destructor 62HaikuKernelVolume::~HaikuKernelVolume() 63{ 64 delete fNodes; 65} 66 67 68// Init 69status_t 70HaikuKernelVolume::Init() 71{ 72 fNodes = new(std::nothrow) NodeMap; 73 if (fNodes == NULL) 74 return B_NO_MEMORY; 75 return fNodes->InitCheck(); 76} 77 78 79// NewVNode 80status_t 81HaikuKernelVolume::NewVNode(ino_t vnodeID, void* privateNode, fs_vnode_ops* ops, 82 HaikuKernelNode** _node) 83{ 84 AutoLocker<NodeMap> _(fNodes); 85 86 // check whether we do already know the node 87 HaikuKernelNode* node = fNodes->Get(vnodeID); 88 if (node != NULL) 89 return B_BAD_VALUE; 90 91 // get node capabilities 92 HaikuKernelNode::Capabilities* capabilities 93 = _FileSystem()->GetNodeCapabilities(ops); 94 if (capabilities == NULL) 95 return B_NO_MEMORY; 96 97 // create a new node 98 node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, ops, 99 capabilities); 100 if (node == NULL) { 101 _FileSystem()->PutNodeCapabilities(capabilities); 102 return B_NO_MEMORY; 103 } 104 105 // add to map 106 status_t error = fNodes->Put(vnodeID, node); 107 if (error != B_OK) { 108 delete node; 109 return error; 110 } 111 112 *_node = node; 113 114 return B_OK; 115} 116 117 118// PublishVNode 119status_t 120HaikuKernelVolume::PublishVNode(ino_t vnodeID, void* privateNode, 121 fs_vnode_ops* ops, int type, uint32 flags, HaikuKernelNode** _node) 122{ 123 AutoLocker<NodeMap> _(fNodes); 124 125 // check whether we do already know the node 126 HaikuKernelNode* node = fNodes->Get(vnodeID); 127 if (node != NULL) { 128 if (node->published) 129 return B_BAD_VALUE; 130 } else { 131 // get node capabilities 132 HaikuKernelNode::Capabilities* capabilities 133 = _FileSystem()->GetNodeCapabilities(ops); 134 if (capabilities == NULL) 135 return B_NO_MEMORY; 136 137 // create a new node 138 node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, 139 ops, capabilities); 140 if (node == NULL) { 141 _FileSystem()->PutNodeCapabilities(capabilities); 142 return B_NO_MEMORY; 143 } 144 145 // add to map 146 status_t error = fNodes->Put(vnodeID, node); 147 if (error != B_OK) { 148 delete node; 149 return error; 150 } 151 } 152 153 node->published = true; 154 155 *_node = node; 156 157 return B_OK; 158} 159 160 161// UndoNewVNode 162void 163HaikuKernelVolume::UndoNewVNode(HaikuKernelNode* node) 164{ 165 fNodes->Remove(node->id); 166 delete node; 167} 168 169 170// UndoPublishVNode 171void 172HaikuKernelVolume::UndoPublishVNode(HaikuKernelNode* node) 173{ 174 fNodes->Remove(node->id); 175 delete node; 176} 177 178 179// NodeWithID 180HaikuKernelNode* 181HaikuKernelVolume::NodeWithID(ino_t vnodeID) const 182{ 183 return fNodes->Get(vnodeID); 184} 185 186 187// #pragma mark - 188// #pragma mark ----- FS ----- 189 190// Mount 191status_t 192HaikuKernelVolume::Mount(const char* device, uint32 flags, 193 const char* parameters, ino_t* rootID) 194{ 195 if (!fFSModule->mount) 196 return B_BAD_VALUE; 197 198 // mount 199 status_t error = fFSModule->mount(&fVolume, device, flags, parameters, 200 rootID); 201 if (error != B_OK) 202 return error; 203 204 _InitCapabilities(); 205 206 return B_OK; 207} 208 209// Unmount 210status_t 211HaikuKernelVolume::Unmount() 212{ 213 if (!fVolume.ops->unmount) 214 return B_BAD_VALUE; 215 216 return fVolume.ops->unmount(&fVolume); 217} 218 219// Sync 220status_t 221HaikuKernelVolume::Sync() 222{ 223 if (!fVolume.ops->sync) 224 return B_BAD_VALUE; 225 return fVolume.ops->sync(&fVolume); 226} 227 228// ReadFSInfo 229status_t 230HaikuKernelVolume::ReadFSInfo(fs_info* info) 231{ 232 if (!fVolume.ops->read_fs_info) 233 return B_BAD_VALUE; 234 return fVolume.ops->read_fs_info(&fVolume, info); 235} 236 237// WriteFSInfo 238status_t 239HaikuKernelVolume::WriteFSInfo(const struct fs_info* info, uint32 mask) 240{ 241 if (!fVolume.ops->write_fs_info) 242 return B_BAD_VALUE; 243 return fVolume.ops->write_fs_info(&fVolume, info, mask); 244} 245 246 247// #pragma mark - file cache 248 249 250// GetFileMap 251status_t 252HaikuKernelVolume::GetFileMap(void* _node, off_t offset, size_t size, 253 struct file_io_vec* vecs, size_t* count) 254{ 255 HaikuKernelNode* node = (HaikuKernelNode*)_node; 256 257 if (!node->ops->get_file_map) 258 return B_BAD_VALUE; 259 return node->ops->get_file_map(&fVolume, node, offset, size, vecs, 260 count); 261} 262 263 264// #pragma mark - vnodes 265 266 267// Lookup 268status_t 269HaikuKernelVolume::Lookup(void* _dir, const char* entryName, ino_t* vnid) 270{ 271 HaikuKernelNode* dir = (HaikuKernelNode*)_dir; 272 273 if (!dir->ops->lookup) 274 return B_BAD_VALUE; 275 return dir->ops->lookup(&fVolume, dir, entryName, vnid); 276 277} 278 279// GetVNodeName 280status_t 281HaikuKernelVolume::GetVNodeName(void* _node, char* buffer, size_t bufferSize) 282{ 283 HaikuKernelNode* node = (HaikuKernelNode*)_node; 284 285 // If not implemented by the client file system, we invoke our super class 286 // version, which emulates the functionality. 287 if (!node->ops->get_vnode_name) 288 return Volume::GetVNodeName(_node, buffer, bufferSize); 289 return node->ops->get_vnode_name(&fVolume, node, buffer, bufferSize); 290} 291 292// ReadVNode 293status_t 294HaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type, 295 uint32* flags, FSVNodeCapabilities* _capabilities) 296{ 297 if (!fVolume.ops->get_vnode) 298 return B_BAD_VALUE; 299 300 // create a new wrapper node and add it to the map 301 HaikuKernelNode* node = new(std::nothrow) HaikuKernelNode(this, vnid, NULL, 302 NULL, NULL); 303 if (node == NULL) 304 return B_NO_MEMORY; 305 ObjectDeleter<HaikuKernelNode> nodeDeleter(node); 306 307 AutoLocker<NodeMap> locker(fNodes); 308 if (fNodes->Get(vnid) != NULL) 309 return B_BAD_VALUE; 310 311 status_t error = fNodes->Put(vnid, node); 312 if (error != B_OK) 313 return error; 314 315 locker.Unlock(); 316 317 // get the node 318 error = fVolume.ops->get_vnode(&fVolume, vnid, node, type, flags, reenter); 319 if (error != B_OK) { 320 locker.Lock(); 321 fNodes->Remove(vnid); 322 return error; 323 } 324 325 // get node capabilities 326 HaikuKernelNode::Capabilities* capabilities 327 = _FileSystem()->GetNodeCapabilities(node->ops); 328 if (capabilities == NULL) { 329 node->ops->put_vnode(&fVolume, node, reenter); 330 locker.Lock(); 331 fNodes->Remove(vnid); 332 return B_NO_MEMORY; 333 } 334 335 locker.Lock(); 336 node->capabilities = capabilities; 337 node->published = true; 338 nodeDeleter.Detach(); 339 340 *_node = node; 341 *_capabilities = capabilities->capabilities; 342 343 return B_OK; 344} 345 346// WriteVNode 347status_t 348HaikuKernelVolume::WriteVNode(void* _node, bool reenter) 349{ 350 HaikuKernelNode* node = (HaikuKernelNode*)_node; 351 352 fNodes->Remove(node->id); 353 354 if (!node->ops->put_vnode) 355 return B_BAD_VALUE; 356 status_t error = node->ops->put_vnode(&fVolume, node, reenter); 357 358 delete node; 359 360 return error; 361} 362 363// RemoveVNode 364status_t 365HaikuKernelVolume::RemoveVNode(void* _node, bool reenter) 366{ 367 HaikuKernelNode* node = (HaikuKernelNode*)_node; 368 369 fNodes->Remove(node->id); 370 371 if (!node->ops->remove_vnode) 372 return B_BAD_VALUE; 373 return node->ops->remove_vnode(&fVolume, node, reenter); 374} 375 376 377// #pragma mark - asynchronous I/O 378 379 380status_t 381HaikuKernelVolume::DoIO(void* _node, void* cookie, 382 const IORequestInfo& requestInfo) 383{ 384 HaikuKernelNode* node = (HaikuKernelNode*)_node; 385 386 if (!node->ops->io) 387 return B_BAD_VALUE; 388 389 // create a request object 390 HaikuKernelIORequest* request 391 = new(std::nothrow) HaikuKernelIORequest(this, requestInfo); 392 if (request == NULL) 393 RETURN_ERROR(B_NO_MEMORY); 394 395 status_t error = _FileSystem()->AddIORequest(request); 396 if (error != B_OK) { 397 delete request; 398 RETURN_ERROR(error); 399 } 400 401 // call the hook 402 error = node->ops->io(&fVolume, node, cookie, (io_request*)request); 403 404 // directly put our reference to the request, if the call failed 405 if (error != B_OK) { 406 _FileSystem()->PutIORequest(request); 407 RETURN_ERROR(error); 408 } 409 410 // TODO: ATM we don't release our reference when the request is finished 411 // normally! 412 413 return B_OK; 414} 415 416 417status_t 418HaikuKernelVolume::CancelIO(void* _node, void* cookie, int32 ioRequestID) 419{ 420 HaikuKernelNode* node = (HaikuKernelNode*)_node; 421 422 if (!node->ops->cancel_io) 423 return B_BAD_VALUE; 424 425 // get the request 426 HaikuKernelIORequest* request = _FileSystem()->GetIORequest(ioRequestID); 427 if (request == NULL) 428 RETURN_ERROR(B_BAD_VALUE); 429 430 // call the hook 431 status_t error = node->ops->cancel_io(&fVolume, node, cookie, 432 (io_request*)request); 433 434 // put the request -- once for the reference we got above, once for the 435 // reference we've got in DoIO() 436 _FileSystem()->PutIORequest(request, 2); 437 438 return error; 439} 440 441 442// IterativeIOGetVecs 443status_t 444HaikuKernelVolume::IterativeIOGetVecs(void* _cookie, int32 requestID, 445 off_t offset, size_t size, struct file_io_vec* vecs, size_t* _count) 446{ 447 HaikuKernelIterativeFDIOCookie* cookie 448 = (HaikuKernelIterativeFDIOCookie*)_cookie; 449 450 // get the request 451 HaikuKernelIORequest* request = _FileSystem()->GetIORequest(requestID); 452 if (request == NULL) 453 RETURN_ERROR(B_BAD_VALUE); 454 455 // call the callback 456 status_t error = cookie->getVecs(cookie->cookie, (io_request*)request, 457 offset, size, vecs, _count); 458 459 // put the reference we got above 460 _FileSystem()->PutIORequest(request, 1); 461 462 return error; 463} 464 465 466// IterativeIOFinished 467status_t 468HaikuKernelVolume::IterativeIOFinished(void* _cookie, int32 requestID, 469 status_t status, bool partialTransfer, size_t bytesTransferred) 470{ 471 HaikuKernelIterativeFDIOCookie* cookie 472 = (HaikuKernelIterativeFDIOCookie*)_cookie; 473 474 // we're definitely done with the cookie, now 475 ObjectDeleter<HaikuKernelIterativeFDIOCookie> _(cookie); 476 477 // get the request 478 HaikuKernelIORequest* request = _FileSystem()->GetIORequest(requestID); 479 if (request == NULL) 480 RETURN_ERROR(B_BAD_VALUE); 481 482 // call the callback 483 status_t error = cookie->finished(cookie->cookie, (io_request*)request, 484 status, partialTransfer, bytesTransferred); 485 486 // We're done with the request, too, so put the reference we got above and 487 // the one added by DoIO(). 488 _FileSystem()->PutIORequest(request, 2); 489 490 return error; 491} 492 493 494// #pragma mark - nodes 495 496 497// IOCtl 498status_t 499HaikuKernelVolume::IOCtl(void* _node, void* cookie, uint32 command, 500 void* buffer, size_t size) 501{ 502 HaikuKernelNode* node = (HaikuKernelNode*)_node; 503 504 if (!node->ops->ioctl) 505 return B_BAD_VALUE; 506 return node->ops->ioctl(&fVolume, node, cookie, command, buffer, 507 size); 508} 509 510// SetFlags 511status_t 512HaikuKernelVolume::SetFlags(void* _node, void* cookie, int flags) 513{ 514 HaikuKernelNode* node = (HaikuKernelNode*)_node; 515 516 if (!node->ops->set_flags) 517 return B_BAD_VALUE; 518 return node->ops->set_flags(&fVolume, node, cookie, flags); 519} 520 521// Select 522status_t 523HaikuKernelVolume::Select(void* _node, void* cookie, uint8 event, 524 selectsync* sync) 525{ 526 HaikuKernelNode* node = (HaikuKernelNode*)_node; 527 528 if (!node->ops->select) { 529 UserlandFS::KernelEmu::notify_select_event(sync, event, false); 530 return B_OK; 531 } 532 return node->ops->select(&fVolume, node, cookie, event, sync); 533} 534 535// Deselect 536status_t 537HaikuKernelVolume::Deselect(void* _node, void* cookie, uint8 event, 538 selectsync* sync) 539{ 540 HaikuKernelNode* node = (HaikuKernelNode*)_node; 541 542 if (!node->ops->select || !node->ops->deselect) 543 return B_OK; 544 return node->ops->deselect(&fVolume, node, cookie, event, sync); 545} 546 547// FSync 548status_t 549HaikuKernelVolume::FSync(void* _node) 550{ 551 HaikuKernelNode* node = (HaikuKernelNode*)_node; 552 553 if (!node->ops->fsync) 554 return B_BAD_VALUE; 555 return node->ops->fsync(&fVolume, node); 556} 557 558// ReadSymlink 559status_t 560HaikuKernelVolume::ReadSymlink(void* _node, char* buffer, size_t bufferSize, 561 size_t* bytesRead) 562{ 563 HaikuKernelNode* node = (HaikuKernelNode*)_node; 564 565 if (!node->ops->read_symlink) 566 return B_BAD_VALUE; 567 568 *bytesRead = bufferSize; 569 570 return node->ops->read_symlink(&fVolume, node, buffer, bytesRead); 571} 572 573// CreateSymlink 574status_t 575HaikuKernelVolume::CreateSymlink(void* _dir, const char* name, 576 const char* target, int mode) 577{ 578 HaikuKernelNode* dir = (HaikuKernelNode*)_dir; 579 580 if (!dir->ops->create_symlink) 581 return B_BAD_VALUE; 582 return dir->ops->create_symlink(&fVolume, dir, name, target, mode); 583} 584 585// Link 586status_t 587HaikuKernelVolume::Link(void* _dir, const char* name, void* _node) 588{ 589 HaikuKernelNode* dir = (HaikuKernelNode*)_dir; 590 HaikuKernelNode* node = (HaikuKernelNode*)_node; 591 592 if (!dir->ops->link) 593 return B_BAD_VALUE; 594 return dir->ops->link(&fVolume, dir, name, node); 595} 596 597// Unlink 598status_t 599HaikuKernelVolume::Unlink(void* _dir, const char* name) 600{ 601 HaikuKernelNode* dir = (HaikuKernelNode*)_dir; 602 603 if (!dir->ops->unlink) 604 return B_BAD_VALUE; 605 return dir->ops->unlink(&fVolume, dir, name); 606} 607 608// Rename 609status_t 610HaikuKernelVolume::Rename(void* _oldDir, const char* oldName, void* _newDir, 611 const char* newName) 612{ 613 HaikuKernelNode* oldDir = (HaikuKernelNode*)_oldDir; 614 HaikuKernelNode* newDir = (HaikuKernelNode*)_newDir; 615 616 if (!oldDir->ops->rename) 617 return B_BAD_VALUE; 618 return oldDir->ops->rename(&fVolume, oldDir, oldName, newDir, newName); 619} 620 621// Access 622status_t 623HaikuKernelVolume::Access(void* _node, int mode) 624{ 625 HaikuKernelNode* node = (HaikuKernelNode*)_node; 626 627 if (!node->ops->access) 628 return B_OK; 629 return node->ops->access(&fVolume, node, mode); 630} 631 632// ReadStat 633status_t 634HaikuKernelVolume::ReadStat(void* _node, struct stat* st) 635{ 636 HaikuKernelNode* node = (HaikuKernelNode*)_node; 637 638 if (!node->ops->read_stat) 639 return B_BAD_VALUE; 640 return node->ops->read_stat(&fVolume, node, st); 641} 642 643// WriteStat 644status_t 645HaikuKernelVolume::WriteStat(void* _node, const struct stat *st, uint32 mask) 646{ 647 HaikuKernelNode* node = (HaikuKernelNode*)_node; 648 649 if (!node->ops->write_stat) 650 return B_BAD_VALUE; 651 return node->ops->write_stat(&fVolume, node, st, mask); 652} 653 654 655// #pragma mark - files 656 657 658// Create 659status_t 660HaikuKernelVolume::Create(void* _dir, const char* name, int openMode, int mode, 661 void** cookie, ino_t* vnid) 662{ 663 HaikuKernelNode* dir = (HaikuKernelNode*)_dir; 664 665 if (!dir->ops->create) 666 return B_BAD_VALUE; 667 return dir->ops->create(&fVolume, dir, name, openMode, mode, cookie, 668 vnid); 669} 670 671// Open 672status_t 673HaikuKernelVolume::Open(void* _node, int openMode, void** cookie) 674{ 675 HaikuKernelNode* node = (HaikuKernelNode*)_node; 676 677 if (!node->ops->open) 678 return B_BAD_VALUE; 679 return node->ops->open(&fVolume, node, openMode, cookie); 680} 681 682// Close 683status_t 684HaikuKernelVolume::Close(void* _node, void* cookie) 685{ 686 HaikuKernelNode* node = (HaikuKernelNode*)_node; 687 688 if (!node->ops->close) 689 return B_OK; 690 return node->ops->close(&fVolume, node, cookie); 691} 692 693// FreeCookie 694status_t 695HaikuKernelVolume::FreeCookie(void* _node, void* cookie) 696{ 697 HaikuKernelNode* node = (HaikuKernelNode*)_node; 698 699 if (!node->ops->free_cookie) 700 return B_OK; 701 return node->ops->free_cookie(&fVolume, node, cookie); 702} 703 704// Read 705status_t 706HaikuKernelVolume::Read(void* _node, void* cookie, off_t pos, void* buffer, 707 size_t bufferSize, size_t* bytesRead) 708{ 709 HaikuKernelNode* node = (HaikuKernelNode*)_node; 710 711 if (!node->ops->read) 712 return B_BAD_VALUE; 713 714 *bytesRead = bufferSize; 715 716 return node->ops->read(&fVolume, node, cookie, pos, buffer, bytesRead); 717} 718 719// Write 720status_t 721HaikuKernelVolume::Write(void* _node, void* cookie, off_t pos, 722 const void* buffer, size_t bufferSize, size_t* bytesWritten) 723{ 724 HaikuKernelNode* node = (HaikuKernelNode*)_node; 725 726 if (!node->ops->write) 727 return B_BAD_VALUE; 728 729 *bytesWritten = bufferSize; 730 731 return node->ops->write(&fVolume, node, cookie, pos, buffer, 732 bytesWritten); 733} 734 735 736// #pragma mark - directories 737 738 739// CreateDir 740status_t 741HaikuKernelVolume::CreateDir(void* _dir, const char* name, int mode) 742{ 743 HaikuKernelNode* dir = (HaikuKernelNode*)_dir; 744 745 if (!dir->ops->create_dir) 746 return B_BAD_VALUE; 747 return dir->ops->create_dir(&fVolume, dir, name, mode); 748} 749 750// RemoveDir 751status_t 752HaikuKernelVolume::RemoveDir(void* _dir, const char* name) 753{ 754 HaikuKernelNode* dir = (HaikuKernelNode*)_dir; 755 756 if (!dir->ops->remove_dir) 757 return B_BAD_VALUE; 758 return dir->ops->remove_dir(&fVolume, dir, name); 759} 760 761// OpenDir 762status_t 763HaikuKernelVolume::OpenDir(void* _node, void** cookie) 764{ 765 HaikuKernelNode* node = (HaikuKernelNode*)_node; 766 767 if (!node->ops->open_dir) 768 return B_BAD_VALUE; 769 return node->ops->open_dir(&fVolume, node, cookie); 770} 771 772// CloseDir 773status_t 774HaikuKernelVolume::CloseDir(void* _node, void* cookie) 775{ 776 HaikuKernelNode* node = (HaikuKernelNode*)_node; 777 778 if (!node->ops->close_dir) 779 return B_OK; 780 return node->ops->close_dir(&fVolume, node, cookie); 781} 782 783// FreeDirCookie 784status_t 785HaikuKernelVolume::FreeDirCookie(void* _node, void* cookie) 786{ 787 HaikuKernelNode* node = (HaikuKernelNode*)_node; 788 789 if (!node->ops->free_dir_cookie) 790 return B_OK; 791 return node->ops->free_dir_cookie(&fVolume, node, cookie); 792} 793 794// ReadDir 795status_t 796HaikuKernelVolume::ReadDir(void* _node, void* cookie, void* buffer, 797 size_t bufferSize, uint32 count, uint32* countRead) 798{ 799 HaikuKernelNode* node = (HaikuKernelNode*)_node; 800 801 if (!node->ops->read_dir) 802 return B_BAD_VALUE; 803 804 *countRead = count; 805 806 return node->ops->read_dir(&fVolume, node, cookie, 807 (struct dirent*)buffer, bufferSize, countRead); 808} 809 810// RewindDir 811status_t 812HaikuKernelVolume::RewindDir(void* _node, void* cookie) 813{ 814 HaikuKernelNode* node = (HaikuKernelNode*)_node; 815 816 if (!node->ops->rewind_dir) 817 return B_BAD_VALUE; 818 return node->ops->rewind_dir(&fVolume, node, cookie); 819} 820 821 822// #pragma mark - attribute directories 823 824 825// OpenAttrDir 826status_t 827HaikuKernelVolume::OpenAttrDir(void* _node, void** cookie) 828{ 829 HaikuKernelNode* node = (HaikuKernelNode*)_node; 830 831 if (!node->ops->open_attr_dir) 832 return B_BAD_VALUE; 833 return node->ops->open_attr_dir(&fVolume, node, cookie); 834} 835 836// CloseAttrDir 837status_t 838HaikuKernelVolume::CloseAttrDir(void* _node, void* cookie) 839{ 840 HaikuKernelNode* node = (HaikuKernelNode*)_node; 841 842 if (!node->ops->close_attr_dir) 843 return B_OK; 844 return node->ops->close_attr_dir(&fVolume, node, cookie); 845} 846 847// FreeAttrDirCookie 848status_t 849HaikuKernelVolume::FreeAttrDirCookie(void* _node, void* cookie) 850{ 851 HaikuKernelNode* node = (HaikuKernelNode*)_node; 852 853 if (!node->ops->free_attr_dir_cookie) 854 return B_OK; 855 return node->ops->free_attr_dir_cookie(&fVolume, node, cookie); 856} 857 858// ReadAttrDir 859status_t 860HaikuKernelVolume::ReadAttrDir(void* _node, void* cookie, void* buffer, 861 size_t bufferSize, uint32 count, uint32* countRead) 862{ 863 HaikuKernelNode* node = (HaikuKernelNode*)_node; 864 865 if (!node->ops->read_attr_dir) 866 return B_BAD_VALUE; 867 868 *countRead = count; 869 870 return node->ops->read_attr_dir(&fVolume, node, cookie, 871 (struct dirent*)buffer, bufferSize, countRead); 872} 873 874// RewindAttrDir 875status_t 876HaikuKernelVolume::RewindAttrDir(void* _node, void* cookie) 877{ 878 HaikuKernelNode* node = (HaikuKernelNode*)_node; 879 880 if (!node->ops->rewind_attr_dir) 881 return B_BAD_VALUE; 882 return node->ops->rewind_attr_dir(&fVolume, node, cookie); 883} 884 885 886// #pragma mark - attributes 887 888 889// CreateAttr 890status_t 891HaikuKernelVolume::CreateAttr(void* _node, const char* name, uint32 type, 892 int openMode, void** cookie) 893{ 894 HaikuKernelNode* node = (HaikuKernelNode*)_node; 895 896 if (!node->ops->create_attr) 897 return B_BAD_VALUE; 898 return node->ops->create_attr(&fVolume, node, name, type, openMode, 899 cookie); 900} 901 902// OpenAttr 903status_t 904HaikuKernelVolume::OpenAttr(void* _node, const char* name, int openMode, 905 void** cookie) 906{ 907 HaikuKernelNode* node = (HaikuKernelNode*)_node; 908 909 if (!node->ops->open_attr) 910 return B_BAD_VALUE; 911 return node->ops->open_attr(&fVolume, node, name, openMode, cookie); 912} 913 914// CloseAttr 915status_t 916HaikuKernelVolume::CloseAttr(void* _node, void* cookie) 917{ 918 HaikuKernelNode* node = (HaikuKernelNode*)_node; 919 920 if (!node->ops->close_attr) 921 return B_OK; 922 return node->ops->close_attr(&fVolume, node, cookie); 923} 924 925// FreeAttrCookie 926status_t 927HaikuKernelVolume::FreeAttrCookie(void* _node, void* cookie) 928{ 929 HaikuKernelNode* node = (HaikuKernelNode*)_node; 930 931 if (!node->ops->free_attr_cookie) 932 return B_OK; 933 return node->ops->free_attr_cookie(&fVolume, node, cookie); 934} 935 936// ReadAttr 937status_t 938HaikuKernelVolume::ReadAttr(void* _node, void* cookie, off_t pos, 939 void* buffer, size_t bufferSize, size_t* bytesRead) 940{ 941 HaikuKernelNode* node = (HaikuKernelNode*)_node; 942 943 if (!node->ops->read_attr) 944 return B_BAD_VALUE; 945 946 *bytesRead = bufferSize; 947 948 return node->ops->read_attr(&fVolume, node, cookie, pos, buffer, 949 bytesRead); 950} 951 952// WriteAttr 953status_t 954HaikuKernelVolume::WriteAttr(void* _node, void* cookie, off_t pos, 955 const void* buffer, size_t bufferSize, size_t* bytesWritten) 956{ 957 HaikuKernelNode* node = (HaikuKernelNode*)_node; 958 959 if (!node->ops->write_attr) 960 return B_BAD_VALUE; 961 962 *bytesWritten = bufferSize; 963 964 return node->ops->write_attr(&fVolume, node, cookie, pos, buffer, 965 bytesWritten); 966} 967 968// ReadAttrStat 969status_t 970HaikuKernelVolume::ReadAttrStat(void* _node, void* cookie, 971 struct stat *st) 972{ 973 HaikuKernelNode* node = (HaikuKernelNode*)_node; 974 975 if (!node->ops->read_attr_stat) 976 return B_BAD_VALUE; 977 return node->ops->read_attr_stat(&fVolume, node, cookie, st); 978} 979 980// WriteAttrStat 981status_t 982HaikuKernelVolume::WriteAttrStat(void* _node, void* cookie, 983 const struct stat* st, int statMask) 984{ 985 HaikuKernelNode* node = (HaikuKernelNode*)_node; 986 987 if (!node->ops->write_attr_stat) 988 return B_BAD_VALUE; 989 return node->ops->write_attr_stat(&fVolume, node, cookie, st, 990 statMask); 991} 992 993// RenameAttr 994status_t 995HaikuKernelVolume::RenameAttr(void* _oldNode, const char* oldName, 996 void* _newNode, const char* newName) 997{ 998 HaikuKernelNode* oldNode = (HaikuKernelNode*)_oldNode; 999 HaikuKernelNode* newNode = (HaikuKernelNode*)_newNode; 1000 1001 if (!oldNode->ops->rename_attr) 1002 return B_BAD_VALUE; 1003 return oldNode->ops->rename_attr(&fVolume, oldNode, oldName, newNode, 1004 newName); 1005} 1006 1007// RemoveAttr 1008status_t 1009HaikuKernelVolume::RemoveAttr(void* _node, const char* name) 1010{ 1011 HaikuKernelNode* node = (HaikuKernelNode*)_node; 1012 1013 if (!node->ops->remove_attr) 1014 return B_BAD_VALUE; 1015 return node->ops->remove_attr(&fVolume, node, name); 1016} 1017 1018 1019// #pragma mark - indices 1020 1021 1022// OpenIndexDir 1023status_t 1024HaikuKernelVolume::OpenIndexDir(void** cookie) 1025{ 1026 if (!fVolume.ops->open_index_dir) 1027 return B_BAD_VALUE; 1028 return fVolume.ops->open_index_dir(&fVolume, cookie); 1029} 1030 1031// CloseIndexDir 1032status_t 1033HaikuKernelVolume::CloseIndexDir(void* cookie) 1034{ 1035 if (!fVolume.ops->close_index_dir) 1036 return B_OK; 1037 return fVolume.ops->close_index_dir(&fVolume, cookie); 1038} 1039 1040// FreeIndexDirCookie 1041status_t 1042HaikuKernelVolume::FreeIndexDirCookie(void* cookie) 1043{ 1044 if (!fVolume.ops->free_index_dir_cookie) 1045 return B_OK; 1046 return fVolume.ops->free_index_dir_cookie(&fVolume, cookie); 1047} 1048 1049// ReadIndexDir 1050status_t 1051HaikuKernelVolume::ReadIndexDir(void* cookie, void* buffer, 1052 size_t bufferSize, uint32 count, uint32* countRead) 1053{ 1054 if (!fVolume.ops->read_index_dir) 1055 return B_BAD_VALUE; 1056 1057 *countRead = count; 1058 1059 return fVolume.ops->read_index_dir(&fVolume, cookie, 1060 (struct dirent*)buffer, bufferSize, countRead); 1061} 1062 1063// RewindIndexDir 1064status_t 1065HaikuKernelVolume::RewindIndexDir(void* cookie) 1066{ 1067 if (!fVolume.ops->rewind_index_dir) 1068 return B_BAD_VALUE; 1069 return fVolume.ops->rewind_index_dir(&fVolume, cookie); 1070} 1071 1072// CreateIndex 1073status_t 1074HaikuKernelVolume::CreateIndex(const char* name, uint32 type, uint32 flags) 1075{ 1076 if (!fVolume.ops->create_index) 1077 return B_BAD_VALUE; 1078 return fVolume.ops->create_index(&fVolume, name, type, flags); 1079} 1080 1081// RemoveIndex 1082status_t 1083HaikuKernelVolume::RemoveIndex(const char* name) 1084{ 1085 if (!fVolume.ops->remove_index) 1086 return B_BAD_VALUE; 1087 return fVolume.ops->remove_index(&fVolume, name); 1088} 1089 1090// StatIndex 1091status_t 1092HaikuKernelVolume::ReadIndexStat(const char *name, struct stat *st) 1093{ 1094 if (!fVolume.ops->read_index_stat) 1095 return B_BAD_VALUE; 1096 return fVolume.ops->read_index_stat(&fVolume, name, st); 1097} 1098 1099 1100// #pragma mark - queries 1101 1102 1103// OpenQuery 1104status_t 1105HaikuKernelVolume::OpenQuery(const char* queryString, uint32 flags, 1106 port_id port, uint32 token, void** cookie) 1107{ 1108 if (!fVolume.ops->open_query) 1109 return B_BAD_VALUE; 1110 return fVolume.ops->open_query(&fVolume, queryString, flags, port, 1111 token, cookie); 1112} 1113 1114// CloseQuery 1115status_t 1116HaikuKernelVolume::CloseQuery(void* cookie) 1117{ 1118 if (!fVolume.ops->close_query) 1119 return B_OK; 1120 return fVolume.ops->close_query(&fVolume, cookie); 1121} 1122 1123// FreeQueryCookie 1124status_t 1125HaikuKernelVolume::FreeQueryCookie(void* cookie) 1126{ 1127 if (!fVolume.ops->free_query_cookie) 1128 return B_OK; 1129 return fVolume.ops->free_query_cookie(&fVolume, cookie); 1130} 1131 1132// ReadQuery 1133status_t 1134HaikuKernelVolume::ReadQuery(void* cookie, void* buffer, size_t bufferSize, 1135 uint32 count, uint32* countRead) 1136{ 1137 if (!fVolume.ops->read_query) 1138 return B_BAD_VALUE; 1139 1140 *countRead = count; 1141 1142 return fVolume.ops->read_query(&fVolume, cookie, (struct dirent*)buffer, 1143 bufferSize, countRead); 1144} 1145 1146// RewindQuery 1147status_t 1148HaikuKernelVolume::RewindQuery(void* cookie) 1149{ 1150 if (!fVolume.ops->rewind_query) 1151 return B_BAD_VALUE; 1152 return fVolume.ops->rewind_query(&fVolume, cookie); 1153} 1154 1155// _InitCapabilities 1156void 1157HaikuKernelVolume::_InitCapabilities() 1158{ 1159 fCapabilities.ClearAll(); 1160 1161 // FS operations 1162 fCapabilities.Set(FS_VOLUME_CAPABILITY_UNMOUNT, fVolume.ops->unmount); 1163 1164 fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_FS_INFO, 1165 fVolume.ops->read_fs_info); 1166 fCapabilities.Set(FS_VOLUME_CAPABILITY_WRITE_FS_INFO, 1167 fVolume.ops->write_fs_info); 1168 fCapabilities.Set(FS_VOLUME_CAPABILITY_SYNC, fVolume.ops->sync); 1169 1170 // vnode operations 1171 fCapabilities.Set(FS_VOLUME_CAPABILITY_GET_VNODE, fVolume.ops->get_vnode); 1172 1173 // index directory & index operations 1174 fCapabilities.Set(FS_VOLUME_CAPABILITY_OPEN_INDEX_DIR, 1175 fVolume.ops->open_index_dir); 1176 fCapabilities.Set(FS_VOLUME_CAPABILITY_CLOSE_INDEX_DIR, 1177 fVolume.ops->close_index_dir); 1178 fCapabilities.Set(FS_VOLUME_CAPABILITY_FREE_INDEX_DIR_COOKIE, 1179 fVolume.ops->free_index_dir_cookie); 1180 fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_INDEX_DIR, 1181 fVolume.ops->read_index_dir); 1182 fCapabilities.Set(FS_VOLUME_CAPABILITY_REWIND_INDEX_DIR, 1183 fVolume.ops->rewind_index_dir); 1184 1185 fCapabilities.Set(FS_VOLUME_CAPABILITY_CREATE_INDEX, 1186 fVolume.ops->create_index); 1187 fCapabilities.Set(FS_VOLUME_CAPABILITY_REMOVE_INDEX, 1188 fVolume.ops->remove_index); 1189 fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_INDEX_STAT, 1190 fVolume.ops->read_index_stat); 1191 1192 // query operations 1193 fCapabilities.Set(FS_VOLUME_CAPABILITY_OPEN_QUERY, fVolume.ops->open_query); 1194 fCapabilities.Set(FS_VOLUME_CAPABILITY_CLOSE_QUERY, 1195 fVolume.ops->close_query); 1196 fCapabilities.Set(FS_VOLUME_CAPABILITY_FREE_QUERY_COOKIE, 1197 fVolume.ops->free_query_cookie); 1198 fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_QUERY, fVolume.ops->read_query); 1199 fCapabilities.Set(FS_VOLUME_CAPABILITY_REWIND_QUERY, 1200 fVolume.ops->rewind_query); 1201} 1202