14649fe05SIngo Weinhold/*
24649fe05SIngo Weinhold * Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
34649fe05SIngo Weinhold * Distributed under the terms of the MIT License.
44649fe05SIngo Weinhold */
54ed322c6SIngo Weinhold
64ed322c6SIngo Weinhold#include "HaikuKernelVolume.h"
74ed322c6SIngo Weinhold
84ed322c6SIngo Weinhold#include <new>
94ed322c6SIngo Weinhold
104ed322c6SIngo Weinhold#include <fcntl.h>
1198092e98SIngo Weinhold#include <string.h>
124ed322c6SIngo Weinhold#include <unistd.h>
134ed322c6SIngo Weinhold
14c74777f3SIngo Weinhold#include "AutoDeleter.h"
15c74777f3SIngo Weinhold#include "AutoLocker.h"
164ed322c6SIngo Weinhold#include "Debug.h"
17c74777f3SIngo Weinhold#include "HashMap.h"
183b8f138fSIngo Weinhold
19f1c6ce08SIngo Weinhold#include "../IORequestInfo.h"
203b8f138fSIngo Weinhold#include "../kernel_emu.h"
213b8f138fSIngo Weinhold
227c1ffcb9SIngo Weinhold#include "HaikuKernelFileSystem.h"
237c1ffcb9SIngo Weinhold#include "HaikuKernelIORequest.h"
24cdebdeb0SIngo Weinhold#include "HaikuKernelNode.h"
254ed322c6SIngo Weinhold
264ed322c6SIngo Weinhold
27c74777f3SIngo Weinhold// NodeMap
28c74777f3SIngo Weinholdclass HaikuKernelVolume::NodeMap
29de48af7aSAugustin Cavalier	: public SynchronizedHashMap<HashKey64<ino_t>, HaikuKernelNode*, Locker> {
30c74777f3SIngo Weinhold};
31c74777f3SIngo Weinhold
32c74777f3SIngo Weinhold
337c1ffcb9SIngo Weinhold// _FileSystem
347c1ffcb9SIngo Weinholdinline HaikuKernelFileSystem*
357c1ffcb9SIngo WeinholdHaikuKernelVolume::_FileSystem() const
367c1ffcb9SIngo Weinhold{
377c1ffcb9SIngo Weinhold	return static_cast<HaikuKernelFileSystem*>(fFileSystem);
387c1ffcb9SIngo Weinhold}
39f1c6ce08SIngo Weinhold
40f1c6ce08SIngo Weinhold
414ed322c6SIngo Weinhold// constructor
42245aecdaSAxel DörflerHaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
434ed322c6SIngo Weinhold	file_system_module_info* fsModule)
44c74777f3SIngo Weinhold	:
45c74777f3SIngo Weinhold	Volume(fileSystem, id),
46c74777f3SIngo Weinhold	fFSModule(fsModule),
477c1ffcb9SIngo Weinhold	fNodes(NULL)
484ed322c6SIngo Weinhold{
49cdebdeb0SIngo Weinhold	fVolume.id = id;
50cdebdeb0SIngo Weinhold	fVolume.partition = -1;
51cdebdeb0SIngo Weinhold	fVolume.layer = 0;
52cdebdeb0SIngo Weinhold	fVolume.private_volume = NULL;		// filled in by the FS
53cdebdeb0SIngo Weinhold	fVolume.ops = NULL;					// filled in by the FS
54cdebdeb0SIngo Weinhold	fVolume.sub_volume = NULL;
55cdebdeb0SIngo Weinhold	fVolume.super_volume = NULL;
56cdebdeb0SIngo Weinhold	fVolume.file_system = fFSModule;
577e6a04c7SIngo Weinhold	fVolume.file_system_name = const_cast<char*>(fileSystem->GetName());
58cdebdeb0SIngo Weinhold	fVolume.haikuVolume = this;
594ed322c6SIngo Weinhold}
604ed322c6SIngo Weinhold
614ed322c6SIngo Weinhold// destructor
624ed322c6SIngo WeinholdHaikuKernelVolume::~HaikuKernelVolume()
634ed322c6SIngo Weinhold{
64f1c6ce08SIngo Weinhold	delete fNodes;
654ed322c6SIngo Weinhold}
664ed322c6SIngo Weinhold
67b7d815f1SIngo Weinhold
68c74777f3SIngo Weinhold// Init
69c74777f3SIngo Weinholdstatus_t
70c74777f3SIngo WeinholdHaikuKernelVolume::Init()
71c74777f3SIngo Weinhold{
72c74777f3SIngo Weinhold	fNodes = new(std::nothrow) NodeMap;
73c74777f3SIngo Weinhold	if (fNodes == NULL)
74c74777f3SIngo Weinhold		return B_NO_MEMORY;
757c1ffcb9SIngo Weinhold	return fNodes->InitCheck();
76c74777f3SIngo Weinhold}
77c74777f3SIngo Weinhold
78c74777f3SIngo Weinhold
79b7d815f1SIngo Weinhold// NewVNode
80b7d815f1SIngo Weinholdstatus_t
81b7d815f1SIngo WeinholdHaikuKernelVolume::NewVNode(ino_t vnodeID, void* privateNode, fs_vnode_ops* ops,
82c74777f3SIngo Weinhold	HaikuKernelNode** _node)
83b7d815f1SIngo Weinhold{
84c74777f3SIngo Weinhold	AutoLocker<NodeMap> _(fNodes);
85c74777f3SIngo Weinhold
86c74777f3SIngo Weinhold	// check whether we do already know the node
87c74777f3SIngo Weinhold	HaikuKernelNode* node = fNodes->Get(vnodeID);
88c74777f3SIngo Weinhold	if (node != NULL)
89c74777f3SIngo Weinhold		return B_BAD_VALUE;
90c74777f3SIngo Weinhold
914649fe05SIngo Weinhold	// get node capabilities
924649fe05SIngo Weinhold	HaikuKernelNode::Capabilities* capabilities
934649fe05SIngo Weinhold		= _FileSystem()->GetNodeCapabilities(ops);
944649fe05SIngo Weinhold	if (capabilities == NULL)
954649fe05SIngo Weinhold		return B_NO_MEMORY;
964649fe05SIngo Weinhold
97c74777f3SIngo Weinhold	// create a new node
984649fe05SIngo Weinhold	node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, ops,
994649fe05SIngo Weinhold		capabilities);
1004649fe05SIngo Weinhold	if (node == NULL) {
1014649fe05SIngo Weinhold		_FileSystem()->PutNodeCapabilities(capabilities);
102c74777f3SIngo Weinhold		return B_NO_MEMORY;
1034649fe05SIngo Weinhold	}
104c74777f3SIngo Weinhold
105c74777f3SIngo Weinhold	// add to map
106c74777f3SIngo Weinhold	status_t error = fNodes->Put(vnodeID, node);
107c74777f3SIngo Weinhold	if (error != B_OK) {
108c74777f3SIngo Weinhold		delete node;
109c74777f3SIngo Weinhold		return error;
110c74777f3SIngo Weinhold	}
111c74777f3SIngo Weinhold
112c74777f3SIngo Weinhold	*_node = node;
113c74777f3SIngo Weinhold
114c74777f3SIngo Weinhold	return B_OK;
115b7d815f1SIngo Weinhold}
116b7d815f1SIngo Weinhold
117b7d815f1SIngo Weinhold
118b7d815f1SIngo Weinhold// PublishVNode
119b7d815f1SIngo Weinholdstatus_t
120b7d815f1SIngo WeinholdHaikuKernelVolume::PublishVNode(ino_t vnodeID, void* privateNode,
121c74777f3SIngo Weinhold	fs_vnode_ops* ops, int type, uint32 flags, HaikuKernelNode** _node)
122b7d815f1SIngo Weinhold{
123c74777f3SIngo Weinhold	AutoLocker<NodeMap> _(fNodes);
124c74777f3SIngo Weinhold
125c74777f3SIngo Weinhold	// check whether we do already know the node
126c74777f3SIngo Weinhold	HaikuKernelNode* node = fNodes->Get(vnodeID);
127c74777f3SIngo Weinhold	if (node != NULL) {
128c74777f3SIngo Weinhold		if (node->published)
129c74777f3SIngo Weinhold			return B_BAD_VALUE;
130c74777f3SIngo Weinhold	} else {
1314649fe05SIngo Weinhold		// get node capabilities
1324649fe05SIngo Weinhold		HaikuKernelNode::Capabilities* capabilities
1334649fe05SIngo Weinhold			= _FileSystem()->GetNodeCapabilities(ops);
1344649fe05SIngo Weinhold		if (capabilities == NULL)
1354649fe05SIngo Weinhold			return B_NO_MEMORY;
1364649fe05SIngo Weinhold
137c74777f3SIngo Weinhold		// create a new node
138c74777f3SIngo Weinhold		node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode,
1394649fe05SIngo Weinhold			ops, capabilities);
1404649fe05SIngo Weinhold		if (node == NULL) {
1414649fe05SIngo Weinhold			_FileSystem()->PutNodeCapabilities(capabilities);
142c74777f3SIngo Weinhold			return B_NO_MEMORY;
1434649fe05SIngo Weinhold		}
144c74777f3SIngo Weinhold
145c74777f3SIngo Weinhold		// add to map
146c74777f3SIngo Weinhold		status_t error = fNodes->Put(vnodeID, node);
147c74777f3SIngo Weinhold		if (error != B_OK) {
148c74777f3SIngo Weinhold			delete node;
149c74777f3SIngo Weinhold			return error;
150c74777f3SIngo Weinhold		}
151c74777f3SIngo Weinhold	}
152c74777f3SIngo Weinhold
153c74777f3SIngo Weinhold	node->published = true;
154c74777f3SIngo Weinhold
155c74777f3SIngo Weinhold	*_node = node;
156c74777f3SIngo Weinhold
157c74777f3SIngo Weinhold	return B_OK;
158b7d815f1SIngo Weinhold}
159b7d815f1SIngo Weinhold
160b7d815f1SIngo Weinhold
161b7d815f1SIngo Weinhold// UndoNewVNode
162c74777f3SIngo Weinholdvoid
163b7d815f1SIngo WeinholdHaikuKernelVolume::UndoNewVNode(HaikuKernelNode* node)
164b7d815f1SIngo Weinhold{
165c74777f3SIngo Weinhold	fNodes->Remove(node->id);
166c74777f3SIngo Weinhold	delete node;
167b7d815f1SIngo Weinhold}
168b7d815f1SIngo Weinhold
169b7d815f1SIngo Weinhold
170b7d815f1SIngo Weinhold// UndoPublishVNode
171c74777f3SIngo Weinholdvoid
172b7d815f1SIngo WeinholdHaikuKernelVolume::UndoPublishVNode(HaikuKernelNode* node)
173b7d815f1SIngo Weinhold{
174c74777f3SIngo Weinhold	fNodes->Remove(node->id);
175c74777f3SIngo Weinhold	delete node;
176b7d815f1SIngo Weinhold}
177b7d815f1SIngo Weinhold
178b7d815f1SIngo Weinhold
17902f7a2f4SIngo Weinhold// NodeWithID
18002f7a2f4SIngo WeinholdHaikuKernelNode*
18102f7a2f4SIngo WeinholdHaikuKernelVolume::NodeWithID(ino_t vnodeID) const
18202f7a2f4SIngo Weinhold{
18302f7a2f4SIngo Weinhold	return fNodes->Get(vnodeID);
18402f7a2f4SIngo Weinhold}
18502f7a2f4SIngo Weinhold
18602f7a2f4SIngo Weinhold
1874ed322c6SIngo Weinhold// #pragma mark -
1884ed322c6SIngo Weinhold// #pragma mark ----- FS -----
1894ed322c6SIngo Weinhold
1904ed322c6SIngo Weinhold// Mount
1914ed322c6SIngo Weinholdstatus_t
1924ed322c6SIngo WeinholdHaikuKernelVolume::Mount(const char* device, uint32 flags,
193245aecdaSAxel Dörfler	const char* parameters, ino_t* rootID)
1944ed322c6SIngo Weinhold{
1954ed322c6SIngo Weinhold	if (!fFSModule->mount)
1964ed322c6SIngo Weinhold		return B_BAD_VALUE;
1977a4de3f1SIngo Weinhold
1987a4de3f1SIngo Weinhold	// mount
19967cf3a62SIngo Weinhold	status_t error = fFSModule->mount(&fVolume, device, flags, parameters,
20067cf3a62SIngo Weinhold		rootID);
20167cf3a62SIngo Weinhold	if (error != B_OK)
2027a4de3f1SIngo Weinhold		return error;
2037a4de3f1SIngo Weinhold
204cdebdeb0SIngo Weinhold	_InitCapabilities();
205cdebdeb0SIngo Weinhold
2067a4de3f1SIngo Weinhold	return B_OK;
2074ed322c6SIngo Weinhold}
2084ed322c6SIngo Weinhold
2094ed322c6SIngo Weinhold// Unmount
2104ed322c6SIngo Weinholdstatus_t
2114ed322c6SIngo WeinholdHaikuKernelVolume::Unmount()
2124ed322c6SIngo Weinhold{
213cdebdeb0SIngo Weinhold	if (!fVolume.ops->unmount)
2144ed322c6SIngo Weinhold		return B_BAD_VALUE;
2157a4de3f1SIngo Weinhold
21667cf3a62SIngo Weinhold	return fVolume.ops->unmount(&fVolume);
2174ed322c6SIngo Weinhold}
2184ed322c6SIngo Weinhold
2194ed322c6SIngo Weinhold// Sync
2204ed322c6SIngo Weinholdstatus_t
2214ed322c6SIngo WeinholdHaikuKernelVolume::Sync()
2224ed322c6SIngo Weinhold{
223cdebdeb0SIngo Weinhold	if (!fVolume.ops->sync)
2244ed322c6SIngo Weinhold		return B_BAD_VALUE;
225cdebdeb0SIngo Weinhold	return fVolume.ops->sync(&fVolume);
2264ed322c6SIngo Weinhold}
2274ed322c6SIngo Weinhold
2284ed322c6SIngo Weinhold// ReadFSInfo
2294ed322c6SIngo Weinholdstatus_t
2304ed322c6SIngo WeinholdHaikuKernelVolume::ReadFSInfo(fs_info* info)
2314ed322c6SIngo Weinhold{
232cdebdeb0SIngo Weinhold	if (!fVolume.ops->read_fs_info)
2334ed322c6SIngo Weinhold		return B_BAD_VALUE;
234cdebdeb0SIngo Weinhold	return fVolume.ops->read_fs_info(&fVolume, info);
2354ed322c6SIngo Weinhold}
2364ed322c6SIngo Weinhold
2374ed322c6SIngo Weinhold// WriteFSInfo
2384ed322c6SIngo Weinholdstatus_t
2394ed322c6SIngo WeinholdHaikuKernelVolume::WriteFSInfo(const struct fs_info* info, uint32 mask)
2404ed322c6SIngo Weinhold{
241cdebdeb0SIngo Weinhold	if (!fVolume.ops->write_fs_info)
2424ed322c6SIngo Weinhold		return B_BAD_VALUE;
243cdebdeb0SIngo Weinhold	return fVolume.ops->write_fs_info(&fVolume, info, mask);
2444ed322c6SIngo Weinhold}
2454ed322c6SIngo Weinhold
2464ed322c6SIngo Weinhold
2477a4de3f1SIngo Weinhold// #pragma mark - file cache
2487a4de3f1SIngo Weinhold
2497a4de3f1SIngo Weinhold
2507a4de3f1SIngo Weinhold// GetFileMap
2517a4de3f1SIngo Weinholdstatus_t
252cdebdeb0SIngo WeinholdHaikuKernelVolume::GetFileMap(void* _node, off_t offset, size_t size,
2537a4de3f1SIngo Weinhold	struct file_io_vec* vecs, size_t* count)
2547a4de3f1SIngo Weinhold{
255cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
256cdebdeb0SIngo Weinhold
257cdebdeb0SIngo Weinhold	if (!node->ops->get_file_map)
2587a4de3f1SIngo Weinhold		return B_BAD_VALUE;
259cdebdeb0SIngo Weinhold	return node->ops->get_file_map(&fVolume, node, offset, size, vecs,
2607a4de3f1SIngo Weinhold		count);
2617a4de3f1SIngo Weinhold}
2627a4de3f1SIngo Weinhold
2637a4de3f1SIngo Weinhold
2644ed322c6SIngo Weinhold// #pragma mark - vnodes
2654ed322c6SIngo Weinhold
2664ed322c6SIngo Weinhold
2674ed322c6SIngo Weinhold// Lookup
2684ed322c6SIngo Weinholdstatus_t
269cdebdeb0SIngo WeinholdHaikuKernelVolume::Lookup(void* _dir, const char* entryName, ino_t* vnid)
2704ed322c6SIngo Weinhold{
271cdebdeb0SIngo Weinhold	HaikuKernelNode* dir = (HaikuKernelNode*)_dir;
272cdebdeb0SIngo Weinhold
273cdebdeb0SIngo Weinhold	if (!dir->ops->lookup)
2744ed322c6SIngo Weinhold		return B_BAD_VALUE;
275cdebdeb0SIngo Weinhold	return dir->ops->lookup(&fVolume, dir, entryName, vnid);
276cdebdeb0SIngo Weinhold
2774ed322c6SIngo Weinhold}
2784ed322c6SIngo Weinhold
279ed07b9c7SIngo Weinhold// GetVNodeName
280ed07b9c7SIngo Weinholdstatus_t
281cdebdeb0SIngo WeinholdHaikuKernelVolume::GetVNodeName(void* _node, char* buffer, size_t bufferSize)
282ed07b9c7SIngo Weinhold{
283cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
284cdebdeb0SIngo Weinhold
285ed07b9c7SIngo Weinhold	// If not implemented by the client file system, we invoke our super class
286ed07b9c7SIngo Weinhold	// version, which emulates the functionality.
287cdebdeb0SIngo Weinhold	if (!node->ops->get_vnode_name)
288cdebdeb0SIngo Weinhold		return Volume::GetVNodeName(_node, buffer, bufferSize);
289cdebdeb0SIngo Weinhold	return node->ops->get_vnode_name(&fVolume, node, buffer, bufferSize);
290ed07b9c7SIngo Weinhold}
291ed07b9c7SIngo Weinhold
2924ed322c6SIngo Weinhold// ReadVNode
2934ed322c6SIngo Weinholdstatus_t
294cdebdeb0SIngo WeinholdHaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
2954649fe05SIngo Weinhold	uint32* flags, FSVNodeCapabilities* _capabilities)
2964ed322c6SIngo Weinhold{
297cdebdeb0SIngo Weinhold	if (!fVolume.ops->get_vnode)
2984ed322c6SIngo Weinhold		return B_BAD_VALUE;
299cdebdeb0SIngo Weinhold
300c74777f3SIngo Weinhold	// create a new wrapper node and add it to the map
301c74777f3SIngo Weinhold	HaikuKernelNode* node = new(std::nothrow) HaikuKernelNode(this, vnid, NULL,
3024649fe05SIngo Weinhold		NULL, NULL);
303cdebdeb0SIngo Weinhold	if (node == NULL)
304cdebdeb0SIngo Weinhold		return B_NO_MEMORY;
305c74777f3SIngo Weinhold	ObjectDeleter<HaikuKernelNode> nodeDeleter(node);
306c74777f3SIngo Weinhold
307c74777f3SIngo Weinhold	AutoLocker<NodeMap> locker(fNodes);
308c74777f3SIngo Weinhold	if (fNodes->Get(vnid) != NULL)
309c74777f3SIngo Weinhold		return B_BAD_VALUE;
310c74777f3SIngo Weinhold
311c74777f3SIngo Weinhold	status_t error = fNodes->Put(vnid, node);
312c74777f3SIngo Weinhold	if (error != B_OK)
313c74777f3SIngo Weinhold		return error;
314c74777f3SIngo Weinhold
315c74777f3SIngo Weinhold	locker.Unlock();
316cdebdeb0SIngo Weinhold
317cdebdeb0SIngo Weinhold	// get the node
318c74777f3SIngo Weinhold	error = fVolume.ops->get_vnode(&fVolume, vnid, node, type, flags, reenter);
319cdebdeb0SIngo Weinhold	if (error != B_OK) {
320c74777f3SIngo Weinhold		locker.Lock();
321c74777f3SIngo Weinhold		fNodes->Remove(vnid);
322cdebdeb0SIngo Weinhold		return error;
323cdebdeb0SIngo Weinhold	}
324cdebdeb0SIngo Weinhold
3254649fe05SIngo Weinhold	// get node capabilities
3264649fe05SIngo Weinhold	HaikuKernelNode::Capabilities* capabilities
3274649fe05SIngo Weinhold		= _FileSystem()->GetNodeCapabilities(node->ops);
3284649fe05SIngo Weinhold	if (capabilities == NULL) {
3294649fe05SIngo Weinhold		node->ops->put_vnode(&fVolume, node, reenter);
3304649fe05SIngo Weinhold		locker.Lock();
3314649fe05SIngo Weinhold		fNodes->Remove(vnid);
3324649fe05SIngo Weinhold		return B_NO_MEMORY;
3334649fe05SIngo Weinhold	}
3344649fe05SIngo Weinhold
335c74777f3SIngo Weinhold	locker.Lock();
3364649fe05SIngo Weinhold	node->capabilities = capabilities;
337c74777f3SIngo Weinhold	node->published = true;
338c74777f3SIngo Weinhold	nodeDeleter.Detach();
339c74777f3SIngo Weinhold
340cdebdeb0SIngo Weinhold	*_node = node;
3414649fe05SIngo Weinhold	*_capabilities = capabilities->capabilities;
342c74777f3SIngo Weinhold
343cdebdeb0SIngo Weinhold	return B_OK;
3444ed322c6SIngo Weinhold}
3454ed322c6SIngo Weinhold
3464ed322c6SIngo Weinhold// WriteVNode
3474ed322c6SIngo Weinholdstatus_t
348cdebdeb0SIngo WeinholdHaikuKernelVolume::WriteVNode(void* _node, bool reenter)
3494ed322c6SIngo Weinhold{
350cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
351cdebdeb0SIngo Weinhold
352c74777f3SIngo Weinhold	fNodes->Remove(node->id);
353c74777f3SIngo Weinhold
354cdebdeb0SIngo Weinhold	if (!node->ops->put_vnode)
3554ed322c6SIngo Weinhold		return B_BAD_VALUE;
356cdebdeb0SIngo Weinhold	status_t error = node->ops->put_vnode(&fVolume, node, reenter);
357cdebdeb0SIngo Weinhold
358cdebdeb0SIngo Weinhold	delete node;
359cdebdeb0SIngo Weinhold
360cdebdeb0SIngo Weinhold	return error;
3614ed322c6SIngo Weinhold}
3624ed322c6SIngo Weinhold
3634ed322c6SIngo Weinhold// RemoveVNode
3644ed322c6SIngo Weinholdstatus_t
365cdebdeb0SIngo WeinholdHaikuKernelVolume::RemoveVNode(void* _node, bool reenter)
3664ed322c6SIngo Weinhold{
367cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
368cdebdeb0SIngo Weinhold
369c74777f3SIngo Weinhold	fNodes->Remove(node->id);
370c74777f3SIngo Weinhold
371cdebdeb0SIngo Weinhold	if (!node->ops->remove_vnode)
3724ed322c6SIngo Weinhold		return B_BAD_VALUE;
373cdebdeb0SIngo Weinhold	return node->ops->remove_vnode(&fVolume, node, reenter);
3744ed322c6SIngo Weinhold}
3754ed322c6SIngo Weinhold
3764ed322c6SIngo Weinhold
377f1c6ce08SIngo Weinhold// #pragma mark - asynchronous I/O
378f1c6ce08SIngo Weinhold
379f1c6ce08SIngo Weinhold
380f1c6ce08SIngo Weinholdstatus_t
3817c1ffcb9SIngo WeinholdHaikuKernelVolume::DoIO(void* _node, void* cookie,
3827c1ffcb9SIngo Weinhold	const IORequestInfo& requestInfo)
383f1c6ce08SIngo Weinhold{
384f1c6ce08SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
385f1c6ce08SIngo Weinhold
386f1c6ce08SIngo Weinhold	if (!node->ops->io)
387f1c6ce08SIngo Weinhold		return B_BAD_VALUE;
388f1c6ce08SIngo Weinhold
3897c1ffcb9SIngo Weinhold	// create a request object
3907c1ffcb9SIngo Weinhold	HaikuKernelIORequest* request
391687e02f9SIngo Weinhold		= new(std::nothrow) HaikuKernelIORequest(this, requestInfo);
3927c1ffcb9SIngo Weinhold	if (request == NULL)
3937c1ffcb9SIngo Weinhold		RETURN_ERROR(B_NO_MEMORY);
394f1c6ce08SIngo Weinhold
3957c1ffcb9SIngo Weinhold	status_t error = _FileSystem()->AddIORequest(request);
3967c1ffcb9SIngo Weinhold	if (error != B_OK) {
3977c1ffcb9SIngo Weinhold		delete request;
3987c1ffcb9SIngo Weinhold		RETURN_ERROR(error);
3997c1ffcb9SIngo Weinhold	}
400f1c6ce08SIngo Weinhold
401f1c6ce08SIngo Weinhold	// call the hook
4027c1ffcb9SIngo Weinhold	error = node->ops->io(&fVolume, node, cookie, (io_request*)request);
403f1c6ce08SIngo Weinhold
4047c1ffcb9SIngo Weinhold	// directly put our reference to the request, if the call failed
4057c1ffcb9SIngo Weinhold	if (error != B_OK) {
4067c1ffcb9SIngo Weinhold		_FileSystem()->PutIORequest(request);
4077c1ffcb9SIngo Weinhold		RETURN_ERROR(error);
4087c1ffcb9SIngo Weinhold	}
409f1c6ce08SIngo Weinhold
4107c1ffcb9SIngo Weinhold	// TODO: ATM we don't release our reference when the request is finished
4117c1ffcb9SIngo Weinhold	// normally!
4127c1ffcb9SIngo Weinhold
4137c1ffcb9SIngo Weinhold	return B_OK;
414f1c6ce08SIngo Weinhold}
415f1c6ce08SIngo Weinhold
416f1c6ce08SIngo Weinhold
417f1c6ce08SIngo Weinholdstatus_t
418f1c6ce08SIngo WeinholdHaikuKernelVolume::CancelIO(void* _node, void* cookie, int32 ioRequestID)
419f1c6ce08SIngo Weinhold{
420f1c6ce08SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
421f1c6ce08SIngo Weinhold
422f1c6ce08SIngo Weinhold	if (!node->ops->cancel_io)
423f1c6ce08SIngo Weinhold		return B_BAD_VALUE;
424f1c6ce08SIngo Weinhold
4257c1ffcb9SIngo Weinhold	// get the request
4267c1ffcb9SIngo Weinhold	HaikuKernelIORequest* request = _FileSystem()->GetIORequest(ioRequestID);
4277c1ffcb9SIngo Weinhold	if (request == NULL)
4287c1ffcb9SIngo Weinhold		RETURN_ERROR(B_BAD_VALUE);
4297c1ffcb9SIngo Weinhold
4307c1ffcb9SIngo Weinhold	// call the hook
4317c1ffcb9SIngo Weinhold	status_t error = node->ops->cancel_io(&fVolume, node, cookie,
4327c1ffcb9SIngo Weinhold		(io_request*)request);
4337c1ffcb9SIngo Weinhold
4347c1ffcb9SIngo Weinhold	// put the request -- once for the reference we got above, once for the
4357c1ffcb9SIngo Weinhold	// reference we've got in DoIO()
4367c1ffcb9SIngo Weinhold	_FileSystem()->PutIORequest(request, 2);
4377c1ffcb9SIngo Weinhold
4387c1ffcb9SIngo Weinhold	return error;
439f1c6ce08SIngo Weinhold}
440f1c6ce08SIngo Weinhold
441f1c6ce08SIngo Weinhold
442c76e8d36SIngo Weinhold// IterativeIOGetVecs
443c76e8d36SIngo Weinholdstatus_t
444c76e8d36SIngo WeinholdHaikuKernelVolume::IterativeIOGetVecs(void* _cookie, int32 requestID,
445c76e8d36SIngo Weinhold	off_t offset, size_t size, struct file_io_vec* vecs, size_t* _count)
446c76e8d36SIngo Weinhold{
447c76e8d36SIngo Weinhold	HaikuKernelIterativeFDIOCookie* cookie
448c76e8d36SIngo Weinhold		= (HaikuKernelIterativeFDIOCookie*)_cookie;
449c76e8d36SIngo Weinhold
450c76e8d36SIngo Weinhold	// get the request
451c76e8d36SIngo Weinhold	HaikuKernelIORequest* request = _FileSystem()->GetIORequest(requestID);
452c76e8d36SIngo Weinhold	if (request == NULL)
453c76e8d36SIngo Weinhold		RETURN_ERROR(B_BAD_VALUE);
454c76e8d36SIngo Weinhold
455c76e8d36SIngo Weinhold	// call the callback
456c76e8d36SIngo Weinhold	status_t error = cookie->getVecs(cookie->cookie, (io_request*)request,
457c76e8d36SIngo Weinhold		offset, size, vecs, _count);
458c76e8d36SIngo Weinhold
459c76e8d36SIngo Weinhold	// put the reference we got above
460c76e8d36SIngo Weinhold	_FileSystem()->PutIORequest(request, 1);
461c76e8d36SIngo Weinhold
462c76e8d36SIngo Weinhold	return error;
463c76e8d36SIngo Weinhold}
464c76e8d36SIngo Weinhold
465c76e8d36SIngo Weinhold
466c76e8d36SIngo Weinhold// IterativeIOFinished
467c76e8d36SIngo Weinholdstatus_t
468c76e8d36SIngo WeinholdHaikuKernelVolume::IterativeIOFinished(void* _cookie, int32 requestID,
469c76e8d36SIngo Weinhold	status_t status, bool partialTransfer, size_t bytesTransferred)
470c76e8d36SIngo Weinhold{
471c76e8d36SIngo Weinhold	HaikuKernelIterativeFDIOCookie* cookie
472c76e8d36SIngo Weinhold		= (HaikuKernelIterativeFDIOCookie*)_cookie;
473c76e8d36SIngo Weinhold
474c76e8d36SIngo Weinhold	// we're definitely done with the cookie, now
475c76e8d36SIngo Weinhold	ObjectDeleter<HaikuKernelIterativeFDIOCookie> _(cookie);
476c76e8d36SIngo Weinhold
477c76e8d36SIngo Weinhold	// get the request
478c76e8d36SIngo Weinhold	HaikuKernelIORequest* request = _FileSystem()->GetIORequest(requestID);
479c76e8d36SIngo Weinhold	if (request == NULL)
480c76e8d36SIngo Weinhold		RETURN_ERROR(B_BAD_VALUE);
481c76e8d36SIngo Weinhold
482c76e8d36SIngo Weinhold	// call the callback
483c76e8d36SIngo Weinhold	status_t error = cookie->finished(cookie->cookie, (io_request*)request,
484c76e8d36SIngo Weinhold		status, partialTransfer, bytesTransferred);
485c76e8d36SIngo Weinhold
486c76e8d36SIngo Weinhold	// We're done with the request, too, so put the reference we got above and
487c76e8d36SIngo Weinhold	// the one added by DoIO().
488c76e8d36SIngo Weinhold	_FileSystem()->PutIORequest(request, 2);
489c76e8d36SIngo Weinhold
490c76e8d36SIngo Weinhold	return error;
491c76e8d36SIngo Weinhold}
492c76e8d36SIngo Weinhold
493c76e8d36SIngo Weinhold
4944ed322c6SIngo Weinhold// #pragma mark - nodes
4954ed322c6SIngo Weinhold
4964ed322c6SIngo Weinhold
4974ed322c6SIngo Weinhold// IOCtl
4984ed322c6SIngo Weinholdstatus_t
499cdebdeb0SIngo WeinholdHaikuKernelVolume::IOCtl(void* _node, void* cookie, uint32 command,
5004ed322c6SIngo Weinhold	void* buffer, size_t size)
5014ed322c6SIngo Weinhold{
502cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
503cdebdeb0SIngo Weinhold
504cdebdeb0SIngo Weinhold	if (!node->ops->ioctl)
5054ed322c6SIngo Weinhold		return B_BAD_VALUE;
506cdebdeb0SIngo Weinhold	return node->ops->ioctl(&fVolume, node, cookie, command, buffer,
5074ed322c6SIngo Weinhold		size);
5084ed322c6SIngo Weinhold}
5094ed322c6SIngo Weinhold
5104ed322c6SIngo Weinhold// SetFlags
5114ed322c6SIngo Weinholdstatus_t
512cdebdeb0SIngo WeinholdHaikuKernelVolume::SetFlags(void* _node, void* cookie, int flags)
5134ed322c6SIngo Weinhold{
514cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
515cdebdeb0SIngo Weinhold
516cdebdeb0SIngo Weinhold	if (!node->ops->set_flags)
5174ed322c6SIngo Weinhold		return B_BAD_VALUE;
518cdebdeb0SIngo Weinhold	return node->ops->set_flags(&fVolume, node, cookie, flags);
5194ed322c6SIngo Weinhold}
5204ed322c6SIngo Weinhold
5214ed322c6SIngo Weinhold// Select
5224ed322c6SIngo Weinholdstatus_t
523cdebdeb0SIngo WeinholdHaikuKernelVolume::Select(void* _node, void* cookie, uint8 event,
524cdebdeb0SIngo Weinhold	selectsync* sync)
5254ed322c6SIngo Weinhold{
526cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
527cdebdeb0SIngo Weinhold
528cdebdeb0SIngo Weinhold	if (!node->ops->select) {
529636bfc08SIngo Weinhold		UserlandFS::KernelEmu::notify_select_event(sync, event, false);
5304ed322c6SIngo Weinhold		return B_OK;
5314ed322c6SIngo Weinhold	}
532cdebdeb0SIngo Weinhold	return node->ops->select(&fVolume, node, cookie, event, sync);
5334ed322c6SIngo Weinhold}
5344ed322c6SIngo Weinhold
5354ed322c6SIngo Weinhold// Deselect
5364ed322c6SIngo Weinholdstatus_t
537cdebdeb0SIngo WeinholdHaikuKernelVolume::Deselect(void* _node, void* cookie, uint8 event,
5384ed322c6SIngo Weinhold	selectsync* sync)
5394ed322c6SIngo Weinhold{
540cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
541cdebdeb0SIngo Weinhold
542cdebdeb0SIngo Weinhold	if (!node->ops->select || !node->ops->deselect)
5434ed322c6SIngo Weinhold		return B_OK;
544cdebdeb0SIngo Weinhold	return node->ops->deselect(&fVolume, node, cookie, event, sync);
5454ed322c6SIngo Weinhold}
5464ed322c6SIngo Weinhold
5474ed322c6SIngo Weinhold// FSync
5484ed322c6SIngo Weinholdstatus_t
549cdebdeb0SIngo WeinholdHaikuKernelVolume::FSync(void* _node)
5504ed322c6SIngo Weinhold{
551cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
552cdebdeb0SIngo Weinhold
553cdebdeb0SIngo Weinhold	if (!node->ops->fsync)
5544ed322c6SIngo Weinhold		return B_BAD_VALUE;
555cdebdeb0SIngo Weinhold	return node->ops->fsync(&fVolume, node);
5564ed322c6SIngo Weinhold}
5574ed322c6SIngo Weinhold
5584ed322c6SIngo Weinhold// ReadSymlink
5594ed322c6SIngo Weinholdstatus_t
560cdebdeb0SIngo WeinholdHaikuKernelVolume::ReadSymlink(void* _node, char* buffer, size_t bufferSize,
5614ed322c6SIngo Weinhold	size_t* bytesRead)
5624ed322c6SIngo Weinhold{
563cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
564cdebdeb0SIngo Weinhold
565cdebdeb0SIngo Weinhold	if (!node->ops->read_symlink)
5664ed322c6SIngo Weinhold		return B_BAD_VALUE;
5674ed322c6SIngo Weinhold
5684ed322c6SIngo Weinhold	*bytesRead = bufferSize;
5694ed322c6SIngo Weinhold
570cdebdeb0SIngo Weinhold	return node->ops->read_symlink(&fVolume, node, buffer, bytesRead);
5714ed322c6SIngo Weinhold}
5724ed322c6SIngo Weinhold
5734ed322c6SIngo Weinhold// CreateSymlink
5744ed322c6SIngo Weinholdstatus_t
575cdebdeb0SIngo WeinholdHaikuKernelVolume::CreateSymlink(void* _dir, const char* name,
5764ed322c6SIngo Weinhold	const char* target, int mode)
5774ed322c6SIngo Weinhold{
578cdebdeb0SIngo Weinhold	HaikuKernelNode* dir = (HaikuKernelNode*)_dir;
579cdebdeb0SIngo Weinhold
580cdebdeb0SIngo Weinhold	if (!dir->ops->create_symlink)
5814ed322c6SIngo Weinhold		return B_BAD_VALUE;
582cdebdeb0SIngo Weinhold	return dir->ops->create_symlink(&fVolume, dir, name, target, mode);
5834ed322c6SIngo Weinhold}
5844ed322c6SIngo Weinhold
5854ed322c6SIngo Weinhold// Link
5864ed322c6SIngo Weinholdstatus_t
587cdebdeb0SIngo WeinholdHaikuKernelVolume::Link(void* _dir, const char* name, void* _node)
5884ed322c6SIngo Weinhold{
589cdebdeb0SIngo Weinhold	HaikuKernelNode* dir = (HaikuKernelNode*)_dir;
590cdebdeb0SIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
591cdebdeb0SIngo Weinhold
592cdebdeb0SIngo Weinhold	if (!dir->ops->link)
5934ed322c6SIngo Weinhold		return B_BAD_VALUE;
594cdebdeb0SIngo Weinhold	return dir->ops->link(&fVolume, dir, name, node);
5954ed322c6SIngo Weinhold}
5964ed322c6SIngo Weinhold
5974ed322c6SIngo Weinhold// Unlink
5984ed322c6SIngo Weinholdstatus_t
599cdebdeb0SIngo WeinholdHaikuKernelVolume::Unlink(void* _dir, const char* name)
6004ed322c6SIngo Weinhold{
601cdebdeb0SIngo Weinhold	HaikuKernelNode* dir = (HaikuKernelNode*)_dir;
602cdebdeb0SIngo Weinhold
603cdebdeb0SIngo Weinhold	if (!dir->ops->unlink)
6044ed322c6SIngo Weinhold		return B_BAD_VALUE;
605cdebdeb0SIngo Weinhold	return dir->ops->unlink(&fVolume, dir, name);
6064ed322c6SIngo Weinhold}
6074ed322c6SIngo Weinhold
6084ed322c6SIngo Weinhold// Rename
6094ed322c6SIngo Weinholdstatus_t
610b19b5f9dSIngo WeinholdHaikuKernelVolume::Rename(void* _oldDir, const char* oldName, void* _newDir,
6114ed322c6SIngo Weinhold	const char* newName)
6124ed322c6SIngo Weinhold{
613b19b5f9dSIngo Weinhold	HaikuKernelNode* oldDir = (HaikuKernelNode*)_oldDir;
614b19b5f9dSIngo Weinhold	HaikuKernelNode* newDir = (HaikuKernelNode*)_newDir;
615b19b5f9dSIngo Weinhold
616b19b5f9dSIngo Weinhold	if (!oldDir->ops->rename)
6174ed322c6SIngo Weinhold		return B_BAD_VALUE;
618b19b5f9dSIngo Weinhold	return oldDir->ops->rename(&fVolume, oldDir, oldName, newDir, newName);
6194ed322c6SIngo Weinhold}
6204ed322c6SIngo Weinhold
6214ed322c6SIngo Weinhold// Access
6224ed322c6SIngo Weinholdstatus_t
623b19b5f9dSIngo WeinholdHaikuKernelVolume::Access(void* _node, int mode)
6244ed322c6SIngo Weinhold{
625b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
626b19b5f9dSIngo Weinhold
627b19b5f9dSIngo Weinhold	if (!node->ops->access)
6284ed322c6SIngo Weinhold		return B_OK;
629b19b5f9dSIngo Weinhold	return node->ops->access(&fVolume, node, mode);
6304ed322c6SIngo Weinhold}
6314ed322c6SIngo Weinhold
6324ed322c6SIngo Weinhold// ReadStat
6334ed322c6SIngo Weinholdstatus_t
634b19b5f9dSIngo WeinholdHaikuKernelVolume::ReadStat(void* _node, struct stat* st)
6354ed322c6SIngo Weinhold{
636b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
637b19b5f9dSIngo Weinhold
638b19b5f9dSIngo Weinhold	if (!node->ops->read_stat)
6394ed322c6SIngo Weinhold		return B_BAD_VALUE;
640b19b5f9dSIngo Weinhold	return node->ops->read_stat(&fVolume, node, st);
6414ed322c6SIngo Weinhold}
6424ed322c6SIngo Weinhold
6434ed322c6SIngo Weinhold// WriteStat
6444ed322c6SIngo Weinholdstatus_t
645b19b5f9dSIngo WeinholdHaikuKernelVolume::WriteStat(void* _node, const struct stat *st, uint32 mask)
6464ed322c6SIngo Weinhold{
647b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
648b19b5f9dSIngo Weinhold
649b19b5f9dSIngo Weinhold	if (!node->ops->write_stat)
6504ed322c6SIngo Weinhold		return B_BAD_VALUE;
651b19b5f9dSIngo Weinhold	return node->ops->write_stat(&fVolume, node, st, mask);
6524ed322c6SIngo Weinhold}
6534ed322c6SIngo Weinhold
6544ed322c6SIngo Weinhold
6554ed322c6SIngo Weinhold// #pragma mark - files
6564ed322c6SIngo Weinhold
6574ed322c6SIngo Weinhold
6584ed322c6SIngo Weinhold// Create
6594ed322c6SIngo Weinholdstatus_t
660b19b5f9dSIngo WeinholdHaikuKernelVolume::Create(void* _dir, const char* name, int openMode, int mode,
661cdebdeb0SIngo Weinhold	void** cookie, ino_t* vnid)
6624ed322c6SIngo Weinhold{
663b19b5f9dSIngo Weinhold	HaikuKernelNode* dir = (HaikuKernelNode*)_dir;
664b19b5f9dSIngo Weinhold
665b19b5f9dSIngo Weinhold	if (!dir->ops->create)
6664ed322c6SIngo Weinhold		return B_BAD_VALUE;
667b19b5f9dSIngo Weinhold	return dir->ops->create(&fVolume, dir, name, openMode, mode, cookie,
6684ed322c6SIngo Weinhold		vnid);
6694ed322c6SIngo Weinhold}
6704ed322c6SIngo Weinhold
6714ed322c6SIngo Weinhold// Open
6724ed322c6SIngo Weinholdstatus_t
673b19b5f9dSIngo WeinholdHaikuKernelVolume::Open(void* _node, int openMode, void** cookie)
6744ed322c6SIngo Weinhold{
675b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
676b19b5f9dSIngo Weinhold
677b19b5f9dSIngo Weinhold	if (!node->ops->open)
6784ed322c6SIngo Weinhold		return B_BAD_VALUE;
679b19b5f9dSIngo Weinhold	return node->ops->open(&fVolume, node, openMode, cookie);
6804ed322c6SIngo Weinhold}
6814ed322c6SIngo Weinhold
6824ed322c6SIngo Weinhold// Close
6834ed322c6SIngo Weinholdstatus_t
684b19b5f9dSIngo WeinholdHaikuKernelVolume::Close(void* _node, void* cookie)
6854ed322c6SIngo Weinhold{
686b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
687b19b5f9dSIngo Weinhold
688b19b5f9dSIngo Weinhold	if (!node->ops->close)
6894ed322c6SIngo Weinhold		return B_OK;
690b19b5f9dSIngo Weinhold	return node->ops->close(&fVolume, node, cookie);
6914ed322c6SIngo Weinhold}
6924ed322c6SIngo Weinhold
6934ed322c6SIngo Weinhold// FreeCookie
6944ed322c6SIngo Weinholdstatus_t
695b19b5f9dSIngo WeinholdHaikuKernelVolume::FreeCookie(void* _node, void* cookie)
6964ed322c6SIngo Weinhold{
697b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
698b19b5f9dSIngo Weinhold
699b19b5f9dSIngo Weinhold	if (!node->ops->free_cookie)
7004ed322c6SIngo Weinhold		return B_OK;
701b19b5f9dSIngo Weinhold	return node->ops->free_cookie(&fVolume, node, cookie);
7024ed322c6SIngo Weinhold}
7034ed322c6SIngo Weinhold
7044ed322c6SIngo Weinhold// Read
7054ed322c6SIngo Weinholdstatus_t
706b19b5f9dSIngo WeinholdHaikuKernelVolume::Read(void* _node, void* cookie, off_t pos, void* buffer,
7074ed322c6SIngo Weinhold	size_t bufferSize, size_t* bytesRead)
7084ed322c6SIngo Weinhold{
709b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
710b19b5f9dSIngo Weinhold
711b19b5f9dSIngo Weinhold	if (!node->ops->read)
7124ed322c6SIngo Weinhold		return B_BAD_VALUE;
7134ed322c6SIngo Weinhold
7144ed322c6SIngo Weinhold	*bytesRead = bufferSize;
7154ed322c6SIngo Weinhold
716b19b5f9dSIngo Weinhold	return node->ops->read(&fVolume, node, cookie, pos, buffer, bytesRead);
7174ed322c6SIngo Weinhold}
7184ed322c6SIngo Weinhold
7194ed322c6SIngo Weinhold// Write
7204ed322c6SIngo Weinholdstatus_t
721b19b5f9dSIngo WeinholdHaikuKernelVolume::Write(void* _node, void* cookie, off_t pos,
7224ed322c6SIngo Weinhold	const void* buffer, size_t bufferSize, size_t* bytesWritten)
7234ed322c6SIngo Weinhold{
724b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
725b19b5f9dSIngo Weinhold
726b19b5f9dSIngo Weinhold	if (!node->ops->write)
7274ed322c6SIngo Weinhold		return B_BAD_VALUE;
7284ed322c6SIngo Weinhold
7294ed322c6SIngo Weinhold	*bytesWritten = bufferSize;
7304ed322c6SIngo Weinhold
731b19b5f9dSIngo Weinhold	return node->ops->write(&fVolume, node, cookie, pos, buffer,
7324ed322c6SIngo Weinhold		bytesWritten);
7334ed322c6SIngo Weinhold}
7344ed322c6SIngo Weinhold
7354ed322c6SIngo Weinhold
7364ed322c6SIngo Weinhold// #pragma mark -  directories
7374ed322c6SIngo Weinhold
7384ed322c6SIngo Weinhold
7394ed322c6SIngo Weinhold// CreateDir
7404ed322c6SIngo Weinholdstatus_t
7413cf43c26SIngo WeinholdHaikuKernelVolume::CreateDir(void* _dir, const char* name, int mode)
7424ed322c6SIngo Weinhold{
743b19b5f9dSIngo Weinhold	HaikuKernelNode* dir = (HaikuKernelNode*)_dir;
744b19b5f9dSIngo Weinhold
745b19b5f9dSIngo Weinhold	if (!dir->ops->create_dir)
7464ed322c6SIngo Weinhold		return B_BAD_VALUE;
7473cf43c26SIngo Weinhold	return dir->ops->create_dir(&fVolume, dir, name, mode);
7484ed322c6SIngo Weinhold}
7494ed322c6SIngo Weinhold
7504ed322c6SIngo Weinhold// RemoveDir
7514ed322c6SIngo Weinholdstatus_t
752b19b5f9dSIngo WeinholdHaikuKernelVolume::RemoveDir(void* _dir, const char* name)
7534ed322c6SIngo Weinhold{
754b19b5f9dSIngo Weinhold	HaikuKernelNode* dir = (HaikuKernelNode*)_dir;
755b19b5f9dSIngo Weinhold
756b19b5f9dSIngo Weinhold	if (!dir->ops->remove_dir)
7574ed322c6SIngo Weinhold		return B_BAD_VALUE;
758b19b5f9dSIngo Weinhold	return dir->ops->remove_dir(&fVolume, dir, name);
7594ed322c6SIngo Weinhold}
7604ed322c6SIngo Weinhold
7614ed322c6SIngo Weinhold// OpenDir
7624ed322c6SIngo Weinholdstatus_t
763b19b5f9dSIngo WeinholdHaikuKernelVolume::OpenDir(void* _node, void** cookie)
7644ed322c6SIngo Weinhold{
765b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
766b19b5f9dSIngo Weinhold
767b19b5f9dSIngo Weinhold	if (!node->ops->open_dir)
7684ed322c6SIngo Weinhold		return B_BAD_VALUE;
769b19b5f9dSIngo Weinhold	return node->ops->open_dir(&fVolume, node, cookie);
7704ed322c6SIngo Weinhold}
7714ed322c6SIngo Weinhold
7724ed322c6SIngo Weinhold// CloseDir
7734ed322c6SIngo Weinholdstatus_t
774b19b5f9dSIngo WeinholdHaikuKernelVolume::CloseDir(void* _node, void* cookie)
7754ed322c6SIngo Weinhold{
776b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
777b19b5f9dSIngo Weinhold
778b19b5f9dSIngo Weinhold	if (!node->ops->close_dir)
7794ed322c6SIngo Weinhold		return B_OK;
780b19b5f9dSIngo Weinhold	return node->ops->close_dir(&fVolume, node, cookie);
7814ed322c6SIngo Weinhold}
7824ed322c6SIngo Weinhold
7834ed322c6SIngo Weinhold// FreeDirCookie
7844ed322c6SIngo Weinholdstatus_t
785b19b5f9dSIngo WeinholdHaikuKernelVolume::FreeDirCookie(void* _node, void* cookie)
7864ed322c6SIngo Weinhold{
787b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
788b19b5f9dSIngo Weinhold
789b19b5f9dSIngo Weinhold	if (!node->ops->free_dir_cookie)
7904ed322c6SIngo Weinhold		return B_OK;
791b19b5f9dSIngo Weinhold	return node->ops->free_dir_cookie(&fVolume, node, cookie);
7924ed322c6SIngo Weinhold}
7934ed322c6SIngo Weinhold
7944ed322c6SIngo Weinhold// ReadDir
7954ed322c6SIngo Weinholdstatus_t
796b19b5f9dSIngo WeinholdHaikuKernelVolume::ReadDir(void* _node, void* cookie, void* buffer,
7974ed322c6SIngo Weinhold	size_t bufferSize, uint32 count, uint32* countRead)
7984ed322c6SIngo Weinhold{
799b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
800b19b5f9dSIngo Weinhold
801b19b5f9dSIngo Weinhold	if (!node->ops->read_dir)
8024ed322c6SIngo Weinhold		return B_BAD_VALUE;
8034ed322c6SIngo Weinhold
8044ed322c6SIngo Weinhold	*countRead = count;
8054ed322c6SIngo Weinhold
806b19b5f9dSIngo Weinhold	return node->ops->read_dir(&fVolume, node, cookie,
8074ed322c6SIngo Weinhold		(struct dirent*)buffer, bufferSize, countRead);
8084ed322c6SIngo Weinhold}
8094ed322c6SIngo Weinhold
8104ed322c6SIngo Weinhold// RewindDir
8114ed322c6SIngo Weinholdstatus_t
812b19b5f9dSIngo WeinholdHaikuKernelVolume::RewindDir(void* _node, void* cookie)
8134ed322c6SIngo Weinhold{
814b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
815b19b5f9dSIngo Weinhold
816b19b5f9dSIngo Weinhold	if (!node->ops->rewind_dir)
8174ed322c6SIngo Weinhold		return B_BAD_VALUE;
818b19b5f9dSIngo Weinhold	return node->ops->rewind_dir(&fVolume, node, cookie);
8194ed322c6SIngo Weinhold}
8204ed322c6SIngo Weinhold
8214ed322c6SIngo Weinhold
8224ed322c6SIngo Weinhold// #pragma mark - attribute directories
8234ed322c6SIngo Weinhold
8244ed322c6SIngo Weinhold
8254ed322c6SIngo Weinhold// OpenAttrDir
8264ed322c6SIngo Weinholdstatus_t
827b19b5f9dSIngo WeinholdHaikuKernelVolume::OpenAttrDir(void* _node, void** cookie)
8284ed322c6SIngo Weinhold{
829b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
830b19b5f9dSIngo Weinhold
831b19b5f9dSIngo Weinhold	if (!node->ops->open_attr_dir)
8324ed322c6SIngo Weinhold		return B_BAD_VALUE;
833b19b5f9dSIngo Weinhold	return node->ops->open_attr_dir(&fVolume, node, cookie);
8344ed322c6SIngo Weinhold}
8354ed322c6SIngo Weinhold
8364ed322c6SIngo Weinhold// CloseAttrDir
8374ed322c6SIngo Weinholdstatus_t
838b19b5f9dSIngo WeinholdHaikuKernelVolume::CloseAttrDir(void* _node, void* cookie)
8394ed322c6SIngo Weinhold{
840b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
841b19b5f9dSIngo Weinhold
842b19b5f9dSIngo Weinhold	if (!node->ops->close_attr_dir)
8434ed322c6SIngo Weinhold		return B_OK;
844b19b5f9dSIngo Weinhold	return node->ops->close_attr_dir(&fVolume, node, cookie);
8454ed322c6SIngo Weinhold}
8464ed322c6SIngo Weinhold
8474ed322c6SIngo Weinhold// FreeAttrDirCookie
8484ed322c6SIngo Weinholdstatus_t
849b19b5f9dSIngo WeinholdHaikuKernelVolume::FreeAttrDirCookie(void* _node, void* cookie)
8504ed322c6SIngo Weinhold{
851b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
852b19b5f9dSIngo Weinhold
853b19b5f9dSIngo Weinhold	if (!node->ops->free_attr_dir_cookie)
8544ed322c6SIngo Weinhold		return B_OK;
855b19b5f9dSIngo Weinhold	return node->ops->free_attr_dir_cookie(&fVolume, node, cookie);
8564ed322c6SIngo Weinhold}
8574ed322c6SIngo Weinhold
8584ed322c6SIngo Weinhold// ReadAttrDir
8594ed322c6SIngo Weinholdstatus_t
860b19b5f9dSIngo WeinholdHaikuKernelVolume::ReadAttrDir(void* _node, void* cookie, void* buffer,
8614ed322c6SIngo Weinhold	size_t bufferSize, uint32 count, uint32* countRead)
8624ed322c6SIngo Weinhold{
863b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
864b19b5f9dSIngo Weinhold
865b19b5f9dSIngo Weinhold	if (!node->ops->read_attr_dir)
8664ed322c6SIngo Weinhold		return B_BAD_VALUE;
8674ed322c6SIngo Weinhold
8684ed322c6SIngo Weinhold	*countRead = count;
8694ed322c6SIngo Weinhold
870b19b5f9dSIngo Weinhold	return node->ops->read_attr_dir(&fVolume, node, cookie,
8714ed322c6SIngo Weinhold		(struct dirent*)buffer, bufferSize, countRead);
8724ed322c6SIngo Weinhold}
8734ed322c6SIngo Weinhold
8744ed322c6SIngo Weinhold// RewindAttrDir
8754ed322c6SIngo Weinholdstatus_t
876b19b5f9dSIngo WeinholdHaikuKernelVolume::RewindAttrDir(void* _node, void* cookie)
8774ed322c6SIngo Weinhold{
878b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
879b19b5f9dSIngo Weinhold
880b19b5f9dSIngo Weinhold	if (!node->ops->rewind_attr_dir)
8814ed322c6SIngo Weinhold		return B_BAD_VALUE;
882b19b5f9dSIngo Weinhold	return node->ops->rewind_attr_dir(&fVolume, node, cookie);
8834ed322c6SIngo Weinhold}
8844ed322c6SIngo Weinhold
8854ed322c6SIngo Weinhold
8864ed322c6SIngo Weinhold// #pragma mark - attributes
8874ed322c6SIngo Weinhold
8884ed322c6SIngo Weinhold
8894ed322c6SIngo Weinhold// CreateAttr
8904ed322c6SIngo Weinholdstatus_t
891b19b5f9dSIngo WeinholdHaikuKernelVolume::CreateAttr(void* _node, const char* name, uint32 type,
892cdebdeb0SIngo Weinhold	int openMode, void** cookie)
8934ed322c6SIngo Weinhold{
894b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
895b19b5f9dSIngo Weinhold
896b19b5f9dSIngo Weinhold	if (!node->ops->create_attr)
8974ed322c6SIngo Weinhold		return B_BAD_VALUE;
898b19b5f9dSIngo Weinhold	return node->ops->create_attr(&fVolume, node, name, type, openMode,
8994ed322c6SIngo Weinhold		cookie);
9004ed322c6SIngo Weinhold}
9014ed322c6SIngo Weinhold
9024ed322c6SIngo Weinhold// OpenAttr
9034ed322c6SIngo Weinholdstatus_t
904b19b5f9dSIngo WeinholdHaikuKernelVolume::OpenAttr(void* _node, const char* name, int openMode,
905cdebdeb0SIngo Weinhold	void** cookie)
9064ed322c6SIngo Weinhold{
907b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
908b19b5f9dSIngo Weinhold
909b19b5f9dSIngo Weinhold	if (!node->ops->open_attr)
9104ed322c6SIngo Weinhold		return B_BAD_VALUE;
911b19b5f9dSIngo Weinhold	return node->ops->open_attr(&fVolume, node, name, openMode, cookie);
9124ed322c6SIngo Weinhold}
9134ed322c6SIngo Weinhold
9144ed322c6SIngo Weinhold// CloseAttr
9154ed322c6SIngo Weinholdstatus_t
916b19b5f9dSIngo WeinholdHaikuKernelVolume::CloseAttr(void* _node, void* cookie)
9174ed322c6SIngo Weinhold{
918b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
919b19b5f9dSIngo Weinhold
920b19b5f9dSIngo Weinhold	if (!node->ops->close_attr)
9214ed322c6SIngo Weinhold		return B_OK;
922b19b5f9dSIngo Weinhold	return node->ops->close_attr(&fVolume, node, cookie);
9234ed322c6SIngo Weinhold}
9244ed322c6SIngo Weinhold
9254ed322c6SIngo Weinhold// FreeAttrCookie
9264ed322c6SIngo Weinholdstatus_t
927b19b5f9dSIngo WeinholdHaikuKernelVolume::FreeAttrCookie(void* _node, void* cookie)
9284ed322c6SIngo Weinhold{
929b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
930b19b5f9dSIngo Weinhold
931b19b5f9dSIngo Weinhold	if (!node->ops->free_attr_cookie)
9324ed322c6SIngo Weinhold		return B_OK;
933b19b5f9dSIngo Weinhold	return node->ops->free_attr_cookie(&fVolume, node, cookie);
9344ed322c6SIngo Weinhold}
9354ed322c6SIngo Weinhold
9364ed322c6SIngo Weinhold// ReadAttr
9374ed322c6SIngo Weinholdstatus_t
938b19b5f9dSIngo WeinholdHaikuKernelVolume::ReadAttr(void* _node, void* cookie, off_t pos,
9394ed322c6SIngo Weinhold	void* buffer, size_t bufferSize, size_t* bytesRead)
9404ed322c6SIngo Weinhold{
941b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
942b19b5f9dSIngo Weinhold
943b19b5f9dSIngo Weinhold	if (!node->ops->read_attr)
9444ed322c6SIngo Weinhold		return B_BAD_VALUE;
9454ed322c6SIngo Weinhold
9464ed322c6SIngo Weinhold	*bytesRead = bufferSize;
9474ed322c6SIngo Weinhold
948b19b5f9dSIngo Weinhold	return node->ops->read_attr(&fVolume, node, cookie, pos, buffer,
9494ed322c6SIngo Weinhold		bytesRead);
9504ed322c6SIngo Weinhold}
9514ed322c6SIngo Weinhold
9524ed322c6SIngo Weinhold// WriteAttr
9534ed322c6SIngo Weinholdstatus_t
954b19b5f9dSIngo WeinholdHaikuKernelVolume::WriteAttr(void* _node, void* cookie, off_t pos,
9554ed322c6SIngo Weinhold	const void* buffer, size_t bufferSize, size_t* bytesWritten)
9564ed322c6SIngo Weinhold{
957b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
958b19b5f9dSIngo Weinhold
959b19b5f9dSIngo Weinhold	if (!node->ops->write_attr)
9604ed322c6SIngo Weinhold		return B_BAD_VALUE;
9614ed322c6SIngo Weinhold
9624ed322c6SIngo Weinhold	*bytesWritten = bufferSize;
9634ed322c6SIngo Weinhold
964b19b5f9dSIngo Weinhold	return node->ops->write_attr(&fVolume, node, cookie, pos, buffer,
9654ed322c6SIngo Weinhold		bytesWritten);
9664ed322c6SIngo Weinhold}
9674ed322c6SIngo Weinhold
9684ed322c6SIngo Weinhold// ReadAttrStat
9694ed322c6SIngo Weinholdstatus_t
970b19b5f9dSIngo WeinholdHaikuKernelVolume::ReadAttrStat(void* _node, void* cookie,
9714ed322c6SIngo Weinhold	struct stat *st)
9724ed322c6SIngo Weinhold{
973b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
974b19b5f9dSIngo Weinhold
975b19b5f9dSIngo Weinhold	if (!node->ops->read_attr_stat)
9764ed322c6SIngo Weinhold		return B_BAD_VALUE;
977b19b5f9dSIngo Weinhold	return node->ops->read_attr_stat(&fVolume, node, cookie, st);
9784ed322c6SIngo Weinhold}
9794ed322c6SIngo Weinhold
980ed07b9c7SIngo Weinhold// WriteAttrStat
981ed07b9c7SIngo Weinholdstatus_t
982b19b5f9dSIngo WeinholdHaikuKernelVolume::WriteAttrStat(void* _node, void* cookie,
983ed07b9c7SIngo Weinhold	const struct stat* st, int statMask)
984ed07b9c7SIngo Weinhold{
985b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
986b19b5f9dSIngo Weinhold
987b19b5f9dSIngo Weinhold	if (!node->ops->write_attr_stat)
988ed07b9c7SIngo Weinhold		return B_BAD_VALUE;
989b19b5f9dSIngo Weinhold	return node->ops->write_attr_stat(&fVolume, node, cookie, st,
990ed07b9c7SIngo Weinhold		statMask);
991ed07b9c7SIngo Weinhold}
992ed07b9c7SIngo Weinhold
9934ed322c6SIngo Weinhold// RenameAttr
9944ed322c6SIngo Weinholdstatus_t
995b19b5f9dSIngo WeinholdHaikuKernelVolume::RenameAttr(void* _oldNode, const char* oldName,
996b19b5f9dSIngo Weinhold	void* _newNode, const char* newName)
9974ed322c6SIngo Weinhold{
998b19b5f9dSIngo Weinhold	HaikuKernelNode* oldNode = (HaikuKernelNode*)_oldNode;
999b19b5f9dSIngo Weinhold	HaikuKernelNode* newNode = (HaikuKernelNode*)_newNode;
1000b19b5f9dSIngo Weinhold
1001b19b5f9dSIngo Weinhold	if (!oldNode->ops->rename_attr)
10024ed322c6SIngo Weinhold		return B_BAD_VALUE;
1003b19b5f9dSIngo Weinhold	return oldNode->ops->rename_attr(&fVolume, oldNode, oldName, newNode,
10044ed322c6SIngo Weinhold		newName);
10054ed322c6SIngo Weinhold}
10064ed322c6SIngo Weinhold
10074ed322c6SIngo Weinhold// RemoveAttr
10084ed322c6SIngo Weinholdstatus_t
1009b19b5f9dSIngo WeinholdHaikuKernelVolume::RemoveAttr(void* _node, const char* name)
10104ed322c6SIngo Weinhold{
1011b19b5f9dSIngo Weinhold	HaikuKernelNode* node = (HaikuKernelNode*)_node;
1012b19b5f9dSIngo Weinhold
1013b19b5f9dSIngo Weinhold	if (!node->ops->remove_attr)
10144ed322c6SIngo Weinhold		return B_BAD_VALUE;
1015b19b5f9dSIngo Weinhold	return node->ops->remove_attr(&fVolume, node, name);
10164ed322c6SIngo Weinhold}
10174ed322c6SIngo Weinhold
10184ed322c6SIngo Weinhold
10194ed322c6SIngo Weinhold// #pragma mark - indices
10204ed322c6SIngo Weinhold
10214ed322c6SIngo Weinhold
10224ed322c6SIngo Weinhold// OpenIndexDir
10234ed322c6SIngo Weinholdstatus_t
1024cdebdeb0SIngo WeinholdHaikuKernelVolume::OpenIndexDir(void** cookie)
10254ed322c6SIngo Weinhold{
1026cdebdeb0SIngo Weinhold	if (!fVolume.ops->open_index_dir)
10274ed322c6SIngo Weinhold		return B_BAD_VALUE;
1028cdebdeb0SIngo Weinhold	return fVolume.ops->open_index_dir(&fVolume, cookie);
10294ed322c6SIngo Weinhold}
10304ed322c6SIngo Weinhold
10314ed322c6SIngo Weinhold// CloseIndexDir
10324ed322c6SIngo Weinholdstatus_t
1033cdebdeb0SIngo WeinholdHaikuKernelVolume::CloseIndexDir(void* cookie)
10344ed322c6SIngo Weinhold{
1035cdebdeb0SIngo Weinhold	if (!fVolume.ops->close_index_dir)
10364ed322c6SIngo Weinhold		return B_OK;
1037cdebdeb0SIngo Weinhold	return fVolume.ops->close_index_dir(&fVolume, cookie);
10384ed322c6SIngo Weinhold}
10394ed322c6SIngo Weinhold
10404ed322c6SIngo Weinhold// FreeIndexDirCookie
10414ed322c6SIngo Weinholdstatus_t
1042cdebdeb0SIngo WeinholdHaikuKernelVolume::FreeIndexDirCookie(void* cookie)
10434ed322c6SIngo Weinhold{
1044cdebdeb0SIngo Weinhold	if (!fVolume.ops->free_index_dir_cookie)
10454ed322c6SIngo Weinhold		return B_OK;
1046cdebdeb0SIngo Weinhold	return fVolume.ops->free_index_dir_cookie(&fVolume, cookie);
10474ed322c6SIngo Weinhold}
10484ed322c6SIngo Weinhold
10494ed322c6SIngo Weinhold// ReadIndexDir
10504ed322c6SIngo Weinholdstatus_t
1051cdebdeb0SIngo WeinholdHaikuKernelVolume::ReadIndexDir(void* cookie, void* buffer,
10524ed322c6SIngo Weinhold	size_t bufferSize, uint32 count, uint32* countRead)
10534ed322c6SIngo Weinhold{
1054cdebdeb0SIngo Weinhold	if (!fVolume.ops->read_index_dir)
10554ed322c6SIngo Weinhold		return B_BAD_VALUE;
10564ed322c6SIngo Weinhold
10574ed322c6SIngo Weinhold	*countRead = count;
10584ed322c6SIngo Weinhold
1059cdebdeb0SIngo Weinhold	return fVolume.ops->read_index_dir(&fVolume, cookie,
10604ed322c6SIngo Weinhold		(struct dirent*)buffer, bufferSize, countRead);
10614ed322c6SIngo Weinhold}
10624ed322c6SIngo Weinhold
10634ed322c6SIngo Weinhold// RewindIndexDir
10644ed322c6SIngo Weinholdstatus_t
1065cdebdeb0SIngo WeinholdHaikuKernelVolume::RewindIndexDir(void* cookie)
10664ed322c6SIngo Weinhold{
1067cdebdeb0SIngo Weinhold	if (!fVolume.ops->rewind_index_dir)
10684ed322c6SIngo Weinhold		return B_BAD_VALUE;
1069cdebdeb0SIngo Weinhold	return fVolume.ops->rewind_index_dir(&fVolume, cookie);
10704ed322c6SIngo Weinhold}
10714ed322c6SIngo Weinhold
10724ed322c6SIngo Weinhold// CreateIndex
10734ed322c6SIngo Weinholdstatus_t
10744ed322c6SIngo WeinholdHaikuKernelVolume::CreateIndex(const char* name, uint32 type, uint32 flags)
10754ed322c6SIngo Weinhold{
1076cdebdeb0SIngo Weinhold	if (!fVolume.ops->create_index)
10774ed322c6SIngo Weinhold		return B_BAD_VALUE;
1078cdebdeb0SIngo Weinhold	return fVolume.ops->create_index(&fVolume, name, type, flags);
10794ed322c6SIngo Weinhold}
10804ed322c6SIngo Weinhold
10814ed322c6SIngo Weinhold// RemoveIndex
10824ed322c6SIngo Weinholdstatus_t
10834ed322c6SIngo WeinholdHaikuKernelVolume::RemoveIndex(const char* name)
10844ed322c6SIngo Weinhold{
1085cdebdeb0SIngo Weinhold	if (!fVolume.ops->remove_index)
10864ed322c6SIngo Weinhold		return B_BAD_VALUE;
1087cdebdeb0SIngo Weinhold	return fVolume.ops->remove_index(&fVolume, name);
10884ed322c6SIngo Weinhold}
10894ed322c6SIngo Weinhold
10904ed322c6SIngo Weinhold// StatIndex
10914ed322c6SIngo Weinholdstatus_t
10924ed322c6SIngo WeinholdHaikuKernelVolume::ReadIndexStat(const char *name, struct stat *st)
10934ed322c6SIngo Weinhold{
1094cdebdeb0SIngo Weinhold	if (!fVolume.ops->read_index_stat)
10954ed322c6SIngo Weinhold		return B_BAD_VALUE;
1096cdebdeb0SIngo Weinhold	return fVolume.ops->read_index_stat(&fVolume, name, st);
10974ed322c6SIngo Weinhold}
10984ed322c6SIngo Weinhold
10994ed322c6SIngo Weinhold
11004ed322c6SIngo Weinhold// #pragma mark - queries
11014ed322c6SIngo Weinhold
11024ed322c6SIngo Weinhold
11034ed322c6SIngo Weinhold// OpenQuery
11044ed322c6SIngo Weinholdstatus_t
11054ed322c6SIngo WeinholdHaikuKernelVolume::OpenQuery(const char* queryString, uint32 flags,
1106cdebdeb0SIngo Weinhold	port_id port, uint32 token, void** cookie)
11074ed322c6SIngo Weinhold{
1108cdebdeb0SIngo Weinhold	if (!fVolume.ops->open_query)
11094ed322c6SIngo Weinhold		return B_BAD_VALUE;
1110cdebdeb0SIngo Weinhold	return fVolume.ops->open_query(&fVolume, queryString, flags, port,
11114ed322c6SIngo Weinhold		token, cookie);
11124ed322c6SIngo Weinhold}
11134ed322c6SIngo Weinhold
11144ed322c6SIngo Weinhold// CloseQuery
11154ed322c6SIngo Weinholdstatus_t
1116cdebdeb0SIngo WeinholdHaikuKernelVolume::CloseQuery(void* cookie)
11174ed322c6SIngo Weinhold{
1118cdebdeb0SIngo Weinhold	if (!fVolume.ops->close_query)
11194ed322c6SIngo Weinhold		return B_OK;
1120cdebdeb0SIngo Weinhold	return fVolume.ops->close_query(&fVolume, cookie);
11214ed322c6SIngo Weinhold}
11224ed322c6SIngo Weinhold
11234ed322c6SIngo Weinhold// FreeQueryCookie
11244ed322c6SIngo Weinholdstatus_t
1125cdebdeb0SIngo WeinholdHaikuKernelVolume::FreeQueryCookie(void* cookie)
11264ed322c6SIngo Weinhold{
1127cdebdeb0SIngo Weinhold	if (!fVolume.ops->free_query_cookie)
11284ed322c6SIngo Weinhold		return B_OK;
1129cdebdeb0SIngo Weinhold	return fVolume.ops->free_query_cookie(&fVolume, cookie);
11304ed322c6SIngo Weinhold}
11314ed322c6SIngo Weinhold
11324ed322c6SIngo Weinhold// ReadQuery
11334ed322c6SIngo Weinholdstatus_t
1134cdebdeb0SIngo WeinholdHaikuKernelVolume::ReadQuery(void* cookie, void* buffer, size_t bufferSize,
11354ed322c6SIngo Weinhold	uint32 count, uint32* countRead)
11364ed322c6SIngo Weinhold{
1137cdebdeb0SIngo Weinhold	if (!fVolume.ops->read_query)
11384ed322c6SIngo Weinhold		return B_BAD_VALUE;
11394ed322c6SIngo Weinhold
11404ed322c6SIngo Weinhold	*countRead = count;
11414ed322c6SIngo Weinhold
1142cdebdeb0SIngo Weinhold	return fVolume.ops->read_query(&fVolume, cookie, (struct dirent*)buffer,
11434ed322c6SIngo Weinhold		bufferSize, countRead);
11444ed322c6SIngo Weinhold}
1145ed07b9c7SIngo Weinhold
1146ed07b9c7SIngo Weinhold// RewindQuery
1147ed07b9c7SIngo Weinholdstatus_t
1148cdebdeb0SIngo WeinholdHaikuKernelVolume::RewindQuery(void* cookie)
1149cdebdeb0SIngo Weinhold{
1150cdebdeb0SIngo Weinhold	if (!fVolume.ops->rewind_query)
1151cdebdeb0SIngo Weinhold		return B_BAD_VALUE;
1152cdebdeb0SIngo Weinhold	return fVolume.ops->rewind_query(&fVolume, cookie);
1153cdebdeb0SIngo Weinhold}
1154cdebdeb0SIngo Weinhold
1155cdebdeb0SIngo Weinhold// _InitCapabilities
1156cdebdeb0SIngo Weinholdvoid
1157cdebdeb0SIngo WeinholdHaikuKernelVolume::_InitCapabilities()
1158cdebdeb0SIngo Weinhold{
1159cdebdeb0SIngo Weinhold	fCapabilities.ClearAll();
1160cdebdeb0SIngo Weinhold
1161cdebdeb0SIngo Weinhold	// FS operations
1162cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_UNMOUNT, fVolume.ops->unmount);
1163cdebdeb0SIngo Weinhold
1164cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_FS_INFO,
1165cdebdeb0SIngo Weinhold		fVolume.ops->read_fs_info);
1166cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_WRITE_FS_INFO,
1167cdebdeb0SIngo Weinhold		fVolume.ops->write_fs_info);
1168cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_SYNC, fVolume.ops->sync);
1169cdebdeb0SIngo Weinhold
1170cdebdeb0SIngo Weinhold	// vnode operations
1171cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_GET_VNODE, fVolume.ops->get_vnode);
1172cdebdeb0SIngo Weinhold
1173cdebdeb0SIngo Weinhold	// index directory & index operations
1174cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_OPEN_INDEX_DIR,
1175cdebdeb0SIngo Weinhold		fVolume.ops->open_index_dir);
1176cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_CLOSE_INDEX_DIR,
1177cdebdeb0SIngo Weinhold		fVolume.ops->close_index_dir);
1178cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_FREE_INDEX_DIR_COOKIE,
1179cdebdeb0SIngo Weinhold		fVolume.ops->free_index_dir_cookie);
1180cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_INDEX_DIR,
1181cdebdeb0SIngo Weinhold		fVolume.ops->read_index_dir);
1182cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_REWIND_INDEX_DIR,
1183cdebdeb0SIngo Weinhold		fVolume.ops->rewind_index_dir);
1184cdebdeb0SIngo Weinhold
1185cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_CREATE_INDEX,
1186cdebdeb0SIngo Weinhold		fVolume.ops->create_index);
1187cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_REMOVE_INDEX,
1188cdebdeb0SIngo Weinhold		fVolume.ops->remove_index);
1189cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_INDEX_STAT,
1190cdebdeb0SIngo Weinhold		fVolume.ops->read_index_stat);
1191cdebdeb0SIngo Weinhold
1192cdebdeb0SIngo Weinhold	// query operations
1193cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_OPEN_QUERY, fVolume.ops->open_query);
1194cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_CLOSE_QUERY,
1195cdebdeb0SIngo Weinhold		fVolume.ops->close_query);
1196cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_FREE_QUERY_COOKIE,
1197cdebdeb0SIngo Weinhold		fVolume.ops->free_query_cookie);
1198cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_QUERY, fVolume.ops->read_query);
1199cdebdeb0SIngo Weinhold	fCapabilities.Set(FS_VOLUME_CAPABILITY_REWIND_QUERY,
1200cdebdeb0SIngo Weinhold		fVolume.ops->rewind_query);
1201ed07b9c7SIngo Weinhold}
1202