diff --git a/docs/user/Doxyfile b/docs/user/Doxyfile index 2c443684a9..4d12059e3e 100644 --- a/docs/user/Doxyfile +++ b/docs/user/Doxyfile @@ -460,9 +460,11 @@ WARN_LOGFILE = # with spaces. INPUT = . \ + drivers \ midi \ midi2 \ support \ + ../../headers/os/drivers/fs_interface.h \ ../../headers/os/midi2 \ ../../headers/os/support \ ../../headers/posix/syslog.h diff --git a/docs/user/book.dox b/docs/user/book.dox index a89fed4ea8..282aa7c4a1 100644 --- a/docs/user/book.dox +++ b/docs/user/book.dox @@ -3,6 +3,7 @@ \section kits Kits and Servers + - \ref drivers - \ref midi1 - \ref midi2 | \link midi2_intro \em Introduction \endlink - \ref support | \link support_intro \em Introduction \endlink @@ -15,6 +16,7 @@ ///// Define main kits ///// /*! + \defgroup drivers Drivers \defgroup midi2 MIDI 2 Kit \brief API for producing and consuming MIDI events. \defgroup libmidi2 (libmidi2.so) @@ -29,4 +31,4 @@ /*! \defgroup support_globals Global functions in the support kit \ingroup support -*/ \ No newline at end of file +*/ diff --git a/docs/user/drivers/drivers.dox b/docs/user/drivers/drivers.dox new file mode 100644 index 0000000000..a7eee02e01 --- /dev/null +++ b/docs/user/drivers/drivers.dox @@ -0,0 +1,8 @@ +/*! +\page drivers Drivers + +\section topics Topics + +- \ref fs_modules + +*/ diff --git a/docs/user/drivers/fs_interface.dox b/docs/user/drivers/fs_interface.dox new file mode 100644 index 0000000000..1665bdb0cd --- /dev/null +++ b/docs/user/drivers/fs_interface.dox @@ -0,0 +1,173 @@ +/*! +\file fs_interface.h +\ingroup drivers +*/ + +/*! +\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 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. + +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(). + +\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 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 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 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 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. +*/ + +/*! +\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 (*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 private data 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 private data handle for the node. +\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 private data handle for the node. +\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. +*/ diff --git a/docs/user/drivers/fs_modules.dox b/docs/user/drivers/fs_modules.dox new file mode 100644 index 0000000000..d4ed416b0f --- /dev/null +++ b/docs/user/drivers/fs_modules.dox @@ -0,0 +1,123 @@ +/*! +\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. + + +\section objects File System Objects + +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 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 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. + +- 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 + +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. + +- 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. + + +\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). + +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. + +*/ +