diff --git a/docs/user/drivers/fs_interface.dox b/docs/user/drivers/fs_interface.dox index 62acc939df..116596b6d1 100644 --- a/docs/user/drivers/fs_interface.dox +++ b/docs/user/drivers/fs_interface.dox @@ -1,568 +1,1438 @@ +/* + * Copyright 2007 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + * Niels Sascha Reedijk + * Corresponds to: + * /trunk/headers/os/drivers/fs_interface.h rev 20724 + */ + /*! -\file fs_interface.h -\ingroup drivers + \file fs_interface.h + \ingroup drivers +*/ + +///// Typedefs ///// + +/*! + \typedef typedef dev_t mount_id + \brief A \c mount_id refers to a specific mounted (virtual) volume. +*/ + +/*! + \typedef typedef ino_t vnode_id + \brief A \c vnode_id refers to one of the available virtual nodes. +*/ + +/*! + \typedef typedef void *fs_volume + \brief Private data structure for the filesystem to store data associated + with volumes. +*/ + +/*! + \typedef typedef void *fs_cookie + \brief Private data structure that is passed to the filesystem when it is + called. +*/ + +/*! + \typedef typedef void *fs_vnode + \brief Private data structure that is passed to the filesystem when it is + operating on vnodes. +*/ + +///// write_stat_mask ////// + +/*! + \enum write_stat_mask + \brief This mask is used in file_system_module_info::write_stat() to + determine which values need to be written. +*/ + +/*! + \var write_stat_mask::FS_WRITE_STAT_MODE + \brief The mode parameter should be updated. +*/ + +/*! + \var write_stat_mask::FS_WRITE_STAT_UID + \brief The UID field should be updated. +*/ + +/*! + \var write_stat_mask::FS_WRITE_STAT_GID + \brief The GID field should be updated. +*/ + +/*! + \var write_stat_mask::FS_WRITE_STAT_SIZE + \brief The size field should be updated. +*/ + +/*! + \var write_stat_mask::FS_WRITE_STAT_ATIME + \brief The access time should be updated. +*/ + +/*! + \var write_stat_mask::FS_WRITE_STAT_MTIME + \brief The 'last modified' field should be updated. +*/ + +/*! + \var write_stat_mask::FS_WRITE_STAT_CRTIME + \brief The 'creation time' should be updated. +*/ + +///// FS_WRITE_FSINFO_NAME ///// + +/*! + \def FS_WRITE_FSINFO_NAME + \brief Passed to file_system_module_info::write_fs_info(). +*/ + +///// 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 filesystem API that your + filesystem conforms to. +*/ + +///// file_system_module_info ///// + + +/*! + \struct file_system_module_info + \brief Kernel module interface for 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. +*/ + +//! @} + +/*! + \name Scanning +*/ + +//! @{ + +/*! + \fn float (*file_system_module_info::identify_partition)(int fd, partition_data *partition, void **cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::scan_partition)(int fd, partition_data *partition, void *cookie) + \brief Undocumented. +*/ + +/*! + \fn void (*file_system_module_info::free_identify_partition_cookie)(partition_data *partition, void *cookie) + \brief Undocumented. +*/ + +/*! + \fn void (*file_system_module_info::free_partition_content_cookie)(partition_data *partition) + \brief Undocumented. +*/ + +//! @} + +/*! + \name General Operations +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::mount)(mount_id id, const char *device, + uint32 flags, const char *args, fs_volume *_fs, vnode_id *_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 _fs. 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 id The ID of the volume to be mounted. It should be saved in the FS's + volume private data (volume handle). + \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 _fs Pointer to a pre-allocated variable the volume handle shall be + written to. + \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. +*/ + +/*! + \fn status_t (*file_system_module_info::unmount)(fs_volume fs) + \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. Although the mount() hook called publish_vnode() for the root node + of the volume, unmount() must not invoke put_vnode(). + + \param fs The volume handle. + \return \c B_OK if everything went fine, another error code otherwise. The + error code will be ignored, though. +*/ + +/*! + \fn status_t (*file_system_module_info::read_fs_info)(fs_volume fs, + 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 device_name: The name of the device or image file containing the volume. + Non-disk-based FSs shall fill in an empty string. + - \c volume_name: The name of the volume. + + The other values are filled in by the VFS. + + \param fs The volume handle. + \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 (*file_system_module_info::write_fs_info)(fs_volume fs, const + struct fs_info *info, uint32 mask) + \brief Update filesystem information on the volume. + + You are requested to update certain information on the volume \a fs. 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. + + TODO: ANY OTHERS? + + \param fs The cookie your filesystem supplied to the volume that should be + updated. + \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 (*file_system_module_info::sync)(fs_volume fs) + \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. + + TODO: WHEN IS THIS CALLED AND FOR WHAT PURPOSE? + + \param fs The cookie your filesystem supplied to the volume that should be + updated. +*/ + +//! @} + +/*! + \name VNode Operations +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::lookup)(fs_volume fs, fs_vnode dir, + const char *name, vnode_id *_id, int *_type) + \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 and the type of the + node in \a _id and \a _type respectively. + + 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 fs The volume handle. + \param dir The node handle of 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. + \param _type Pointer to a pre-allocated variable the type of the found node + shall be written to. The type is encoded as in the \c st_mode field of a + struct stat (bitwise anded with \c S_IFMT). + \retval B_OK Everything went fine. + \retval B_ENTRY_NOT_FOUND The given directory does not contain an entry with + the given name. +*/ + +/*! + \fn status_t (*file_system_module_info::get_vnode_name)(fs_volume fs, fs_vnode vnode, char *buffer, + size_t bufferSize) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::get_vnode)(fs_volume fs, vnode_id id, + fs_vnode *_vnode, 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. + + \param fs The volume handle. + \param id The ID of the node. + \param _vnode Pointer to a pre-allocated variable the node handle shall be + written to. + \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. +*/ + +/*! + \fn \fn status_t (*file_system_module_info::put_vnode)(fs_volume fs, + 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 fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::remove_vnode)(fs_volume fs, + 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 marked removed. + + \param fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::can_page)(fs_volume fs, fs_vnode vnode, fs_cookie cookie) + \brief Undocumented. + + TODO: In both the dos and the bfs implementations this thing simply returns + false... Is there anything more to it? +*/ + +/*! + \fn status_t (*file_system_module_info::read_pages)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + off_t pos, const iovec *vecs, size_t count, size_t *_numBytes, + bool reenter) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::write_pages)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + off_t pos, const iovec *vecs, size_t count, size_t *_numBytes, + bool reenter) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Cache File Access +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::get_file_map)(fs_volume fs, fs_vnode vnode, off_t offset, + size_t size, struct file_io_vec *vecs, size_t *_count) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Standard Operations +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::ioctl)(fs_volume fs, fs_vnode vnode, + fs_cookie 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 fs The file system provided cookie associated with this volume. + \param vnode The file system provided cookie associated with the vnode (if + applicable). + \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 (*file_system_module_info::set_flags)(fs_volume fs, fs_vnode + vnode, fs_cookie 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 fs The file system provided cookie associated with this volume. + \param vnode The file system provided cookie associated with the vnode. + \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 (*file_system_module_info::select)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + uint8 event, uint32 ref, selectsync *sync) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::deselect)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + uint8 event, selectsync *sync) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::fsync)(fs_volume fs, fs_vnode vnode) + \brief Synchronize the buffers with the on disk data. + + \param fs The file system provided cookie associated with this volume. + \param vnode The file system provided cookie associated with the vnode. + \return \c B_OK if the operation succeeded, or else an error code. +*/ + +/*! + \fn status_t (*file_system_module_info::read_symlink)(fs_volume fs, + fs_vnode link, char *buffer, size_t *_bufferSize) + \brief Read the value of a symbolic link. + + If the function is successful, the string written to the buffer shall be + null-terminated and the variable \a _bufferSize points to shall be set to + the length of that string, including the terminating null character. + + \param fs The volume handle. + \param link The node handle. + \param buffer Pointer to a pre-allocated buffer the link value shall be + written to. + \param buffer Pointer to a pre-allocated variable containing the size of the + buffer supplied to the function. Upon successful completion the hook shall + store the number of bytes actually written into the buffer in the variable. + \retval B_OK Everything went fine. + \retval B_BAD_VALUE \a link does not identify a symbolic link. + \retval B_BUFFER_OVERFLOW The supplied buffer is not big enough to contain + the complete link value. +*/ + +/*! + \fn status_t (*file_system_module_info::create_symlink)(fs_volume fs, + fs_vnode dir, const char *name, const char *path, int mode) + \brief Create a new symbolic link. + + Your implementation should check if the user has permission to perform this + operation. + + \param fs The file system provided cookie associated with this volume. + \param dir The file system provided cookie associated with the directory + the symbolic link should be created in. + \param name The name of the new symbolic link. + \param path The path of the original inode the symbolic link should refer to. + \param mode The mode that this symbolic link should be created in. (TODO + what exactly?) + \return \c B_OK if you succeeded, or an error code if you failed. +*/ + +/*! + \fn status_t (*file_system_module_info::link)(fs_volume fs, fs_vnode dir, const char *name, + fs_vnode vnode) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::unlink)(fs_volume fs, fs_vnode dir, const char *name) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::rename)(fs_volume fs, fs_vnode fromDir, const char *fromName, + fs_vnode toDir, const char *toName) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::access)(fs_volume fs, 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 (geteuid() == 0) does always have + read and write permissions, execution permission only when at least one of + the execution permission bits are set. + + \param fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::read_stat)(fs_volume fs, + fs_vnode vnode, struct stat *stat) + \brief Retrieves the stat data for a given node. + + All values of the struct stat save \c st_dev, \c st_ino, \c st_rdev, + and \c st_type need to be filled in. + + \param fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::write_stat)(fs_volume fs, fs_vnode vnode, + const struct stat *stat, uint32 statMask) + \brief Undocumented. +*/ + +//! @} + +/*! + \name File Operations +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::create)(fs_volume fs, fs_vnode dir, + const char *name, int openMode, int perms, fs_cookie *_cookie, + vnode_id *_newVnodeID) + \brief Create a new file. + + Your implementation shall check whether it is possible to create the node. + You will need to take the user's permissions into account. When you create + a new file, you will also have to open it. This means also checking the + permissions the user requires to open the file according to the \a mode. + See \link file_system_module_info::open() open() \endlink for the possible + values of \a mode. + + \param fs The file system provided cookie associated with this volume. + \param dir The file system provided cookie associated with 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 you can store your file system + data for this node in this variable. + \param[out] _newVnodeID In case of success, you can store the new vnode id + in this variable. + \return You should return \c B_OK if creating the new node succeeded, and if + you put data in both \a _cookie and \a _newVnodeID. Else you should return + an error code. +*/ + +/*! + \fn status_t (*file_system_module_info::open)(fs_volume fs, fs_vnode vnode, + int openMode, fs_cookie *_cookie) + \brief Opens the given node. + + The function shall check whether it is possible to open the node according to + the mode specified by \c openMode (also considering the user's access + permissions), create a node cookie, and store it in the variable + \a _cookie points to. + + 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. + + \param fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::close)(fs_volume fs, fs_vnode vnode, + fs_cookie 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. + + \param fs The volume handle. + \param vnode The node handle. + \param cookie The node cookie as returned by open(). + \return \c B_OK if everything went fine, another error code otherwise. +*/ + +/*! + \fn status_t (*file_system_module_info::free_cookie)(fs_volume fs, + fs_vnode vnode, fs_cookie 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 fs The volume handle. + \param vnode The node handle. + \param cookie The node cookie as returned by open(). + \return \c B_OK if everything went fine, another error code otherwise. +*/ + +/*! + \fn status_t (*file_system_module_info::read)(fs_volume fs, fs_vnode vnode, + fs_cookie 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 fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::write)(fs_volume fs, fs_vnode vnode, + fs_cookie 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 read the data, and no data have + been read at all. + + The number of bytes to be written is stored in the variable pointed to by + \a length. + + TODO: What to do if we were to write less than the \a length? Should this + function fail? + + \param fs The file system provided cookie associated with this volume. + \param vnode The file system provided cookie associated with the vnode. + \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 (*file_system_module_info::create_dir)(fs_volume fs, fs_vnode + parent, const char *name, int perms, vnode_id *_newVnodeID) + \brief Create a new directory. + + Your implementation should make sure that the directory actually can be + created in the \a parent directory. You will have to check if the user has + permissions to actually write to the \a parent. If not, this function should + fail (probably with \c B_NOT_ALLOWED, or in case of a read-only filesystem, + with \c B_READ_ONLY_DEVICE). If the operation succeeds, you should put the + new vnode id in \a _newVnodeID. + + \param fs The file system provided cookie associated with this volume. + \param parent The file system provided cookie associated with the parent + node. + \param name The name the new directory should have. + \param perms The permissions the new directory should have. + \param[out] _newVnodeID If creating the directory succeeds, than you should + put the new vnode id in this variable. + \return If the operation succeeds and the \a _newVnodeID is populated with + the new vnode, then you should return \c B_OK. Else you should return with + an error code. +*/ + +/*! + \fn status_t (*file_system_module_info::remove_dir)(fs_volume fs, fs_vnode + parent, const char *name) + \brief Remove a directory. + + You should make sure the user has the proper permissions. You should also + check that the directory is empty. + + \param fs The file system provided cookie associated with this volume. + \param parent The file system provided cookie associated with the parent + node. + \param name The \a name of the directory that needs to be removed. + \retval B_OK Operation succeeded. + \retval B_DIRECTORY_NOT_EMPTY The directory is not empty. + \retval B_ENTRY_NOT_FOUND There is no directory with this \a name. + \retval B_NOT_A_DIRECTORY The entry is not a directory. + \retval "other errors" Other errors occured. +*/ + +/*! + \fn status_t (*file_system_module_info::open_dir)(fs_volume fs, fs_vnode vnode, + fs_cookie *_cookie) + \brief Opens the given directory node. + + If the specified node is not a directory, or if the current user does not + have the permissions to read the 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 fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::close_dir)(fs_volume fs, + fs_vnode vnode, fs_cookie cookie) + \brief Closes the given directory cookie. + + Generally the situation is similar to the one described for close(). In + practice it is a bit, 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 reading a directory + should not block. Therefore for most FSs this hook is a no-op. + + \param fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::free_dir_cookie)(fs_volume fs, + fs_vnode vnode, fs_cookie 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 fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::read_dir)(fs_volume fs, fs_vnode vnode, + fs_cookie 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 begins directly after the end of the + first one (i.e. \c d_reclen bytes after the beginning of the first one). + Most FSs read only one entry at a time though, even if more are requested. + + When the function is invoked after the end of the directory has been reached, + it shall set the variable \a _num points to to \c 0 and return \c B_OK. 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. + + 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 fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::rewind_dir)(fs_volume fs, + fs_vnode vnode, fs_cookie cookie) + \brief Resets the directory cookie to the first entry of the directory. + \param fs The volume handle. + \param vnode The node handle. + \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 (*file_system_module_info::open_attr_dir)(fs_volume fs, fs_vnode vnode, fs_cookie *_cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::close_attr_dir)(fs_volume fs, fs_vnode vnode, fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::free_attr_dir_cookie)(fs_volume fs, fs_vnode vnode, + fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::read_attr_dir)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + struct dirent *buffer, size_t bufferSize, uint32 *_num) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::rewind_attr_dir)(fs_volume fs, fs_vnode vnode, fs_cookie cookie) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Attribute Operations +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::create_attr)(fs_volume fs, fs_vnode vnode, const char *name, + uint32 type, int openMode, fs_cookie *_cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::open_attr)(fs_volume fs, fs_vnode vnode, const char *name, + int openMode, fs_cookie *_cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::close_attr)(fs_volume fs, fs_vnode vnode, fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::free_attr_cookie)(fs_volume fs, fs_vnode vnode, + fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::read_attr)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + off_t pos, void *buffer, size_t *length) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::write_attr)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + off_t pos, const void *buffer, size_t *length) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::read_attr_stat)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + struct stat *stat) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::write_attr_stat)(fs_volume fs, fs_vnode vnode, fs_cookie cookie, + const struct stat *stat, int statMask) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::rename_attr)(fs_volume fs, fs_vnode fromVnode, + const char *fromName, fs_vnode toVnode, const char *toName) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::remove_attr)(fs_volume fs, fs_vnode vnode, const char *name) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Index Directory and Operation +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::open_index_dir)(fs_volume fs, fs_cookie *cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::close_index_dir)(fs_volume fs, fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::free_index_dir_cookie)(fs_volume fs, fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::read_index_dir)(fs_volume fs, fs_cookie cookie, + struct dirent *buffer, size_t bufferSize, uint32 *_num) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::rewind_index_dir)(fs_volume fs, fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::create_index)(fs_volume fs, const char *name, uint32 type, + uint32 flags) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::remove_index)(fs_volume fs, const char *name) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::read_index_stat)(fs_volume fs, const char *name, + struct stat *stat) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Query Operations +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::open_query)(fs_volume fs, const char *query, uint32 flags, + port_id port, uint32 token, fs_cookie *_cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::close_query)(fs_volume fs, fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::free_query_cookie)(fs_volume fs, fs_cookie cookie) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::read_query)(fs_volume fs, + fs_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num) + \brief Reads the next one or more entries matching the query. + + This hook function works pretty much the same way as read_dir(), with the + difference that it doesn't read the entries of a directory, but the entries + matching the given query. + + \param fs The volume handle. + \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 (*file_system_module_info::rewind_query)(fs_volume fs, fs_cookie cookie) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Capability Querying +*/ + +//! @{ + +/*! + \fn bool (*file_system_module_info::supports_defragmenting)(partition_data *partition, + bool *whileMounted) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::supports_repairing)(partition_data *partition, + bool checkOnly, bool *whileMounted) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::supports_resizing)(partition_data *partition, + bool *whileMounted) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::supports_moving)(partition_data *partition, bool *isNoOp) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::supports_setting_content_name)(partition_data *partition, + bool *whileMounted) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::supports_setting_content_parameters)(partition_data *partition, + bool *whileMounted) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::supports_initializing)(partition_data *partition) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::validate_resize)(partition_data *partition, off_t *size) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::validate_move)(partition_data *partition, off_t *start) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::validate_set_content_name)(partition_data *partition, + char *name) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::validate_set_content_parameters)(partition_data *partition, + const char *parameters) + \brief Undocumented. +*/ + +/*! + \fn bool (*file_system_module_info::validate_initialize)(partition_data *partition, char *name, + const char *parameters) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Shadow Partition Modification +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::shadow_changed)(partition_data *partition, + uint32 operation) + \brief Undocumented. +*/ + +//! @} + +/*! + \name Special Operations +*/ + +//! @{ + +/*! + \fn status_t (*file_system_module_info::defragment)(int fd, partition_id partition, + disk_job_id job) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::repair)(int fd, partition_id partition, bool checkOnly, + disk_job_id job) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::resize)(int fd, partition_id partition, off_t size, + disk_job_id job) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::move)(int fd, partition_id partition, off_t offset, + disk_job_id job) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::set_content_name)(int fd, partition_id partition, + const char *name, disk_job_id job) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::set_content_parameters)(int fd, partition_id partition, + const char *parameters, disk_job_id job) + \brief Undocumented. +*/ + +/*! + \fn status_t (*file_system_module_info::initialize)(const char *partition, const char *name, + const char *parameters, disk_job_id job) + \brief Undocumented. +*/ + +//! @} + +///// Global Functions ///// + +/*! + \fn status_t new_vnode(mount_id mountID, vnode_id vnodeID, + fs_vnode privateNode) + \brief Creates 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 file_system_module_info::remove_vnode remove_vnode() \endlink is not + invoked. + + 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(). + + The function fails, if the vnode does already exist. + + \param mountID The ID of the volume. + \param vnodeID The ID of the node. + \param privateNode The private data handle to be associated with the node. + \return \c B_OK if everything went fine, another error code otherwise. */ /*! -\fn status_t new_vnode(mount_id mountID, vnode_id vnodeID, fs_vnode privateNode) -\brief Creates the vnode with ID \a vnodeID and associates it with the private - data handle \a privateNode, but leaves is in an unpublished state. + \fn status_t publish_vnode(mount_id mountID, vnode_id vnodeID, + fs_vnode privateNode) + \brief Creates the vnode with ID \a vnodeID and associates it with the + private data handle \a privateNode or just marks it published. -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 file_system_module_info::remove_vnode remove_vnode() \endlink is not -invoked. + 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 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(). + 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(). -The function fails, if the vnode does already exist. - -\param mountID The ID of the volume. -\param vnodeID The ID of the node. -\param privateNode The private data handle to be associated with the node. -\return \c B_OK if everything went fine, another error code otherwise. + \param mountID The ID of the volume. + \param vnodeID The ID of the node. + \param privateNode The private data handle to be associated with the node. + \return \c B_OK if everything went fine, another error code otherwise. */ /*! -\fn status_t publish_vnode(mount_id mountID, vnode_id vnodeID, - fs_vnode privateNode) -\brief Creates the vnode with ID \a vnodeID and associates it with the private - data handle \a privateNode or just marks it published. + \fn status_t get_vnode(mount_id mountID, vnode_id vnodeID, + fs_vnode *_privateNode) + \brief Retrieves the private data handle for the node with the given ID. -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. The + reference can be surrendered by calling put_vnode(). -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(). - -\param mountID The ID of the volume. -\param vnodeID The ID of the node. -\param privateNode The private data handle to be associated with the node. -\return \c B_OK if everything went fine, another error code otherwise. + \param mountID The ID of the volume. + \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 get_vnode(mount_id mountID, vnode_id vnodeID, - fs_vnode *_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 mountID The ID of the volume. -\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(mount_id mountID, vnode_id vnodeID) + \brief Surrenders a reference to the specified vnode. + \param mountID The ID of the volume. + \param vnodeID The ID of the node. + \return \c B_OK if everything went fine, another error code otherwise. */ /*! -\fn status_t put_vnode(mount_id mountID, vnode_id vnodeID) -\brief Surrenders a reference to the specified vnode. -\param mountID The ID of the volume. -\param vnodeID The ID of the node. -\return \c B_OK if everything went fine, another error code otherwise. + \fn status_t remove_vnode(mount_id mountID, vnode_id 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 file system's + \link file_system_module_info::remove_vnode remove_vnode() \endlink + hook. + + \param mountID The ID of the volume. + \param vnodeID The ID of the node. + \return \c B_OK if everything went fine, another error code otherwise. */ /*! -\fn status_t remove_vnode(mount_id mountID, vnode_id vnodeID) -\brief Marks the specified vnode removed. + \fn status_t unremove_vnode(mount_id mountID, vnode_id 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 does not surrender a reference, -though. + The caller must own a reference to the vnode or at least ensure that a + reference to the vnode exists. -As soon as the last reference to the vnode has been surrendered, the VFS -invokes the file system's -\link file_system_module_info::remove_vnode remove_vnode() \endlink -hook. + 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). -\param mountID The ID of the volume. -\param vnodeID The ID of the node. -\return \c B_OK if everything went fine, another error code otherwise. + \param mountID The ID of the volume. + \param vnodeID The ID of the node. + \return \c B_OK if everything went fine, another error code otherwise. */ /*! -\fn status_t unremove_vnode(mount_id mountID, vnode_id vnodeID); -\brief Clears the "removed" mark of the specified vnode. + \fn status_t get_vnode_removed(mount_id mountID, vnode_id 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. + 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). + \param mountID The ID of the volume. + \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. +*/ -\param mountID The ID of the volume. -\param vnodeID The ID of the node. -\return \c B_OK if everything went fine, another error code otherwise. +///// Deprecated Global Functions + +/*! + \name Deprecated functions + + The following list of functions should not be used, and could be removed even + before the release of Haiku R1. +*/ + +//! @{ + +/*! + \fn status_t notify_listener(int op, mount_id device, vnode_id parentNode, + vnode_id toParentNode, vnode_id node, const char *name) + \brief Deprecated. This feature will be removed in future versions. */ /*! -\fn status_t get_vnode_removed(mount_id mountID, vnode_id 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 mountID The ID of the volume. -\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. -*/ - - -/*! -\class file_system_module_info -\brief Kernel module interface for file systems. + \fn status_t notify_entry_created(mount_id device, vnode_id directory, + const char *name, vnode_id node) + \brief Deprecated. This feature will be removed in future versions. */ /*! -\fn status_t (*file_system_module_info::mount)(mount_id id, const char *device, - uint32 flags, const char *args, fs_volume *_fs, vnode_id *_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 _fs. 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 id The ID of the volume to be mounted. It should be saved in the FS's - volume private data (volume handle). -\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 _fs Pointer to a pre-allocated variable the volume handle shall be - written to. -\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. + \fn status_t notify_entry_removed(mount_id device, vnode_id directory, + const char *name, vnode_id node) + \brief Deprecated. This feature will be removed in future versions. */ /*! -\fn status_t (*file_system_module_info::unmount)(fs_volume fs) -\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. Although the mount() hook called publish_vnode() for the root node -of the volume, unmount() must not invoke put_vnode(). - -\param fs The volume handle. -\return \c B_OK if everything went fine, another error code otherwise. The - error code will be ignored, though. + \fn status_t notify_entry_moved(mount_id device, vnode_id fromDirectory, + const char *fromName, vnode_id toDirectory, + const char *toName, vnode_id node) + \brief Deprecated. This feature will be removed in future versions. */ /*! -\fn status_t (*file_system_module_info::read_fs_info)(fs_volume fs, - 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 device_name: The name of the device or image file containing the volume. - Non-disk-based FSs shall fill in an empty string. -- \c volume_name: The name of the volume. - -The other values are filled in by the VFS. - -\param fs The volume handle. -\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 notify_stat_changed(mount_id device, vnode_id node, + uint32 statFields) + \brief Deprecated. This feature will be removed in future versions. */ /*! -\fn status_t (*file_system_module_info::lookup)(fs_volume fs, fs_vnode dir, - const char *name, vnode_id *_id, int *_type) -\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 and the type of the node -in \a _id and \a _type respectively. - -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 fs The volume handle. -\param dir The node handle of 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. -\param _type Pointer to a pre-allocated variable the type of the found node - shall be written to. The type is encoded as in the \c st_mode field of a - struct stat (bitwise anded with \c S_IFMT). -\retval B_OK Everything went fine. -\retval B_ENTRY_NOT_FOUND The given directory does not contain an entry with - the given name. + \fn status_t notify_attribute_changed(mount_id device, vnode_id node, + const char *attribute, int32 cause) + \brief Deprecated. This feature will be removed in future versions. */ /*! -\fn status_t (*file_system_module_info::get_vnode)(fs_volume fs, vnode_id id, - fs_vnode *_vnode, 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. - -\param fs The volume handle. -\param id The ID of the node. -\param _vnode Pointer to a pre-allocated variable the node handle shall be - written to. -\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. + \fn status_t notify_query_entry_created(port_id port, int32 token, + mount_id device, vnode_id directory, const char *name, + vnode_id node) + \brief Deprecated. This feature will be removed in future versions. */ /*! -\fn \fn status_t (*file_system_module_info::put_vnode)(fs_volume fs, - 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 fs The volume handle. -\param vnode The node handle. -\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 notify_query_entry_removed(port_id port, int32 token, + mount_id device, vnode_id directory, const char *name, + vnode_id node) + \brief Deprecated. This feature will be removed in future versions. */ -/*! -\fn status_t (*file_system_module_info::remove_vnode)(fs_volume fs, - 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 marked removed. - -\param fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::read_symlink)(fs_volume fs, - fs_vnode link, char *buffer, size_t *_bufferSize) -\brief Reads the value of a symlink. - -If the function is successful, the string written to the buffer shall be -null-terminated and the variable \a _bufferSize points to shall be set to -the length of that string, including the terminating null character. - -\param fs The volume handle. -\param link The node handle. -\param buffer Pointer to a pre-allocated buffer the link value shall be written - to. -\param buffer Pointer to a pre-allocated variable containing the size of the - buffer supplied to the function. Upon successful completion the hook shall - store the number of bytes actually written into the buffer in the variable. -\retval B_OK Everything went fine. -\retval B_BAD_VALUE \a link does not identify a symbolic link. -\retval B_BUFFER_OVERFLOW The supplied buffer is not big enough to contain the - complete link value. -*/ - -/*! -\fn status_t (*file_system_module_info::access)(fs_volume fs, 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 (geteuid() == 0) does always have -read and write permissions, execution permission only when at least one of the -execution permission bits are set. - -\param fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::read_stat)(fs_volume fs, - fs_vnode vnode, struct stat *stat) -\brief Retrieves the stat data for a given node. - -All values of the struct stat save \c st_dev, \c st_ino, \c st_rdev, -and \c st_type need to be filled in. - -\param fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::open)(fs_volume fs, fs_vnode vnode, - int openMode, fs_cookie *_cookie) -\brief Opens the given node. - -The function shall check whether it is possible to open the node according to -the mode specified by \c openMode (also considering the user's access -permissions), create a node cookie, and store it in the variable -\a _cookie points to. - -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. - -\param fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::close)(fs_volume fs, fs_vnode vnode, - fs_cookie 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. - -\param fs The volume handle. -\param vnode The node handle. -\param cookie The node cookie as returned by open(). -\return \c B_OK if everything went fine, another error code otherwise. -*/ - -/*! -\fn status_t (*file_system_module_info::free_cookie)(fs_volume fs, - fs_vnode vnode, fs_cookie 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 fs The volume handle. -\param vnode The node handle. -\param cookie The node cookie as returned by open(). -\return \c B_OK if everything went fine, another error code otherwise. -*/ - -/*! -\fn status_t (*file_system_module_info::read)(fs_volume fs, fs_vnode vnode, - fs_cookie cookie, off_t pos, void *buffer, size_t *length) -\brief Reads data from a file. - -The function shall failed 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 are 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 fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::open_dir)(fs_volume fs, fs_vnode vnode, - fs_cookie *_cookie) -\brief Opens the given directory node. - -If the specified node is not a directory, or if the current user does not have -the permissions to read the 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 fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::close_dir)(fs_volume fs, - fs_vnode vnode, fs_cookie cookie) -\brief Closes the given directory cookie. - -Generally the situation is similar to the one described for close(). In -practice it is a bit, 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 reading a directory -should not block. Therefore for most FSs this hook is a no-op. - -\param fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::free_dir_cookie)(fs_volume fs, - fs_vnode vnode, fs_cookie 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 fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::read_dir)(fs_volume fs, fs_vnode vnode, - fs_cookie 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 begins directly after the end of the -first one (i.e. \c d_reclen bytes after the beginning of the first one). -Most FSs read only one entry at a time though, even if more are requested. - -When the function is invoked after the end of the directory has been reached, -it shall set the variable \a _num points to to \c 0 and return \c B_OK. 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. - -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 fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::rewind_dir)(fs_volume fs, - fs_vnode vnode, fs_cookie cookie) -\brief Resets the directory cookie to the first entry of the directory. -\param fs The volume handle. -\param vnode The node handle. -\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 (*file_system_module_info::read_query)(fs_volume fs, - fs_cookie cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num) -\brief Reads the next one or more entries matching the query. - -This hook function works pretty much the same way as read_dir(), with the -difference that it doesn't read the entries of a directory, but the entries -matching the given query. - -\param fs The volume handle. -\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. -*/ +//! @} diff --git a/docs/user/drivers/fs_modules.dox b/docs/user/drivers/fs_modules.dox index d4e86e4219..186b8f59d0 100644 --- a/docs/user/drivers/fs_modules.dox +++ b/docs/user/drivers/fs_modules.dox @@ -1,199 +1,212 @@ -/*! -\page fs_modules File System Modules +/* + * Copyright 2007 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ + + /*! + \page fs_modules File System Modules -To support a particular file system (FS), a kernel module implementing a special -interface (\c file_system_module_info defined in \c ) has to be -provided. As for any other module the -\c std_ops() hook is invoked with \c B_MODULE_INIT directly after the FS module -has been loaded by the kernel, and with \c B_MODULE_UNINIT before it is -unloaded, thus providing a simple mechanism for one-time module initializations. -The same module is used for accessing any volume of that FS type. + To support a particular file system (FS), a kernel module implementing a + special interface (\c file_system_module_info defined in \c ) + has to be provided. As for any other module the \c std_ops() hook is invoked + with \c B_MODULE_INIT directly after the FS module has been loaded by the + kernel, and with \c B_MODULE_UNINIT before it is unloaded, thus providing + a simple mechanism for one-time module initializations. The same module is + used for accessing any volume of that FS type. -\section objects File System Objects + \section objects File System Objects -There are several types of objects a FS module has to deal with directly or -indirectly: + There are several types of objects a FS module has to deal with directly or + indirectly: -- A \em volume is an instance of a file system. For a disk-based file - system it corresponds to a disk, partition, or disk image file. When - mounting a volume the virtual file system layer (VFS) assigns a unique number - (ID, of type \c mount_id aka \c dev_t) to it and a handle (type - \c fs_volume, in fact \c void*) provided by - the file system. Whenever the FS requests a volume-related service from the - kernel, it has to pass the volume ID, and whenever the VFS asks the FS to - perform an operation, it supplies the handle. Normally the handle is a pointer - to a data structure the FS allocates to associate data with the volume. + - A \em volume is an instance of a file system. For a disk-based file + system it corresponds to a disk, partition, or disk image file. When + mounting a volume the virtual file system layer (VFS) assigns a unique + number (ID, of type \c mount_id aka \c dev_t) to it and a handle (type + \c fs_volume, in fact \c void*) provided by + the file system. Whenever the FS requests a volume-related service from the + kernel, it has to pass the volume ID, and whenever the VFS asks the FS to + perform an operation, it supplies the handle. Normally the handle is a + pointer to a data structure the FS allocates to associate data with the + volume. -- A \em node is contained by a volume. It can be of type file, directory, or - symbolic link (symlink). Just as volumes nodes are associated with an ID - (type \c vnode_id aka ino_t) and, if in use, also with a handle - (type \c fs_vnode, in fact \c void*). - Unlike the volume ID the node ID is defined by the FS. It often - has a meaning to the FS, e.g. file systems using inodes might choose the - inode number corresponding to the node. As long as the volume is mounted and - the node is known to the VFS, its node ID must not change. The node handle is - again a pointer to a data structure allocated by the FS. - -- A \em vnode (VFS node) is the VFS representation of a node. A volume may - contain a great number of nodes, but at a time only a few are represented by - vnodes, usually only those that are currently in use (sometimes a few more). + - A \em node is contained by a volume. It can be of type file, directory, or + symbolic link (symlink). Just as volumes nodes are associated with an ID + (type \c vnode_id aka ino_t) and, if in use, also with a handle + (type \c fs_vnode, in fact \c void*). + Unlike the volume ID the node ID is defined by the FS. It often + has a meaning to the FS, e.g. file systems using inodes might choose the + inode number corresponding to the node. As long as the volume is mounted + and the node is known to the VFS, its node ID must not change. The node + handle is again a pointer to a data structure allocated by the FS. + + - A \em vnode (VFS node) is the VFS representation of a node. A volume may + contain a great number of nodes, but at a time only a few are represented + by vnodes, usually only those that are currently in use (sometimes a few + more). -- An \em entry (directory entry) belongs to a directory, has a name, and refers - to a node. It is important to understand the difference between entries and - nodes: A node doesn't have a name, only the entries that refer to it have. - If a FS supports to have more than one entry refer to a single node, it is - also said to support "hard links". It is possible that no entry refers - to a node. This happens when a node (e.g. a file) is still open, but the last - entry referring to it has been removed (the node will be deleted when the - it is closed). While entries are to be understood as independent entities, - the FS interface does not use IDs or handles to refer to them; it always uses - directory and entry name pairs to do that. + - An \em entry (directory entry) belongs to a directory, has a name, and + refers to a node. It is important to understand the difference between + entries and nodes: A node doesn't have a name, only the entries that refer + to it have. If a FS supports to have more than one entry refer to a single + node, it is also said to support "hard links". It is possible that no entry + refers to a node. This happens when a node (e.g. a file) is still open, but + the last entry referring to it has been removed (the node will be deleted + when the it is closed). While entries are to be understood as independent + entities, the FS interface does not use IDs or handles to refer to them; + it always uses directory and entry name pairs to do that. -- An \em attribute is a named and typed data container belonging to a node. A - node may have any number of attributes; they are organized in a (virtual or - actually existing) attribute directory, through which one can iterate. + - An \em attribute is a named and typed data container belonging to a node. A + node may have any number of attributes; they are organized in a (virtual or + actually existing) attribute directory, through which one can iterate. -- An \em index is supposed to provide fast searching capabilities for attributes - with a certain name. A volume's index directory allows for iterating through - the indices. + - An \em index is supposed to provide fast searching capabilities for + attributes with a certain name. A volume's index directory allows for + iterating through the indices. -- A \em query is a fully virtual object for searching for entries via an - expression matching entry name, node size, node modification date, and/or - node attributes. The mechanism of retrieving the entries found by a query - is similar to that for reading a directory contents. A query can be live - in which case the creator of the query is notified by the FS whenever an - entry no longer matches the query expression or starts matching. + - A \em query is a fully virtual object for searching for entries via an + expression matching entry name, node size, node modification date, and/or + node attributes. The mechanism of retrieving the entries found by a query + is similar to that for reading a directory contents. A query can be live + in which case the creator of the query is notified by the FS whenever an + entry no longer matches the query expression or starts matching. -\section concepts Generic Concepts + \section concepts Generic Concepts -A FS module has to (or can) provide quite a lot of hook functions. There are -a few concepts that apply to several groups of them: + A FS module has to (or can) provide quite a lot of hook functions. There are + a few concepts that apply to several groups of them: -- Opening, Closing, and Cookies: Many FS objects can be opened and - closed, namely nodes in general, directories, attribute directories, - attributes, the index directory, and queries. In each case there are three - hook functions: open*(), close*(), and - free*_cookie(). The open*() hook is passed all that is - needed to identify the object to be opened and, in some cases, additional - parameters e.g. specifying a particular opening mode. The implementation - is required to return a cookie (type \c fs_cookie, in fact \c void*), usually - a pointer to a data structure the FS allocates. In some cases (e.g. when an - iteration state is associated with the cookie) a new cookie must be allocated - for each instance of opening the object. The cookie is passed to all hooks - that operate on a thusly opened object. The close*() hook is invoked - to signal that the cookie is to be closed. At this point the cookie might - still be in use. Blocking FS hooks (e.g. blocking read/write operations) - using the same cookie have to be unblocked. When the cookie stops being in - use the free*_cookie() hook is called; it has to free the cookie. + - Opening, Closing, and Cookies: Many FS objects can be opened and + closed, namely nodes in general, directories, attribute directories, + attributes, the index directory, and queries. In each case there are three + hook functions: open*(), close*(), and + free*_cookie(). The open*() hook is passed all that is + needed to identify the object to be opened and, in some cases, additional + parameters e.g. specifying a particular opening mode. The implementation + is required to return a cookie (type \c fs_cookie, in fact \c void*), + usually a pointer to a data structure the FS allocates. In some cases (e.g. + when an iteration state is associated with the cookie) a new cookie must + be allocated for each instance of opening the object. The cookie is passed + to all hooks that operate on a thusly opened object. The close*() + hook is invoked to signal that the cookie is to be closed. At this point + the cookie might still be in use. Blocking FS hooks (e.g. blocking + read/write operations) using the same cookie have to be unblocked. When + the cookie stops being in use the free*_cookie() hook is called; + it has to free the cookie. -- Entry Iteration: For the FS objects serving as containers for other - objects, i.e. directories, attribute directories, the index directory, - and queries, the cookie mechanism is used for a stateful iteration through - the contained objects. The read_*() hook reads the next one or more - entries into a struct dirent buffer. The rewind_*() hook - resets the iteration state to the first entry. + - Entry Iteration: For the FS objects serving as containers for + other objects, i.e. directories, attribute directories, the index + directory, and queries, the cookie mechanism is used for a stateful + iteration through the contained objects. The read_*() hook reads + the next one or more entries into a struct dirent buffer. The + rewind_*() hook resets the iteration state to the first entry. -- Stat Information: In case of nodes, attributes, and indices - detailed information about an object are requested via a read*_stat() - hook and must be written into a struct stat buffer. + - Stat Information: In case of nodes, attributes, and indices + detailed information about an object are requested via a + read*_stat() hook and must be written into a struct stat + buffer. -\section vnodes VNodes + \section vnodes VNodes -A vnode is the VFS representation of a node. As soon as an access to a node -is requested, the VFS creates a corresponding vnode. The requesting entity -gets a reference to the vnode for the time it works with the vnode and -releases the reference when done. When the last reference to a vnode has been -surrendered, the vnode is unused and the VFS can decide to destroy it (usually -it is cached for a while longer). + A vnode is the VFS representation of a node. As soon as an access to a node + is requested, the VFS creates a corresponding vnode. The requesting entity + gets a reference to the vnode for the time it works with the vnode and + releases the reference when done. When the last reference to a vnode has been + surrendered, the vnode is unused and the VFS can decide to destroy it + (usually it is cached for a while longer). -When the VFS creates a vnode, it invokes the FS's -\link file_system_module_info::get_vnode get_vnode() \endlink -hook to let it create the respective node handle (unless the FS requests the -creation of the vnode explicitely by calling publish_vnode()). That's the only -hook that specifies a node by ID; to all other node-related hooks the node -handle is passed. When the VFS deletes the vnode, it invokes the FS's -\link file_system_module_info::put_vnode put_vnode() \endlink -hook or, if the node was marked removed, -\link file_system_module_info::remove_vnode remove_vnode() \endlink. + When the VFS creates a vnode, it invokes the FS's + \link file_system_module_info::get_vnode get_vnode() \endlink + hook to let it create the respective node handle (unless the FS requests the + creation of the vnode explicitely by calling publish_vnode()). That's the + only hook that specifies a node by ID; to all other node-related hooks the + node handle is passed. When the VFS deletes the vnode, it invokes the FS's + \link file_system_module_info::put_vnode put_vnode() \endlink + hook or, if the node was marked removed, + \link file_system_module_info::remove_vnode remove_vnode() \endlink. -There are only four FS hooks through which the VFS gains knowledge of the -existence of a node. The first one is the -\link file_system_module_info::mount mount() \endlink -hook. It is supposed to call \c publish_vnode() for the root node of the volume -and return its ID. The second one is the -\link file_system_module_info::lookup lookup() \endlink -hook. Given a node handle of a directory and an entry name, it is supposed to -call \c get_vnode() for the node the entry refers to and return the node ID. -The remaining two hooks, -\link file_system_module_info::read_dir read_dir() \endlink -and -\link file_system_module_info::read_query read_query() \endlink, -both return entries in a struct dirent structure, which also contains -the ID of the node the entry refers to. + There are only four FS hooks through which the VFS gains knowledge of the + existence of a node. The first one is the + \link file_system_module_info::mount mount() \endlink + hook. It is supposed to call \c publish_vnode() for the root node of the + volume and return its ID. The second one is the + \link file_system_module_info::lookup lookup() \endlink + hook. Given a node handle of a directory and an entry name, it is supposed to + call \c get_vnode() for the node the entry refers to and return the node ID. + The remaining two hooks, + \link file_system_module_info::read_dir read_dir() \endlink and + \link file_system_module_info::read_query read_query() \endlink, + both return entries in a struct dirent structure, which also + contains the ID of the node the entry refers to. -\section mandatory_hooks Mandatory Hooks + \section mandatory_hooks Mandatory Hooks -Which hooks a FS module should provide mainly depends on what functionality -it features. E.g. a FS without support for attribute, indices, and/or queries -can omit the respective hooks (i.e. set them to \c NULL in the module -structure). Some hooks are mandatory, though. A minimal read-only FS module -must implement: + Which hooks a FS module should provide mainly depends on what functionality + it features. E.g. a FS without support for attribute, indices, and/or queries + can omit the respective hooks (i.e. set them to \c NULL in the module + structure). Some hooks are mandatory, though. A minimal read-only FS module + must implement: -- \link file_system_module_info::mount mount() \endlink and - \link file_system_module_info::unmount unmount() \endlink: - Mounting and unmounting a volume is required for pretty obvious reasons. + - \link file_system_module_info::mount mount() \endlink and + \link file_system_module_info::unmount unmount() \endlink: + Mounting and unmounting a volume is required for pretty obvious reasons. -- \link file_system_module_info::lookup lookup() \endlink: - The VFS uses this hook to resolve path names. It is probably one of the - most frequently invoked hooks. + - \link file_system_module_info::lookup lookup() \endlink: + The VFS uses this hook to resolve path names. It is probably one of the + most frequently invoked hooks. -- \link file_system_module_info::get_vnode get_vnode() \endlink and - \link file_system_module_info::put_vnode put_vnode() \endlink: - Create respectively destroy the FS's private node handle when - the VFS creates/deletes the vnode for a particular node. + - \link file_system_module_info::get_vnode get_vnode() \endlink and + \link file_system_module_info::put_vnode put_vnode() \endlink: + Create respectively destroy the FS's private node handle when + the VFS creates/deletes the vnode for a particular node. -- \link file_system_module_info::read_stat read_stat() \endlink: - Return a struct stat info for the given node, consisting of the - type and size of the node, its owner and access permissions, as well as - certain access times. + - \link file_system_module_info::read_stat read_stat() \endlink: + Return a struct stat info for the given node, consisting of the + type and size of the node, its owner and access permissions, as well as + certain access times. -- \link file_system_module_info::open open() \endlink, - \link file_system_module_info::close close() \endlink, and - \link file_system_module_info::free_cookie free_cookie() \endlink: - Open and close a node as explained in \ref concepts. + - \link file_system_module_info::open open() \endlink, + \link file_system_module_info::close close() \endlink, and + \link file_system_module_info::free_cookie free_cookie() \endlink: + Open and close a node as explained in \ref concepts. -- \link file_system_module_info::read read() \endlink: - Read data from an opened node (file). Even if the FS does not feature files, - the hook has to be present anyway; it should return an error in this case. + - \link file_system_module_info::read read() \endlink: + Read data from an opened node (file). Even if the FS does not feature + files, the hook has to be present anyway; it should return an error in this + case. -- \link file_system_module_info::open_dir open_dir() \endlink, - \link file_system_module_info::close_dir close_dir() \endlink, and - \link file_system_module_info::free_dir_cookie free_dir_cookie() \endlink: - Open and close a directory for entry iteration as explained in \ref concepts. + - \link file_system_module_info::open_dir open_dir() \endlink, + \link file_system_module_info::close_dir close_dir() \endlink, and + \link file_system_module_info::free_dir_cookie free_dir_cookie() \endlink: + Open and close a directory for entry iteration as explained in + \ref concepts. -- \link file_system_module_info::read_dir read_dir() \endlink and - \link file_system_module_info::rewind_dir rewind_dir() \endlink: - Read the next entry/entries from a directory, respectively reset the iterator - to the first entry, as explained in \ref concepts. + - \link file_system_module_info::read_dir read_dir() \endlink and + \link file_system_module_info::rewind_dir rewind_dir() \endlink: + Read the next entry/entries from a directory, respectively reset the + iterator to the first entry, as explained in \ref concepts. -Although not strictly mandatory, a FS should additionally implement the -following hooks: + Although not strictly mandatory, a FS should additionally implement the + following hooks: -- \link file_system_module_info::read_fs_info read_fs_info() \endlink: - Return general information about the volume, e.g. total and free size, and - what special features (attributes, MIME types, queries) the volume/FS - supports. + - \link file_system_module_info::read_fs_info read_fs_info() \endlink: + Return general information about the volume, e.g. total and free size, and + what special features (attributes, MIME types, queries) the volume/FS + supports. -- \link file_system_module_info::read_symlink read_symlink() \endlink: - Read the value of a symbolic link. Needed only, if the FS and volume support - symbolic links at all. If absent symbolic links stored on the volume won't - be interpreted. + - \link file_system_module_info::read_symlink read_symlink() \endlink: + Read the value of a symbolic link. Needed only, if the FS and volume + support symbolic links at all. If absent symbolic links stored on the + volume won't be interpreted. -- \link file_system_module_info::access access() \endlink: - Return whether the current user has the given access permissions for a node. - If the hook is absent the user is considerd to have all permissions. + - \link file_system_module_info::access access() \endlink: + Return whether the current user has the given access permissions for a + node. If the hook is absent the user is considerd to have all permissions. */