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
28 class HaikuKernelVolume::NodeMap
29 : public SynchronizedHashMap<HashKey64<ino_t>, HaikuKernelNode*, Locker> {
30 };
31
32
33 // _FileSystem
34 inline HaikuKernelFileSystem*
_FileSystem() const35 HaikuKernelVolume::_FileSystem() const
36 {
37 return static_cast<HaikuKernelFileSystem*>(fFileSystem);
38 }
39
40
41 // constructor
HaikuKernelVolume(FileSystem * fileSystem,dev_t id,file_system_module_info * fsModule)42 HaikuKernelVolume::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
~HaikuKernelVolume()62 HaikuKernelVolume::~HaikuKernelVolume()
63 {
64 delete fNodes;
65 }
66
67
68 // Init
69 status_t
Init()70 HaikuKernelVolume::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
80 status_t
NewVNode(ino_t vnodeID,void * privateNode,fs_vnode_ops * ops,HaikuKernelNode ** _node)81 HaikuKernelVolume::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
119 status_t
PublishVNode(ino_t vnodeID,void * privateNode,fs_vnode_ops * ops,int type,uint32 flags,HaikuKernelNode ** _node)120 HaikuKernelVolume::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
162 void
UndoNewVNode(HaikuKernelNode * node)163 HaikuKernelVolume::UndoNewVNode(HaikuKernelNode* node)
164 {
165 fNodes->Remove(node->id);
166 delete node;
167 }
168
169
170 // UndoPublishVNode
171 void
UndoPublishVNode(HaikuKernelNode * node)172 HaikuKernelVolume::UndoPublishVNode(HaikuKernelNode* node)
173 {
174 fNodes->Remove(node->id);
175 delete node;
176 }
177
178
179 // NodeWithID
180 HaikuKernelNode*
NodeWithID(ino_t vnodeID) const181 HaikuKernelVolume::NodeWithID(ino_t vnodeID) const
182 {
183 return fNodes->Get(vnodeID);
184 }
185
186
187 // #pragma mark -
188 // #pragma mark ----- FS -----
189
190 // Mount
191 status_t
Mount(const char * device,uint32 flags,const char * parameters,ino_t * rootID)192 HaikuKernelVolume::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
210 status_t
Unmount()211 HaikuKernelVolume::Unmount()
212 {
213 if (!fVolume.ops->unmount)
214 return B_BAD_VALUE;
215
216 return fVolume.ops->unmount(&fVolume);
217 }
218
219 // Sync
220 status_t
Sync()221 HaikuKernelVolume::Sync()
222 {
223 if (!fVolume.ops->sync)
224 return B_BAD_VALUE;
225 return fVolume.ops->sync(&fVolume);
226 }
227
228 // ReadFSInfo
229 status_t
ReadFSInfo(fs_info * info)230 HaikuKernelVolume::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
238 status_t
WriteFSInfo(const struct fs_info * info,uint32 mask)239 HaikuKernelVolume::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
251 status_t
GetFileMap(void * _node,off_t offset,size_t size,struct file_io_vec * vecs,size_t * count)252 HaikuKernelVolume::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
268 status_t
Lookup(void * _dir,const char * entryName,ino_t * vnid)269 HaikuKernelVolume::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
280 status_t
GetVNodeName(void * _node,char * buffer,size_t bufferSize)281 HaikuKernelVolume::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
293 status_t
ReadVNode(ino_t vnid,bool reenter,void ** _node,int * type,uint32 * flags,FSVNodeCapabilities * _capabilities)294 HaikuKernelVolume::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
347 status_t
WriteVNode(void * _node,bool reenter)348 HaikuKernelVolume::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
364 status_t
RemoveVNode(void * _node,bool reenter)365 HaikuKernelVolume::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
380 status_t
DoIO(void * _node,void * cookie,const IORequestInfo & requestInfo)381 HaikuKernelVolume::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
417 status_t
CancelIO(void * _node,void * cookie,int32 ioRequestID)418 HaikuKernelVolume::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
443 status_t
IterativeIOGetVecs(void * _cookie,int32 requestID,off_t offset,size_t size,struct file_io_vec * vecs,size_t * _count)444 HaikuKernelVolume::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
467 status_t
IterativeIOFinished(void * _cookie,int32 requestID,status_t status,bool partialTransfer,size_t bytesTransferred)468 HaikuKernelVolume::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
498 status_t
IOCtl(void * _node,void * cookie,uint32 command,void * buffer,size_t size)499 HaikuKernelVolume::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
511 status_t
SetFlags(void * _node,void * cookie,int flags)512 HaikuKernelVolume::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
522 status_t
Select(void * _node,void * cookie,uint8 event,selectsync * sync)523 HaikuKernelVolume::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
536 status_t
Deselect(void * _node,void * cookie,uint8 event,selectsync * sync)537 HaikuKernelVolume::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
548 status_t
FSync(void * _node)549 HaikuKernelVolume::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
559 status_t
ReadSymlink(void * _node,char * buffer,size_t bufferSize,size_t * bytesRead)560 HaikuKernelVolume::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
574 status_t
CreateSymlink(void * _dir,const char * name,const char * target,int mode)575 HaikuKernelVolume::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
586 status_t
Link(void * _dir,const char * name,void * _node)587 HaikuKernelVolume::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
598 status_t
Unlink(void * _dir,const char * name)599 HaikuKernelVolume::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
609 status_t
Rename(void * _oldDir,const char * oldName,void * _newDir,const char * newName)610 HaikuKernelVolume::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
622 status_t
Access(void * _node,int mode)623 HaikuKernelVolume::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
633 status_t
ReadStat(void * _node,struct stat * st)634 HaikuKernelVolume::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
644 status_t
WriteStat(void * _node,const struct stat * st,uint32 mask)645 HaikuKernelVolume::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
659 status_t
Create(void * _dir,const char * name,int openMode,int mode,void ** cookie,ino_t * vnid)660 HaikuKernelVolume::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
672 status_t
Open(void * _node,int openMode,void ** cookie)673 HaikuKernelVolume::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
683 status_t
Close(void * _node,void * cookie)684 HaikuKernelVolume::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
694 status_t
FreeCookie(void * _node,void * cookie)695 HaikuKernelVolume::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
705 status_t
Read(void * _node,void * cookie,off_t pos,void * buffer,size_t bufferSize,size_t * bytesRead)706 HaikuKernelVolume::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
720 status_t
Write(void * _node,void * cookie,off_t pos,const void * buffer,size_t bufferSize,size_t * bytesWritten)721 HaikuKernelVolume::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
740 status_t
CreateDir(void * _dir,const char * name,int mode)741 HaikuKernelVolume::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
751 status_t
RemoveDir(void * _dir,const char * name)752 HaikuKernelVolume::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
762 status_t
OpenDir(void * _node,void ** cookie)763 HaikuKernelVolume::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
773 status_t
CloseDir(void * _node,void * cookie)774 HaikuKernelVolume::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
784 status_t
FreeDirCookie(void * _node,void * cookie)785 HaikuKernelVolume::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
795 status_t
ReadDir(void * _node,void * cookie,void * buffer,size_t bufferSize,uint32 count,uint32 * countRead)796 HaikuKernelVolume::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
811 status_t
RewindDir(void * _node,void * cookie)812 HaikuKernelVolume::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
826 status_t
OpenAttrDir(void * _node,void ** cookie)827 HaikuKernelVolume::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
837 status_t
CloseAttrDir(void * _node,void * cookie)838 HaikuKernelVolume::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
848 status_t
FreeAttrDirCookie(void * _node,void * cookie)849 HaikuKernelVolume::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
859 status_t
ReadAttrDir(void * _node,void * cookie,void * buffer,size_t bufferSize,uint32 count,uint32 * countRead)860 HaikuKernelVolume::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
875 status_t
RewindAttrDir(void * _node,void * cookie)876 HaikuKernelVolume::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
890 status_t
CreateAttr(void * _node,const char * name,uint32 type,int openMode,void ** cookie)891 HaikuKernelVolume::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
903 status_t
OpenAttr(void * _node,const char * name,int openMode,void ** cookie)904 HaikuKernelVolume::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
915 status_t
CloseAttr(void * _node,void * cookie)916 HaikuKernelVolume::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
926 status_t
FreeAttrCookie(void * _node,void * cookie)927 HaikuKernelVolume::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
937 status_t
ReadAttr(void * _node,void * cookie,off_t pos,void * buffer,size_t bufferSize,size_t * bytesRead)938 HaikuKernelVolume::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
953 status_t
WriteAttr(void * _node,void * cookie,off_t pos,const void * buffer,size_t bufferSize,size_t * bytesWritten)954 HaikuKernelVolume::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
969 status_t
ReadAttrStat(void * _node,void * cookie,struct stat * st)970 HaikuKernelVolume::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
981 status_t
WriteAttrStat(void * _node,void * cookie,const struct stat * st,int statMask)982 HaikuKernelVolume::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
994 status_t
RenameAttr(void * _oldNode,const char * oldName,void * _newNode,const char * newName)995 HaikuKernelVolume::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
1008 status_t
RemoveAttr(void * _node,const char * name)1009 HaikuKernelVolume::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
1023 status_t
OpenIndexDir(void ** cookie)1024 HaikuKernelVolume::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
1032 status_t
CloseIndexDir(void * cookie)1033 HaikuKernelVolume::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
1041 status_t
FreeIndexDirCookie(void * cookie)1042 HaikuKernelVolume::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
1050 status_t
ReadIndexDir(void * cookie,void * buffer,size_t bufferSize,uint32 count,uint32 * countRead)1051 HaikuKernelVolume::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
1064 status_t
RewindIndexDir(void * cookie)1065 HaikuKernelVolume::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
1073 status_t
CreateIndex(const char * name,uint32 type,uint32 flags)1074 HaikuKernelVolume::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
1082 status_t
RemoveIndex(const char * name)1083 HaikuKernelVolume::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
1091 status_t
ReadIndexStat(const char * name,struct stat * st)1092 HaikuKernelVolume::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
1104 status_t
OpenQuery(const char * queryString,uint32 flags,port_id port,uint32 token,void ** cookie)1105 HaikuKernelVolume::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
1115 status_t
CloseQuery(void * cookie)1116 HaikuKernelVolume::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
1124 status_t
FreeQueryCookie(void * cookie)1125 HaikuKernelVolume::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
1133 status_t
ReadQuery(void * cookie,void * buffer,size_t bufferSize,uint32 count,uint32 * countRead)1134 HaikuKernelVolume::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
1147 status_t
RewindQuery(void * cookie)1148 HaikuKernelVolume::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
1156 void
_InitCapabilities()1157 HaikuKernelVolume::_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