/*
 * Copyright 2007-2008 Haiku Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Ingo Weinhold <ingo_weinhold@gmx.de>
 *		Niels Sascha Reedijk <niels.reedijk@gmail.com>
 *		Axel Dörfler <axeld@pinc-software.de>
 *
 * Corresponds to:
 *		/trunk/headers/os/drivers/fs_interface.h rev 29781
 */

/*!
	\file fs_interface.h
	\ingroup drivers
	\ingroup libbe
	\brief Provides an interface for file system modules.

	See the \ref fs_modules "introduction to file system modules" for a guide on
	how to get started with writing file system modules.
*/

///// write_stat_mask //////
// TODO: These have been superseded by the B_STAT_* flags in <NodeMonitor.h>.
// Move the documentation there!

/*!
	\def B_STAT_SIZE_INSECURE
	\brief Flag for the fs_vnode_ops::write_stat hook indicating that the FS
		is allowed not to clear the additional space when enlarging a file.

	This flag was added because BFS doesn't support sparse files. It will be
	phased out, when it does.
*/


///// FS_WRITE_FSINFO_NAME /////

/*!
	\def FS_WRITE_FSINFO_NAME
	\brief Passed to fs_volume_ops::write_fs_info() to indicate that the name
		of the volume shall be changed.
*/

///// file_io_vec /////

/*!
	\struct file_io_vec
	\brief Structure that describes the io vector of a file.
*/

/*!
	\var off_t file_io_vec::offset
	\brief The offset within the file.
*/

/*!
	\var off_t file_io_vec::length
	\brief The length of the vector.
*/

///// B_CURRENT_FS_API_VERSION /////

/*!
	\def B_CURRENT_FS_API_VERSION
	\brief Constant that defines the version of the file system API that your
		filesystem conforms to.

	The module name that exports the interface to your file system has to
	end with this constant as in:
	\code "file_systems/myfs" B_CURRENT_FS_API_VERSION \endcode
*/


///// B_VNODE_PUBLISH_REMOVED /////

/*!
	\def B_VNODE_PUBLISH_REMOVED
	\brief Flag for publish_vnode() and fs_vnode_ops::create_special_node()
		indicating that the node shall be published in removed state (i.e. no
		entry refers to it).
*/

///// B_VNODE_DONT_CREATE_SPECIAL_SUB_NODE /////

/*!
	\def B_VNODE_DONT_CREATE_SPECIAL_SUB_NODE
	\brief Flag for publish_vnode() and fs_volume_ops::get_vnode()
		indicating that no subnodes shall be created for the node to publish
		the node shall be published.
*/


///// file_system_module_info /////


/*!
	\struct file_system_module_info
	\brief Kernel module interface for file systems.

	See the \ref fs_modules "introduction to file system modules" for an
	introduction to writing file systems.
*/

/*!
	\name Data members
*/

//! @{

/*!
	\var module_info file_system_module_info::info
	\brief Your module_info object which is required for all modules.
*/

/*!
	\var const char *file_system_module_info::pretty_name
	\brief A NULL-terminated string with a 'pretty' name for you file system.

	Note, if a system wide disk device type constant exists for your file
	system, it should equal this identifier.
*/

//! @}

/*!
	\name Scanning
*/

//! @{

/*!
	\fn float (*file_system_module_info::identify_partition)(int fd,
			partition_data *partition, void **cookie)
	\brief Undocumented. TODO.
*/

/*!
	\fn status_t (*file_system_module_info::scan_partition)(int fd,
			partition_data *partition, void *cookie)
	\brief Undocumented. TODO.
*/

/*!
	\fn void (*file_system_module_info::free_identify_partition_cookie)(
			partition_data *partition, void *cookie)
	\brief Undocumented. TODO.
*/

/*!
	\fn void (*file_system_module_info::free_partition_content_cookie)(
			partition_data *partition)
	\brief Undocumented. TODO.
*/

//! @}

/*!
	\name General Operations
*/

//! @{

/*!
	\fn status_t (*file_system_module_info::mount)(fs_volume *volume,
			const char *device, uint32 flags, const char *args,
			ino_t *_rootVnodeID)

	\brief Mount a volume according to the specified parameters.

	Invoked by the VFS when it has been requested to mount the volume. The FS is
	supposed to perform whatever one-time initialization is necessary for the
	volume. It is required to create a volume handle for the volume and pass it
	back in \a volume->private_volume and set \a volume->ops to the operation
	vector for the volume. Moreover it must invoke publish_vnode() for the root
	node of the volume and pass the ID of the volume back in \a _rootVnodeID.

	A disk-based FS will need to check whether \a device is not \c NULL, open
	it, and analyze whether the device or image file actually represents a
	volume of that FS type.

	If mounting the volume fails for whatever reason, the hook must return an
	error code other than \c B_OK. In this case all resources allocated by the
	hook must be freed before returning. If and only if \c B_OK is returned, the
	unmount() hook will be invoked at a later point when unmounting the volume.

	\param volume Object created by the VFS to represent the volume. Its
		\c private_volume and \c ops members must be set by the hooks. All other
		members are read-only for the FS.
	\param device The path to the device (or image file) representing the volume
		to be mounted. Can be \c NULL.
	\param flags Flags:
		- \c B_MOUNT_READ_ONLY: Mount the volume read-only.
	\param args Null-terminated string in driver settings format, containing FS
		specific parameters.
	\param _rootVnodeID Pointer to a pre-allocated variable the ID of the
		volume's root directory shall be written to.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name Capability Querying
*/

//! @{

/*!
	\fn bool (*file_system_module_info::validate_resize)(partition_data *partition, off_t *size)
	\brief Undocumented. TODO.
*/

/*!
	\fn bool (*file_system_module_info::validate_move)(partition_data *partition, off_t *start)
	\brief Undocumented. TODO.
*/

/*!
	\fn bool (*file_system_module_info::validate_set_content_name)(partition_data *partition,
			char *name)
	\brief Undocumented. TODO.
*/

/*!
	\fn bool (*file_system_module_info::validate_set_content_parameters)(partition_data *partition,
			const char *parameters)
	\brief Undocumented. TODO.
*/

/*!
	\fn bool (*file_system_module_info::validate_initialize)(partition_data *partition, char *name,
			const char *parameters)
	\brief Undocumented. TODO.
*/

//! @}

/*!
	\name Shadow Partition Modification
*/

//! @{

/*!
	\fn status_t (*file_system_module_info::shadow_changed)(partition_data *partition,
			uint32 operation)
	\brief Undocumented. TODO.
*/

//! @}

/*!
	\name Special Operations
*/

//! @{

/*!
	\fn status_t (*file_system_module_info::defragment)(int fd, partition_id partition,
			disk_job_id job)
	\brief Undocumented. TODO.
*/

/*!
	\fn status_t (*file_system_module_info::repair)(int fd, partition_id partition, bool checkOnly,
			disk_job_id job)
	\brief Undocumented. TODO.
*/

/*!
	\fn status_t (*file_system_module_info::resize)(int fd, partition_id partition, off_t size,
			disk_job_id job)
	\brief Undocumented. TODO.
*/

/*!
	\fn status_t (*file_system_module_info::move)(int fd, partition_id partition, off_t offset,
			disk_job_id job)
	\brief Undocumented. TODO.
*/

/*!
	\fn status_t (*file_system_module_info::set_content_name)(int fd, partition_id partition,
			const char *name, disk_job_id job)
	\brief Undocumented. TODO.
*/

/*!
	\fn status_t (*file_system_module_info::set_content_parameters)(int fd, partition_id partition,
			const char *parameters, disk_job_id job)
	\brief Undocumented. TODO.
*/

/*!
	\fn status_t (*file_system_module_info::initialize)(const char *partition, const char *name,
			const char *parameters, disk_job_id job)
	\brief Undocumented. TODO.
*/

//! @}


///// fs_volume_ops /////


/*!
	\struct fs_volume_ops
	\brief Operations vector for a volume.

	See the \ref fs_modules "introduction to file system modules" for an
	introduction to writing file systems.
*/

/*!
	\name General Operations
*/

//! @{

/*!
	\fn status_t (*fs_volume_ops::unmount)(fs_volume *volume)
	\brief Unmounts the given volume.

	Invoked by the VFS when it is asked to unmount the volume. The function must
	free all resources associated with the mounted volume, including the volume
	handle. Before unmount() is called, the VFS calls
	file_system_module_info::put_vnode() respectively
	file_system_module_info::remove_vnode() for each of the volume's nodes. That
	is although the mount() hook called publish_vnode() for the volume's root
	node, unmount() must not invoke put_vnode().

	\param volume The volume object.
	\return \c B_OK if everything went fine, another error code otherwise. The
		error code will be ignored, though.
*/

/*!
	\fn status_t (*fs_volume_ops::read_fs_info)(fs_volume *volume,
			struct fs_info *info)
	\brief Retrieves general information about the volume.

	The following fields of the \c fs_info structure need to be filled in:
	- \c flags: Flags applying to the volume, e.g. \c B_FS_IS_READONLY,
	  \c B_FS_HAS_ATTR, etc.
	- \c block_size: The size of blocks the volume data are organized in.
	  Meaningful mainly for disk-based FSs, other FSs should use some reasonable
	  value for computing \c total_blocks and \c free_blocks.
	- \c io_size: Preferred size of the buffers passed to read() and write().
	- \c total_blocks: Total number of blocks the volume contains.
	- \c free_blocks: Number of free blocks on the volume.
	- \c total_nodes: Maximal number of nodes the volume can contain. If there
	  is no such limitation use \c LONGLONG_MAX.
	- \c free_nodes: Number of additional nodes the volume could contain. If
	  there is no such limitation use \c LONGLONG_MAX.
	- \c volume_name: The name of the volume.

	The other values are filled in by the VFS.

	\param volume The volume object.
	\param info Pointer to a pre-allocated variable the FS info shall be written
		to.
	\return \c B_OK if everything went fine, another error code otherwise. The
		error code will be ignored, though.
*/

/*!
	\fn status_t (*fs_volume_ops::write_fs_info)(fs_volume *volume,
			const struct fs_info *info, uint32 mask)
	\brief Update filesystem information on the volume.

	You are requested to update certain information on the given volume. The
	supplied \a info contains the new values filled in for the \a mask.
	Currently, the only possible mask is solely the \c FS_WRITE_FSINFO_NAME,
	which asks you to update the volume name represented by the value
	\c volume_name in the \c fs_info struct.

	\param volume The volume object.
	\param info The structure that contains the new data.
	\param mask The values of the \a info that need to be updated.
	\return \c B_OK if everything went fine, if not, one of the error codes.
*/

/*!
	\fn status_t (*fs_volume_ops::sync)(fs_volume *volume)
	\brief Synchronize the cached data with the contents of the disk.

	The VFS layer sometimes wants you to synchronize any cached values with the
	data on the device.

	This currently only happens when the POSIX sync() function is invoked, for
	example via the "sync" command line tool.

	\param volume The volume object.
*/

/*!
	\fn status_t (*fs_volume_ops::get_vnode)(fs_volume *volume, ino_t id,
			fs_vnode *vnode, int *_type, uint32 *_flags, bool reenter)
	\brief Creates the private data handle to be associated with the node
		referred to by \a id.

	Invoked by the VFS when it creates the vnode for the respective node.
	When the VFS no longer needs the vnode in memory (for example when
	memory is becoming tight), it will your file_system_module_info::put_vnode(),
	or file_system_module_info::remove_vnode() in case the vnode has been
	marked removed.

	The hook has to initialize \a vnode->private_node with its handle created
	for the node and \a vnode->ops with the operation vector for the node. It
	also has to set \c *_type to the type of the node -- as in \c stat::st_mode
	(the non-type bits can, but do not need to be cleared) -- and \c *_flags to
	a bitwise OR of vnode flags to apply (cf. publish_vnode() for what flags
	bits are possible).

	\param volume The volume object.
	\param id The ID of the node.
	\param vnode Pointer to a node object to be initialized.
	\param _type Pointer to a variable to be set to the node's type.
	\param _flags Pointer to a variable to be set to flags to apply to the
		vnode.
	\param reenter \c true if the hook invocation has been caused by the FS
		itself, e.g. by invoking ::get_vnode().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name Index Directory and Operation
*/

//! @{

/*!
	\fn status_t (*fs_volume_ops::open_index_dir)(fs_volume *volume,
			void **_cookie)
	\brief Open the list of an indices as a directory.

	See \ref concepts "Generic Concepts" on directories and iterators.
	Basically, the VFS uses the same way of traversing through indeces as it
	traverses through a directory.

	\param volume The volume object.
	\param[out] _cookie Pointer where the file system can store a directory
		cookie if the index directory is succesfully opened.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::close_index_dir)(fs_volume *volume,
			void *cookie)
	\brief Close a 'directory' of indices.

	Note that you should free the cookie in the free_index_dir_cookie() call.

	\param volume The volume object.
 	\param cookie The cookie associated with this 'directory'.
	\return B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::free_index_dir_cookie)(fs_volume *volume,
			void *cookie)
	\brief Free the \a cookie to the index 'directory'.

	\param volume The volume object.
	\param cookie The cookie that should be freed.
	\return B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::read_index_dir)(fs_volume *volume,
			void *cookie, struct dirent *buffer, size_t bufferSize,
			uint32 *_num)
	\brief Read the next one or more index entries.

	This method should perform the same task as fs_vnode_ops::read_dir(),
	except that the '.' and the '..' entries don't have to be present.
*/

/*!
	\fn status_t (*fs_volume_ops::rewind_index_dir)(fs_volume *volume,
			void *cookie)
	\brief Reset the index directory cookie to the first entry of the directory.

	\param volume The volume object.
	\param cookie The directory cookie as returned by open_index_dir().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::create_index)(fs_volume *volume,
			const char *name, uint32 type, uint32 flags)
	\brief Create a new index.

	\param volume The volume object.
	\param name The name of the new index.
	\param type The type of index. BFS implements the following types:
		- \c B_INT32_TYPE
		- \c B_UINT32_TYPE
		- \c B_INT64_TYPE
		- \c B_UINT64_TYPE
		- \c B_FLOAT_TYPE
		- \c B_DOUBLE_TYPE
		- \c B_STRING_TYPE
		- \c B_MIME_STRING_TYPE
	\param flags There are currently no extra flags specified. This parameter
		can be ignored.
	\return You should return \c B_OK if the creation succeeded, or return an
		error otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::remove_index)(fs_volume *volume,
			const char *name)
	\brief Remove the index with \a name.

	\param volume The volume object.
	\param name The name of the index to be removed.
	\return You should return \c B_OK if the creation succeeded, or return an
		error otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::read_index_stat)(fs_volume *volume,
			const char *name, struct stat *stat)
	\brief Read the \a stat of the index with a name.

	\param volume The volume object.
	\param name The name of the index to be queried.
	\param stat A pointer to a structure where you should store the values.
	\return You should return \c B_OK if the creation succeeded, or return an
		error otherwise.
*/

//! @}

/*!
	\name Query Operations
*/

//! @{

/*!
	\fn status_t (*fs_volume_ops::open_query)(fs_volume *volume,
			const char *query, uint32 flags, port_id port, uint32 token,
			void **_cookie)
	\brief Open a query as a 'directory'.

	TODO: query expressions should be documented and also the format for sending
	query updates over the port should be updated.

	See \ref concepts "Generic Concepts" on directories and iterators.
	Basically, the VFS uses the same way of traversing through indices as it
	traverses through a directory.

	\param volume The volume object.
	\param query The string that represents a query.
	\param flags Any combination of none or more of these flags:
		- \c B_LIVE_QUERY The query is live. When a query is live, it is
		  constantly updated using the \a port. The FS must invoke the functions
		  notify_query_entry_created() and notify_query_entry_removed() whenever
		  an entry starts respectively stops to match the query predicate.
		- \c B_QUERY_NON_INDEXED Normally at least one of the attributes used
		  in the query string should be indexed. If none is, this hook is
		  allowed to fail, unless this flag is specified. Usually an
		  implementation will simply add a wildcard match for any complete
		  index ("name", "last_modified", or "size") to the query expression.
	\param port The id of the port where updates need to be sent to in case the
		query is live.
	\param token A token that should be attached to the messages sent over the
		\a port.
	\param[out] _cookie The cookie that will be used as 'directory' to traverse
		through the results of the query.
	\return You should return \c B_OK if the creation succeeded, or return an
		error otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::close_query)(fs_volume *volume, void *cookie)
	\brief Close a 'directory' of a query.

	Note that you should free the cookie in the free_query_cookie() call.

	\param volume The volume object.
	\param cookie The cookie that refers to this query.
	\return You should return \c B_OK if the creation succeeded, or return an
		error otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::free_query_cookie)(fs_volume *volume,
			void *cookie)
	\brief Free a cookie of a query.

	\param volume The volume object.
	\param cookie The cookie that should be freed.
	\return You should return \c B_OK if the creation succeeded, or return an
		error otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::read_query)(fs_volume *volume, void *cookie,
			struct dirent *buffer, size_t bufferSize, uint32 *_num)
	\brief Read the next one or more entries matching the query.

	This hook function works pretty much the same way as
	fs_vnode_ops::read_dir(), with the difference that it doesn't read the
	entries of a directory, but the entries matching the given query. Unlike the
	fs_vnode_ops::read_dir() hook, this hook also has to fill in the
	dirent::d_pino field.

	\param volume The volume object.
	\param cookie The query cookie as returned by open_query().
	\param buffer Pointer to a pre-allocated buffer the directory entries shall
		be written to.
	\param bufferSize The size of \a buffer in bytes.
	\param _num Pointer to a pre-allocated variable, when invoked, containing
		the number of entries to be read, and into which the number of entries
		actually read shall be written.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_volume_ops::rewind_query)(fs_volume *volume, void *cookie)
	\brief Reset the query cookie to the first entry of the results.

	\param volume The volume object.
	\param cookie The query cookie as returned by open_query().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name FS Layer Operations
*/

//! @{

/*!
	\fn status_t (*fs_volume_ops::all_layers_mounted)(fs_volume *volume)
	\brief TODO: Document!
*/

/*!
	\fn status_t (*fs_volume_ops::create_sub_vnode)(fs_volume *volume, ino_t id,
			fs_vnode *vnode)
	\brief TODO: Document!
*/

/*!
	\fn status_t (*fs_volume_ops::delete_sub_vnode)(fs_volume *volume,
			fs_vnode *vnode)
	\brief TODO: Document!
*/

//! @}


///// fs_vnode_ops /////


/*!
	\struct fs_vnode_ops
	\brief Operations vector for a node.

	See the \ref fs_modules "introduction to file system modules" for an
	introduction to writing file systems.
*/

/*!
	\name VNode Operations
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::lookup)(fs_volume *volume, fs_vnode *dir,
			const char *name, ino_t *_id)
	\brief Looks up the node a directory entry refers to.

	The VFS uses this hook to resolve path names to vnodes. It is used quite
	often and should be implemented efficiently.

	If the parameter \a dir does not specify a directory, the function shall
	fail. It shall also fail, if it is a directory, but does not contain an
	entry with the given name \a name. Otherwise the function shall invoke
	get_vnode() for the node the entry refers to and pass back the ID of the
	node in \a _id.

	Note that a directory must contain the special entries \c "." and \c "..",
	referring to the same directory and the parent directory respectively.
	lookup() must resolve the nodes accordingly. \c ".." for the root directory
	of the volume shall be resolved to the root directory itself.

	\param volume The volume object.
	\param dir The node object for the directory.
	\param name The name of the directory entry.
	\param _id Pointer to a pre-allocated variable the ID of the found node
		shall be written to.
	\retval B_OK Everything went fine.
	\retval B_NOT_A_DIRECTORY The given node is not a directory.
	\retval B_ENTRY_NOT_FOUND The given directory does not contain an entry with
		the given name.
*/

/*!
	\fn status_t (*fs_vnode_ops::get_vnode_name)(fs_volume *volume,
			fs_vnode *vnode, char *buffer, size_t bufferSize)
	\brief Return the file name of a directory vnode.

	Normally file systems don't support hard links for directories, which means
	that a directory can be addressed by a unique path. This hook returns the
	name of the directory's entry in its parent directory.

	Note that you don't have to implement this call if it can't be easily done;
	it's completely optional.
	If you don't implement it, you'll have to export a NULL pointer for this
	function in the module definition. In this case, the VFS will find the name
	by iterating over its parent directory.

	If invoked for a non-directory node the hook is allowed to fail.

	\param volume The volume object.
	\param vnode The node object.
	\param buffer The buffer that the name can be copied into.
	\param bufferSize The size of the buffer.
	\retval B_OK You successfully copied the file name into the \a buffer.
	\retval "other errors" There was some error looking up or copying the name.
*/

/*!
	\fn \fn status_t (*fs_vnode_ops::put_vnode)(fs_volume *volume,
			fs_vnode *vnode, bool reenter)
	\brief Deletes the private data handle associated with the specified node.

	Invoked by the VFS when it deletes the vnode for the respective node and the
	node is not marked removed.

	\param volume The volume object.
	\param vnode The node object.
	\param reenter \c true if the hook invocation has been caused by the FS
		itself, e.g. by invoking ::put_vnode().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::remove_vnode)(fs_volume *volume,
			fs_vnode *vnode, bool reenter)
	\brief Deletes the private data handle associated with the specified node.

	Invoked by the VFS when it deletes the vnode for the respective node and the
	node has been marked removed by a call to remove_vnode().

	\param volume The volume object.
	\param vnode The node object.
	\param reenter \c true if the hook invocation has been caused by the FS
		itself, e.g. by invoking ::put_vnode().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name VM file access
*/

//! @{

/*!
	\fn bool (*fs_vnode_ops::can_page)(fs_volume *volume, fs_vnode *vnode,
		void *cookie)
	\brief Deprecated.
	\deprecated This is an obsolete hook that is never invoked.
*/

/*!
	\fn status_t (*fs_vnode_ops::read_pages)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, off_t pos, const iovec *vecs, size_t count,
			size_t *_numBytes)
	\brief Deprecated.
	\deprecated This is an obsolete hook that is never invoked.
*/

/*!
	\fn status_t (*fs_vnode_ops::write_pages)(fs_volume *volume,
			fs_vnode *vnode, void *cookie, off_t pos, const iovec *vecs,
			size_t count, size_t *_numBytes)
	\brief Deprecated.
	\deprecated This is an obsolete hook that is never invoked.
*/

//! @}

/*!
	\name Asynchronous I/O
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::io)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, io_request *request)
	\brief TODO: Document!
*/

/*!
	\fn status_t (*fs_vnode_ops::cancel_io)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, io_request *request)
	\brief TODO: Document!
*/

//! @}

/*!
	\name Cache File Access
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::get_file_map)(fs_volume *volume,
			fs_vnode *vnode, off_t offset, size_t size,
			struct file_io_vec *vecs, size_t *_count)
	\brief Fills the \a vecs with the extents of the file data stream.

	This function is called only when you are using the file cache, but if you
	use it, its implementation is mandatory.

	TODO: complete me
*/

//! @}

/*!
	\name Standard Operations
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::ioctl)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, ulong op, void *buffer, size_t length)
	\brief Perform file system specific operations.

	You can implement a customized API using this call. This can be extremely
	handy for debugging purposes. There are no obligatory operations for you to
	implement.

	If you don't want to use this feature, you don't have to implement it.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The file system provided cookie associated with, for example,
		an open file (if applicable).
	\param op The operation code. You will have to define them yourself.
	\param buffer A buffer (if applicable).
	\param length The size of the buffer.
	\return You should return any of your status codes.
*/

/*!
	\fn status_t (*fs_vnode_ops::set_flags)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, int flags)
	\brief Set the open mode flags for an opened file.

	This function should change the open flags for an opened file.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The file system provided cookie associated with the opened
		file.
	\param flags The new flags.
	\return \c B_OK if the operation succeeded, or else an error code.
*/

/*!
	\fn status_t (*fs_vnode_ops::select)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, uint8 event, selectsync *sync)
	\brief Selects the specified \a vnode with the specified \a events.

	This function is called by the VFS whenever select() or poll() is called on
	a file descriptor that points to your file system.

	You have to check if the condition of the select() (ie. if there is data
	available if event is B_SELECT_READ) is already satisfied, and call
	notify_select_event() with the \a sync and \a ref arguments you retrieve
	here.

	Additionally, when a vnode is selected this way, you have to call
	notify_select_event() whenever the condition becomes true until the
	vnode is deselected again via file_system_module_info::deselect().

	This function is optional. If you don't export it, the default
	implementation in the VFS will call notify_select_event() directly which
	will be sufficient for most file systems.

	Note that while select() and the corresponding deselect() are invoked by the
	same thread, notifications are usually generated by other threads. It is
	your responsibility to make sure that notify_select_event() is never called
	for a selectsync object for which deselect() has already returned. This is
	commonly done by holding the same lock when invoking notify_select_event()
	and when removing the selectsync object from the cookie in deselect().
	Such a lock can be any lock, usually one that is associated with the node or
	the volume.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The file system provided cookie associated with the opened
		file.
	\param event The event to be selected. One of:
		- \c B_SELECT_READ: File ready for reading.
    	- \c B_SELECT_WRITE: File ready for writing.
    	- \c B_SELECT_ERROR: I/O error condition.
    	- \c B_SELECT_PRI_READ: File ready for priority read.
    	- \c B_SELECT_PRI_WRITE: File ready for priority write.
    	- \c B_SELECT_HIGH_PRI_READ: File ready for high priority read.
    	- \c B_SELECT_HIGH_PRI_WRITE: File ready for high priority write.
    	- \c B_SELECT_DISCONNECTED: Socket/FIFO/... has been disconnected.
	\param sync Opaque pointer to be passed to notify_select_event().
	\return \c B_OK if the operation succeeded, or else an error code.
*/

/*!
	\fn status_t (*fs_vnode_ops::deselect)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, uint8 event, selectsync *sync)
	\brief Deselects the specified \a vnode from a previous select() call.

	This function is called by the VFS whenever a select() or poll() function
	exits that previously called file_system_module_info::select() on that
	\a vnode.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The file system provided cookie associated with the opened
		file.
	\param event The event to be deselected.
	\param sync Opaque pointer to be passed to notify_select_event().
	\return \c B_OK if the operation succeeded, or else an error code.
*/

/*!
	\fn status_t (*fs_vnode_ops::fsync)(fs_volume *volume, fs_vnode *vnode)
	\brief Synchronize the buffers with the on disk data.

	\param volume The volume object.
	\param vnode The node object.
	\return \c B_OK if the operation succeeded, or else an error code.
*/

/*!
	\fn status_t (*fs_vnode_ops::read_symlink)(fs_volume *volume,
			fs_vnode *link, char *buffer, size_t *_bufferSize)
	\brief Read the value of a symbolic link.

	If the function is successful, the symlink string shall be written to the
	buffer. It does not need to be null-terminated. If the buffer is too small
	to hold the complete string, only the first \c *_bufferSize bytes of the
	string shall be written to the buffer; the buffer shall not be
	null-terminated in this case. Furthermore the variable \a _bufferSize
	shall be set to the length of the symlink contents, even if the entire
	contents did not fit in the provided \a buffer.

	\param volume The volume object.
	\param link The node object.
	\param buffer Pointer to a pre-allocated buffer the link value shall be
		written to.
	\param _bufferSize Pointer to a pre-allocated variable containing the size
		of the buffer supplied to the function. Upon successful completion the
		hook shall store the length of the symlink contents.
	\retval B_OK Everything went fine.
	\retval B_BAD_VALUE \a link does not identify a symbolic link.
*/

/*!
	\fn status_t (*fs_vnode_ops::create_symlink)(fs_volume *volume,
			fs_vnode *dir, const char *name, const char *path, int mode)
	\brief Create a new symbolic link.

	\param volume The volume object.
	\param dir The node object for the directory the symbolic link should be
		created in.
	\param name The name of the new symbolic link.
	\param path The path the symbolic link should refer to.
	\param mode The permissions for the newly created symbolic link.
	\return \c B_OK if you succeeded, or an error code if you failed.
*/

/*!
	\fn status_t (*fs_vnode_ops::link)(fs_volume *volume, fs_vnode *dir,
			const char *name, fs_vnode *vnode)
	\brief Create a new hard link.

	The virtual file system will request the creation of symbolic links with
	create_symlink().

	If you don't implement this function, the VFS will return \c EROFS
	when a hard link is requested. So, if you don't support hard links implement
	this hook and return an appropriate error code.

	\param volume The volume object.
	\param dir The node object for the directory where the link should be
		created.
	\param name The name the link should have.
	\param vnode The vnode the new link should resolve to.
	\retval B_OK The hard link is properly created.
	\retval B_NOT_ALLOWED The user does not have the proper permissions.
	\retval "other errors" Another error occured.
*/

/*!
	\fn status_t (*fs_vnode_ops::unlink)(fs_volume *volume, fs_vnode *dir,
			const char *name)
	\brief Remove a non-directory entry.

	Remove an entry that does refer to a non-directory node. For removing
	directories the remove_dir() hook is used. If invoked on a directory, this
	hook shall fail.

	\param volume The volume object.
	\param dir The node object for the directory containing the entry to be
		removed.
	\param name The name of the entry that should be removed.
	\retval B_OK Removal succeeded.
	\retval B_ENTRY_NOT_FOUND The entry does not exist.
	\retval B_NOT_ALLOWED The user does not have the proper permissions.
	\retval B_IS_A_DIRECTORY The entry refers to a directory.
	\retval "other errors" Another error occured.
*/

/*!
	\fn status_t (*fs_vnode_ops::rename)(fs_volume *volume, fs_vnode *fromDir,
			const char *fromName, fs_vnode *toDir, const char *toName)
	\brief Rename and/or relocate an entry.

	The virtual file system merely relays the request, so make sure the user is
	not changing the file name to something like '.', '..' or anything starting
	with '/'.

	This also means that it if the entry refers to a directory, that it should
	not be moved into one of its own children.

	\param volume The volume object.
	\param fromDir The node object for the parent directory the entry should be
		moved from.
	\param fromName The old entry name.
	\param toDir The node object for the parent directory the entry should be
		moved to.
	\param toName The new entry name.
	\retval B_OK The renaming and relocating succeeded.
	\retval B_BAD_VALUE One of the supplied parameters were invalid.
	\retval B_NOT_ALLOWED The user does not have the proper permissions.
	\retval "other errors" Another error condition was encountered.
*/

/*!
	\fn status_t (*fs_vnode_ops::access)(fs_volume *volume, fs_vnode *vnode,
			int mode)
	\brief Checks whether the current user is allowed to access the node in the
		specified way.

	\a mode is a bitwise combination of:
	- \c R_OK: Read access.
	- \c W_OK: Write access.
	- \c X_OK: Execution.

	If the current user does not have any of the access permissions represented
	by the set bits, the function shall return \c B_NOT_ALLOWED. As a special
	case, if the volume is read-only and write access is requested,
	\c B_READ_ONLY_DEVICE shall be returned. If the requested access mode
	complies with the user's access permissions, the function shall return
	\c B_OK.

	For most FSs the permissions a user has are defined by the \c st_mode,
	\c st_uid, and \c st_gid fields of the node's stat data. As a special
	exception, the root user (<tt>geteuid() == 0</tt>) does always have
	read and write permissions, execution permission only when at least one of
	the execution permission bits are set.

	\param volume The volume object.
	\param vnode The node object.
	\param mode The access mode mask.
	\retval B_OK The user has the permissions to access the node in the
		requested way.
	\retval B_READ_ONLY_DEVICE The volume is read-only, but the write access has
		been requested.
	\retval B_NOT_ALLOWED The user does not have all permissions to access the
		node in the requested way.
*/

/*!
	\fn status_t (*fs_vnode_ops::read_stat)(fs_volume *volume, fs_vnode *vnode,
			struct stat *stat)
	\brief Retrieves the stat data for a given node.

	All values of the <tt>struct stat</tt> save \c st_dev, \c st_ino,
	\c st_rdev, and \c st_type need to be filled in.

	\param volume The volume object.
	\param vnode The node object.
	\param stat Pointer to a pre-allocated variable the stat data shall be
		written to.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::write_stat)(fs_volume *volume, fs_vnode *vnode,
			const struct stat *stat, uint32 statMask)
	\brief Update the stats for a vnode.

	You should make sure that the new values are valid.

	\param volume The volume object.
	\param vnode The node object.
	\param stat The structure with the updated values.
	\param statMask A bitwise combination of one or more of the following,
		specifying which stat field shall be set:
		- B_STAT_MODE: Set the node permissions.
		- B_STAT_UID: Set the owning user.
		- B_STAT_GID: Set the owner group.
		- B_STAT_SIZE: Set the size of the file. If enlarged, the file is
			padded. Normally with zero bytes, but with unspecified data, if
			B_STAT_SIZE_INSECURE is specified, too.
		- B_STAT_SIZE_INSECURE: Modifier for B_STAT_SIZE: When enlarging the
			file padding can be done with arbitrary data.
		- B_STAT_ACCESS_TIME: Set the access time.
		- B_STAT_MODIFICATION_TIME: Set the modification time.
		- B_STAT_CREATION_TIME: Set the creation time.
		- B_STAT_CHANGE_TIME: Set the change time.
	\retval B_OK The update succeeded.
	\retval B_NOT_ALLOWED The user does not have the proper permissions.
	\retval "other errors" Another error condition occured.
*/

//! @}

/*!
 \name File Operations
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::create)(fs_volume *volume, fs_vnode *dir,
			const char *name, int openMode, int perms, void **_cookie,
			ino_t *_newVnodeID)
	\brief Creates and opens a new file.

	The hook is similar to \link fs_vnode_ops::open() open() \endlink, with the
	difference that, if an entry with the name \a name does not already exist
	in the given directory, a new file with that name is created first.
	If the entry does already exist and \a openMode specifies the \c O_EXCL
	flag, the function shall fail with \c B_FILE_EXISTS (aka \c EEXIST).

	\param volume The volume object.
	\param dir The node object for the directory where the file should appear.
	\param name The name of the new file.
	\param openMode The mode associated to the file.
	\param perms The permissions the new file should have.
	\param[out] _cookie In case of success, the storage where you can put your
		FS specific cookie for the open node.
	\param[out] _newVnodeID In case of success, you can store the new vnode id
		in this variable.
	\return If opening the node succeeded (after creating it first, if
		necessary), \c B_OK shall be returned and \a _cookie and \a _newVnodeID
		shall be set. Otherwise an error code shall be returned.
*/

/*!
	\fn status_t (*fs_vnode_ops::open)(fs_volume *volume, fs_vnode *vnode,
			int openMode, void **_cookie)
	\brief Opens the given node.

	The hook is invoked whenever a file is opened (e.g. via the open() POSIX
	function).

	The hook can create a node cookie, and store it in the variable
	\a _cookie points to. The cookie will be passed to all hooks that operate
	on open files.

	The open mode \a openMode is encoded in the same way as the parameter of the
	POSIX function \c open(), i.e. it is either \c O_RDONLY, \c O_WRONLY, or
	\c O_RDWR, bitwise or'ed with flags. The only relevant flags for this hook
	are \c O_TRUNC and \c O_NONBLOCK. You will normally want to store the open
	mode in the file cookie, since you'll have to check in read() and write()
	whether the the respective operation is allowed by the open mode.

	\param volume The volume object.
	\param vnode The node object.
	\param openMode The open mode.
	\param _cookie Pointer to a pre-allocated variable the node cookie shall be
		written to.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::close)(fs_volume *volume, fs_vnode *vnode,
		void *cookie)
	\brief Closes the given node cookie.

	The hook is invoked, when closing the node has been requested. At this point
	other threads might still use the cookie, i.e. still execute hooks to which
	the cookie has been passed. If the FS supports blocking I/O operations, this
	hook should make sure to unblock all currently blocking threads performing
	an operation using the cookie, and mark the cookie such that no further
	threads will block using it.

	For many FSs this hook is a no-op -- it's mandatory to be exported, though.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The node cookie as returned by open().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::free_cookie)(fs_volume *volume,
		fs_vnode *vnode, void *cookie)
	\brief Frees the given node cookie.

	The hook is invoked after close(), when no other thread uses or is going to
	use the cookie. All resources associated with the cookie must be freed.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The node cookie as returned by open().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::read)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, off_t pos, void *buffer, size_t *length)
	\brief Reads data from a file.

	This function should fail if
	- the node is not a file,
	- the cookie has not been opened for reading,
	- \a pos is negative, or
	- some other error occurs while trying to read the data, and no data have
		been read at all.

	The number of bytes to be read is stored in the variable pointed to by
	\a length. If less data is available at file position \a pos, or if \a pos
	if greater than the size of the file, only as many data as available shall
	be read, the function shall store the number of bytes actually read into the
	variable pointed to by \a length, and return \c B_OK.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The node cookie as returned by open().
	\param pos The file position where to start reading data.
	\param buffer Pointer to a pre-allocated buffer the read data shall be
		written to.
	\param length Pointer to a pre-allocated variable containing the size of the
		buffer when invoked, and into which the size of the data actually read
		shall be written.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::write)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, off_t pos, const void *buffer, size_t *length)
	\brief Write data to a file.

	This function should fail if
	- the node is not a file,
	- the cookie has not been opened for writing,
	- \a pos is negative, or
	- some other error occurs while trying to write the data, and no data have
		been written at all.

	The number of bytes to be written is stored in the variable pointed to by
	\a length. If not all bytes could be written, that variable must be updated
	to reflect the amount of actually written bytes. If any bytes have been
	written, the function shall not fail, if an error prevents you from
	writing the full amount. Only when the error prevented you from writing
	any data at all an error shall be returned.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The file system provided cookie associated with the file.
	\param pos The position to start writing.
	\param buffer The buffer that contains the data that will need to be
		written.
	\param length The length of the data that needs to be written.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name Directory Operations
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::create_dir)(fs_volume *volume,
			fs_vnode *parent, const char *name, int perms)
	\brief Create a new directory.

	\param volume The volume object.
	\param parent The node object for the directory in which to create the new
		directory.
	\param name The name the new directory should have.
	\param perms The permissions the new directory should have.
	\return \c B_OK if the directory was created successfully, an error code
		otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::remove_dir)(fs_volume *volume,
			fs_vnode *parent, const char *name)
	\brief Remove a directory.

	The function shall fail, if the entry does not refer to a directory, or if
	it refers to a directory that is not empty.

	\param volume The volume object.
	\param parent The node object for the parent directory containing the
		directory to be removed.
	\param name The \a name of the directory that needs to be removed.
	\retval B_OK Operation succeeded.
	\retval B_ENTRY_NOT_FOUND There is no entry with this \a name.
	\retval B_NOT_A_DIRECTORY The entry is not a directory.
	\retval B_DIRECTORY_NOT_EMPTY The directory is not empty. The virtual
		file system expects directories to be emptied before they can be
		removed.
	\retval "other errors" Other errors occured.
*/

/*!
	\fn status_t (*fs_vnode_ops::open_dir)(fs_volume *volume, fs_vnode *vnode,
				void **_cookie)
	\brief Opens the given directory node.

	If the specified node is not a directory, the function shall fail.
	Otherwise it shall allocate a directory cookie and store it in the variable
	\a _cookie points to. A subsequent read_dir() using the cookie shall start
	reading the first entry of the directory.

	\param volume The volume object.
	\param vnode The node object.
	\param _cookie Pointer to a pre-allocated variable the directory cookie
		shall be written to.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::close_dir)(fs_volume *volume, fs_vnode *vnode,
			void *cookie)
	\brief Closes the given directory cookie.

	Generally the situation is similar to the one described for close(). In
	practice it is a bit different, though, since directory cookies are
	exclusively used for directory iteration, and it normally doesn't make sense
	to have multiple threads read the same directory concurrently. Furthermore
	usually reading a directory will not block. Therefore for most FSs this hook
	is a no-op.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The directory cookie as returned by open_dir().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::free_dir_cookie)(fs_volume *volume,
			fs_vnode *vnode, void *cookie)
	\brief Frees the given directory cookie.

	The hook is invoked after close_dir(), when no other thread uses or is going
	to use the cookie. All resources associated with the cookie must be freed.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The directory cookie as returned by open_dir().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::read_dir)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, struct dirent *buffer, size_t bufferSize,
			uint32 *_num)
	\brief Reads the next one or more directory entries.

	The number of entries to be read at maximum is stored in the variable
	\a _num points to.

	Per read \c dirent the following fields have to be filled in:
	- \c d_dev: The volume ID.
	- \c d_ino: The ID of the node the entry refers to.
	- \c d_name: The null-terminated name of the entry.
	- \c d_reclen: The size of the \c dirent structure in bytes, starting from
	  the beginning of the structure, counting all bytes up to and including
	  the null-termination char of the name stored in \c d_name.

	If more than one entry is read, the corresponding \c dirent structures are
	tightly packed, i.e. the second entry can begin directly after the end of
	the first one (i.e. \c d_reclen bytes after the beginning of the first one).
	The file system should make sure that the dirents are 8-byte aligned, i.e.
	when another entry follows, \c d_reclen of the previous one should be
	aligned. A FS doesn't have to read more than one entry at a time, but it is
	recommended to support that for performance reasons.

	If the provided buffer is too small to contain even the single next
	entry, \c B_BUFFER_OVERFLOW shall be returned. It shall not fail, if at
	least one entry has been read, and the buffer is just too small to hold as
	many entries as requested. When the function is invoked after the end of
	the directory has been reached, it shall set the variable \a _num points to
	\c 0 and return \c B_OK. Usually the function is invoked repeatedly until
	then to get more entries. The \c cookie parameter must be used to track the
	position in the directory.

	Note that a directory is expected to contain the special entries \c "." and
	\c "..", referring to the same directory and the parent directory
	respectively. The \c dirent structure returned for the \c ".." entry of the
	volume's root directory shall refer to the root node itself.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The directory cookie as returned by open_dir().
	\param buffer Pointer to a pre-allocated buffer the directory entries shall
		be written to.
	\param bufferSize The size of \a buffer in bytes.
	\param _num Pointer to a pre-allocated variable, when invoked, containing
		the number of directory entries to be read, and into which the number of
		entries actually read shall be written.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::rewind_dir)(fs_volume *volume, fs_vnode *vnode,
			void *cookie)
	\brief Resets the directory cookie to the first entry of the directory.
	\param volume The volume object.
	\param vnode The node object.
	\param cookie The directory cookie as returned by open_dir().
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name Attribute Directory Operations
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::open_attr_dir)(fs_volume *volume,
			fs_vnode *vnode, void **_cookie)
	\brief Open a 'directory' of attributes for a \a vnode.

	See \ref concepts "Generic Concepts" on directories and iterators.
	Basically, the VFS uses the same way of traversing through attributes as it
	traverses through a directory.

	\param volume The volume object.
	\param vnode The node object.
	\param[out] _cookie Pointer where the file system can store a directory
		cookie if the attribute directory is succesfully opened.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::close_attr_dir)(fs_volume *volume,
			fs_vnode *vnode, void *cookie)
	\brief Close a 'directory' of attributes for a \a vnode.

	Note that you should free the cookie in the free_attr_dir_cookie() call.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie associated with this 'directory'.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::free_attr_dir_cookie)(fs_volume *volume,
			fs_vnode *vnode, void *cookie)
	\brief Free the \a cookie to an attribute 'directory'.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie associated that should be freed.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::read_attr_dir)(fs_volume *volume,
			fs_vnode *vnode, void *cookie, struct dirent *buffer,
			size_t bufferSize, uint32 *_num)
	\brief Read the next one or more attribute directory entries.

	This method should perform the same tasks as read_dir(), except that the '.'
	and '..' entries do not have to be present. Also, only the \c d_name and
	\c d_reclen fields have to be filled in.
*/

/*!
	\fn status_t (*fs_vnode_ops::rewind_attr_dir)(fs_volume *volume,
			fs_vnode *vnode, void *cookie)
	\brief Rewind the attribute directory iterator to the first entry.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie associated with this 'directory'.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name Attribute Operations
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::create_attr)(fs_volume *volume,
			fs_vnode *vnode, const char *name, uint32 type, int openMode,
			void **_cookie)
	\brief Create a new attribute.

	If the attribute already exists, you should open it in truncated mode.

	\param volume The volume object.
	\param vnode The node object.
	\param name The name of the attribute.
	\param type The \c type_code of the attribute.
	\param openMode The openMode of the associated attribute.
	\param[out] _cookie A pointer where you can store an associated file system
		cookie.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::open_attr)(fs_volume *volume, fs_vnode *vnode,
			const char *name, int openMode, void **_cookie)
	\brief Open an existing attribute.

	\param volume The volume object.
	\param vnode The node object.
	\param name The name of the attribute.
	\param openMode The mode in which you want to open the attribute data.
	\param[out] _cookie A pointer where you can store an associated file system
		cookie.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::close_attr)(fs_volume *volume, fs_vnode *vnode,
				void *cookie)
	\brief Close access to an attribute.

	Note that you should not delete the cookie yet, you should do that when the
	VFS calls free_attr_cookie().

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie you associated with this attribute.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::free_attr_cookie)(fs_volume *volume,
			fs_vnode *vnode, void *cookie)
	\brief Free the cookie of an attribute.

	The VFS calls this hook when all operations on the attribute have ceased.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie to the attribute that should be freed.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::read_attr)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, off_t pos, void *buffer, size_t *length)
	\brief Read attribute data.

	Read until the \a buffer with size \a length is full, or until you are out
	of data, in which case you should update \a length.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie you associated with this attribute.
	\param pos The position to start reading from.
	\param buffer The buffer the data should be copied in.
	\param length The length of the buffer. Update this variable to the actual
		amount of bytes read.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::write_attr)(fs_volume *volume, fs_vnode *vnode,
			void *cookie, off_t pos, const void *buffer, size_t *length)
	\brief Write attribute data.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie you associated with this attribute.
	\param pos The position to start writing to.
	\param buffer The buffer the data should be copied from.
	\param length The size of the buffer. Update this variable to the actual
		amount of bytes written.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::read_attr_stat)(fs_volume *volume,
			fs_vnode *vnode, void *cookie, struct stat *stat)
	\brief Get the stats for an attribute.

	Only the \c st_size and \c st_type fields need to be filled in.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie you associated with this attribute.
	\param stat A pointer to a stat structure you should fill.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::write_attr_stat)(fs_volume *volume,
			fs_vnode *vnode, void *cookie, const struct stat *stat,
			int statMask)
	\brief Update the stats of an attribute.

	Currently on the attribute size (B_STAT_SIZE) can be set.

	\param volume The volume object.
	\param vnode The node object.
	\param cookie The cookie you associated with this attribute.
	\param stat A pointer to the new stats you should write.
	\param statMask One or more of the values of write_stat_mask that tell you
		which fields of \a stat are to be updated.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t (*fs_vnode_ops::rename_attr)(fs_volume *volume,
			fs_vnode *fromVnode, const char *fromName, fs_vnode *toVnode,
			const char *toName)
	\brief Rename and/or relocate an attribute.

	Currently there's no userland or kernel API moving an attribute from one
	node to another. So this hook is to allowed to only support the case where
	\a fromVnode and \a toVnode are equal and fail otherwise.

	\param volume The volume object.
	\param fromVnode The node object for the vnode the attribute currently
		belongs to.
	\param fromName The old name of the attribute.
	\param toVnode The node object for the vnode the attribute should be
		moved to. This can be the same as \a fromVnode, in which case it only
		means the attribute should be renamed.
	\param toName The new name of the attribute. This can be the same as
		\a fromName, in which case it only means the attribute should be
		relocated.
	\retval B_OK The renaming and/or relocating succeeded.
	\retval B_BAD_VALUE One of the supplied parameters were invalid.
	\retval B_NOT_ALLOWED The user does not have the proper permissions.
	\retval "other errors" Another error condition was encountered.
*/

/*!
	\fn status_t (*fs_vnode_ops::remove_attr)(fs_volume *volume,
			fs_vnode *vnode, const char *name)
	\brief Remove an attribute.

	\param volume The volume object.
	\param vnode The node object.
	\param name The name of the attribute.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

//! @}

/*!
	\name Node and FS Layers
*/

//! @{

/*!
	\fn status_t (*fs_vnode_ops::create_special_node)(fs_volume *volume,
			fs_vnode *dir, const char *name, fs_vnode *subVnode, mode_t mode,
			uint32 flags, fs_vnode *_superVnode, ino_t *_nodeID)
	\brief TODO: Document!
*/

/*!
	\fn status_t (*fs_vnode_ops::get_super_vnode)(fs_volume *volume,
			fs_vnode *vnode, fs_volume *superVolume, fs_vnode *superVnode)
	\brief TODO: Document!
*/


//! @}


///// Vnode functions /////

/*!
	\name Vnode functions
*/

//! @{

/*!
	\fn status_t new_vnode(fs_volume *volume, ino_t vnodeID, void *privateNode,
			fs_vnode_ops *ops)
	\brief Create the vnode with ID \a vnodeID and associates it with the
		private data handle \a privateNode, but leaves is in an unpublished
		state.

	The effect of the function is similar to publish_vnode(), but the vnode
	remains in an unpublished state, with the effect that a subsequent
	remove_vnode() will just delete the vnode and not invoke the file system's
	\link fs_vnode_ops::remove_vnode remove_vnode() \endlink when
	the final reference is put down.

	If the vnode shall be kept, publish_vnode() has to be invoked afterwards to
	mark the vnode published. The combined effect is the same as only invoking
	publish_vnode().

	You'll usually use this function to secure a vnode ID from being reused
	while you are in the process of creating the entry. Note that this function
	will panic in case you call it for an existing vnode ID.

	The function fails, if the vnode does already exist.

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\param privateNode The private data handle to be associated with the node.
	\param ops The operation vector for this vnode. Is not copied and must be
		valid through the whole life time of the vnode.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t publish_vnode(fs_volume *volume, ino_t vnodeID,
			void *privateNode, fs_vnode_ops *ops, int type, uint32 flags)
	\brief Creates the vnode with ID \a vnodeID and associates it with the
		private data handle \a privateNode or just marks it published.

	If the vnode does already exist and has been published, the function fails.
	If it has not been published yet (i.e. after a successful new_vnode()), the
	function just marks the vnode published. If the vnode did not exist at all
	before, it is created and published.

	If the function is successful, the caller owns a reference to the vnode. A
	sequence of new_vnode() and publish_vnode() results in just one reference as
	well. The reference can be surrendered by calling put_vnode().

	If called after a new_vnode() the \a privateNode and \a ops parameters must
	be the same as previously passed to new_vnode().

	This call is equivalent to the former BeOS R5 new_vnode() function.

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\param privateNode The private data handle to be associated with the node.
	\param ops The operation vector for this vnode. Is not copied and must be
		valid through the whole life time of the vnode.
	\param type The type of the node as it would appear in a stat::st_mode (with
		all non type-related bits set to 0).
	\param flags A bitwise combination of none or more of the following:
		- B_VNODE_PUBLISH_REMOVED: The node is published in "removed" state,
			i.e. it has no entry referring to it and releasing the last
			reference to the vnode will remove it.
		- B_VNODE_DONT_CREATE_SPECIAL_SUB_NODE: Normally for FIFO or socket type
			nodes the VFS creates sub node providing the associated
			functionality. This flag prevents that from happing.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t get_vnode(fs_volume *volume, ino_t vnodeID,
			void **_privateNode)
	\brief Retrieves the private data handle for the node with the given ID.

	If the function is successful, the caller owns a reference to the vnode. The
	reference can be surrendered by calling put_vnode().

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\param _privateNode Pointer to a pre-allocated variable the private data
		handle shall be written to.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t put_vnode(fs_volume *volume, ino_t vnodeID)
	\brief Surrenders a reference to the specified vnode.

	When the last reference to the vnode has been put the VFS will call
	fs_vnode_ops::put_vnode() (eventually), respectively, if the node has been
	marked removed fs_vnode_ops::remove_vnode() (immediately).

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t acquire_vnode(fs_volume *volume, ino_t vnodeID)
	\brief Acquires another reference to a vnode.

	Similar to get_vnode() in that the function acquires a vnode reference.
	Unlike get_vnode() this function can also be invoked between new_vnode()
	and publish_vnode().

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t remove_vnode(fs_volume *volume, ino_t vnodeID)
	\brief Marks the specified vnode removed.

	The caller must own a reference to the vnode or at least ensure that a
	reference to the vnode exists. The function does not surrender a reference,
	though.

	As soon as the last reference to the vnode has been surrendered, the VFS
	invokes the node's \link fs_vnode_ops::remove_vnode remove_vnode() \endlink
	hook.

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t unremove_vnode(fs_volume *volume, ino_t vnodeID)
	\brief Clears the "removed" mark of the specified vnode.

	The caller must own a reference to the vnode or at least ensure that a
	reference to the vnode exists.

	The function is usually called when the caller, who has invoked
	remove_vnode() before realizes that it is not possible to remove the node
	(e.g. due to an error). Afterwards the vnode will continue to exist as if
	remove_vnode() had never been invoked.

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn status_t get_vnode_removed(fs_volume *volume, ino_t vnodeID,
			bool *_removed)
	\brief Returns whether the specified vnode is marked removed.

	The caller must own a reference to the vnode or at least ensure that a
	reference to the vnode exists.

	\param volume The volume object.
	\param vnodeID The ID of the node.
	\param _removed Pointer to a pre-allocated variable set to \c true, if the
		node is marked removed, to \c false otherwise.
	\return \c B_OK if everything went fine, another error code otherwise.
*/

/*!
	\fn fs_volume* volume_for_vnode(fs_vnode *vnode)
	\brief Returns the volume object for a given vnode.

	\param vnode The node object.
	\return The volume object for the given vnode.
*/

//! @}

///// Notification Functions

/*!
	\name Notification Functions

	The following functions are used to implement the node monitor functionality
	in your file system. Whenever one of the below mentioned events occur, you
	have to call them.

	The node monitor will then notify all registered listeners for the nodes
	that changed.
*/

//! @{

/*!
	\fn status_t notify_entry_created(dev_t device, ino_t directory,
			const char *name, ino_t node)
	\brief Notifies listeners that a file system entry has been created.
*/

/*!
	\fn status_t notify_entry_removed(dev_t device, ino_t directory,
			const char *name, ino_t node)
	\brief Notifies listeners that a file system entry has been removed.
*/

/*!
	\fn status_t notify_entry_moved(dev_t device, ino_t fromDirectory,
			const char *fromName, ino_t toDirectory,
			const char *toName, ino_t node)
	\brief Notifies listeners that a file system entry has been renamed and/or
		moved to another directory.
*/

/*!
	\fn status_t notify_stat_changed(dev_t device, ino_t directory, ino_t node,
			uint32 statFields)
	\brief Notifies listeners that certain \a statFields of a node were updated.
*/

/*!
	\fn status_t notify_attribute_changed(dev_t device, ino_t directory,
			ino_t node, const char *attribute, int32 cause)
	\brief Notifies listeners that an attribute of a node has been changed.
*/

/*!
	\fn status_t notify_query_entry_created(port_id port, int32 token,
			dev_t device, ino_t directory, const char *name, ino_t node)
	\brief Notifies listeners that an entry has entered the result set of a live
		query.
*/

/*!
	\fn status_t notify_query_entry_removed(port_id port, int32 token,
			dev_t device, ino_t directory, const char *name, ino_t node)
	\brief Notifies listeners that an entry has left the result set of a live
		query.
*/

//! @}
