This page provides the official documentation of the VFS-FS protocol of MINIX 3. It describes the protocol used between the VFS server and file servers responsible for mounted file systems. The current version documents the protocol used in Git commit dca81e05. If you update this document because of changes to MINIX 3, please mention the revision number of the change in the wiki comment.
The following information is written mainly for people implementing a file server.
All requests made in the VFS-FS protocol come from VFS; the file server only sends replies. Every request must be answered with exactly one reply. The first request from VFS is REQ_READSUPER; the last request is REQ_UNMOUNT. The file server must use sef_receive() or sef_receive_status() to receive messages, and should use send() to send replies.
The <minix/vfsif.h>
header file provides the definitions for requests, replies and message fields. VFS puts the request code in the type field of the request message. Request codes are always in the range VFS_BASE to VFS_BASE+NREQS, exclusive. The file server puts reply code for a request in the type field of the reply message. This is always OK (0) or a negative error code. Any request not implemented by the file server must return EINVAL or, preferably, ENOSYS.
It is possible for the file server to send a request to VFS in response to a request from VFS. Such requests always have a positive nonzero request code, which allows them to be distinguished from replies. VFS will process requests from a FS in reply to its own request, repeatedly, until it receives an actual reply. Support for such nested calls is limited and may break arbitrarily. Currently, VFS allows only the getsysinfo() system call to be invoked this way, for use by ProcFS.
The driver should use the System Event Framework (SEF). This framework automatically takes care of interaction with the Reincarnation Server (RS).
REQ_UNMOUNT is not a request for termination. Once the file system has been unmounted, the file server should terminate upon receipt of a SIGTERM signal. The file server must not terminate from a SIGTERM as long as the file system is still mounted (this situation can occur upon system shutdown), but should then terminate after processing a subsequent unmount request. In other words, the file server should terminate after it received a SIGTERM signal and it has been unmounted. The file system may, but need not support receipt of another REQ_READSUPER request after being unmounted.
Signals may be received by registering a signal handler callback function using the SEF API. Aside from the messages recognized by SEF, the file server will in principle not receive any messages besides requests from VFS.
If a file server returns an error in response to a request, that request is expected not to have had any effect: the state of the file server is exactly the same before and after the request, and no “progress” has been made in any sense.
A notable exception to these are the EENTERMOUNT, ELEAVEMOUNT and ESYMLINK pseudo-errors returned by REQ_LOOKUP. These errors are interpreted by VFS as part of the path lookup process, and are never passed back to the application. No other requests must return these errors.
VFS requests mainly revolve around inodes. In the VFS-FS protocol, inodes represent open files (of any type, including directories) in the system. Many requests operate on an inode, or on a directory entry (see below). An inode is uniquely identified by its inode number; the file server is responsible for picking inode numbers for its files. Inode number 0 is reserved and may mean “no inode” in some contexts.
Upon success, certain requests (REQ_READSUPER, REQ_LOOKUP, REQ_CREATE, REQ_NEWNODE) open an inode. Each open request for an inode increases that inode's reference count: the number of times the inode is opened by VFS. The REQ_PUTNODE request decreases an open inode's reference count, effectively closing the inode when its reference count has reached zero again. A file server should only treat the reference count as an indicator whether the inode is open or not. The actual reference count is meaningless, as VFS may delay REQ_PUTNODE requests for as long as the file remains open, or drop all but one references at any time.
VFS caches open inodes including some metadata, in the form of vnodes. Cached metadata includes the file's mode, size, owner UID and GID, and special device number. VFS only refers to open inodes in requests. That is, if an inode number is passed as part of a VFS request, the associated inode will have a nonzero reference count in the file server.
Data transferred between VFS (or the user process) and the FS that is not put in the request/reply messages, is passed using memory grants. An FS can use sys_safecopyfrom (for READ grants) or sys_safecopyto (for WRITE grants) to retrieve or store data. These functions may not succeed; any errors thrown by these functions must be passed back to VFS.
For grants used to pass strings from VFS to the file server, the provided grant and string length will include the terminating '\0' character. A notable exception is REQ_SLINK, which provides an unterminated string for the link target; similarly, REQ_RDLINK is expected to return an unterminated string. In all other cases, file servers may check for a positive nonzero length and the presence of the terminating '\0' character as part of protection against VFS bugs.
Several calls manipulate directory entries. A directory entry is always provided in the form of a containing directory inode number, which is guaranteed to be an inode for a directory by VFS, and a last path component, which is a name string passed via a grant (usually in the REQ_GRANT field of the request message) and a string length (usually in the REQ_PATH_LENGTH field).
Such a name string will never contain a '/' slash character, or contain a '\0' character anywhere else but at the end. As indicated above, it is guaranteed to end with a '\0' character, and the passed string length will include that character. The maximum string length, including terminating '\0' character, is limited to PATH_MAX+1 bytes. A file server is free not to accept long names by returning an ENAMETOOLONG error.
VFS generally does not perform any other checks on the last path component of such directory entries, leaving those up to each file server. For example, when VFS requests the creation of a new directory entry, a file server will have to make sure that an entry with that name does not already exist in that directory.
VFS takes care of all checks to make sure that no write requests are sent to a read-only file system. In principle, the file system should never have to return an EROFS error. A file server may choose to perform this check itself anyway, to protect against VFS bugs.
VFS performs all access permission checks, with one exception. During lookups, when an inode is used as a directory in the process of resolving a path, the file server needs to check whether the caller has search access for that directory. A file server may choose to perform other checks itself as well to protect against VFS bugs, but may not always be able to, since not all requests provide the caller's user and group ID.
Every file server is responsible for raw transfers from (REQ_BREAD) and to (REQ_BWRITE) the device that it has been mounted on. This allows it to keep its cache synchronized. Before such raw transfers are initiated, VFS will send a REQ_NEW_DRIVER request to the file server to indicate which driver label to use. The root file server has more responsibilities as far as this is concerned; see the next section.
MINIX 3 supports restarting crashed device drivers. This includes the block device drivers that file systems are mounted on. File servers may assume a crash-only model: a block device driver either returns a valid response to a request, or communication results in an error. This may be an IPC-level error or an ERESTART response code. IPC-level errors may be transient, and the file server should retry the original request at least once to see if another IPC-level error is generated. If so, the FS may assume that the device driver has become fully unavailable. An ERESTART response code indicates the driver has been restarted and the file server should reissue a BDEV_OPEN to the driver before retrying the request. Other non-IPC error codes may be transient. For robustness, the FS may choose to retry an operation a few times before propagating up the error. If at all possible, the file system should use the libbdev library to talk to block device drivers, which transparently takes care of all these issues.
The root file server (serving the “/” partition) has a number of additional responsibilities that other file servers do not have. In particular:
While file systems may support files of type named pipe (S_IFIFO) and of type socket (S_IFSOCK), they need not implement support for pipe communication nor unix domain socket communication. This is all handled by the Pipe File Server (PFS). PFS is also responsible for cloned devices and is consequently the only file server that has to support REQ_NEWNODE, to create deleted open files.
This specification reflects the protocol as it should be implemented, not how it is implemented by MFS. In particular, old and deprecated requests are not and should not be included.
The entire VFS-FS protocol is entirely POSIX-oriented. Any deviation from the requirements imposed by POSIX in this specification is unintentional except when mentioned explicitly. For convenience, links to the relevant Open Group function specifications and file access (ATIME), modification (MTIME) and change (CTIME) time-stamp update requirements are provided.
The reply codes in this document are advisory and mostly aimed at indicating additional restrictions needed for POSIX compliance. Not all of them may be applicable to every file server, and a file server may send other error codes where appropriate. Errors resulting from protocol validation checks (e.g. EROFS), and sys_safecopy.. errors, are not included.
The requests are ordered according to the following rough categorization:
Mount the file system.
Request fields
<16% >REQ_GRANT | <6% >m9_l2 | <12% >cp_grant_id_t | memory grant (READ) for the label of the block device driver to use |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the label |
REQ_DEV | m9_l5 | dev_t | device number of block device to mount |
REQ_FLAGS | m9_s3 | int | flag field containing a bitwise combination of the following possible flags: REQ_RDONLY (the file system is mounted read-only), REQ_ISROOT (the file system is the root file system) |
Reply fields
<16% >RES_INODE_NR | <6% >m9_l1 | <12% >ino_t | upon success: inode number of the root inode |
RES_MODE | m9_s2 | mode_t | upon success: mode of the root inode |
RES_FILE_SIZE_HI | m9_l2 | u32_t | upon success: file size of the root inode (upper 32 bits) |
RES_FILE_SIZE_LO | m9_l3 | u32_t | upon success: file size of the root inode (lower 32 bits) |
RES_UID | m9_s4 | uid_t | upon success: user ID of the root inode |
RES_GID | m9_s1 | gid_t | upon success: group ID of the root inode |
RES_CONREQS | m9_s3 | u16_t | upon success: number of concurrent requests that can be handled by FS |
Reply codes
<16% >EINVAL | label too long |
EINVAL | unable to retrieve endpoint from DS using label |
EINVAL | opening device driver failed |
EINVAL | reading superblock failed |
OK | file system initialized and mounted |
Description
Notes
Unmount the file system.
Request fields
Reply fields
Reply codes
<16% >OK | file system unmounted |
Description
Notes
vm_clear_cache()
. Failure to do so could cause corruption due to block aliasing (the same block being accessible through multiple devices). File servers that use libminixfs can use lmfs_invalidate()
.Resolve a path string to an inode.
Request fields
<16% >REQ_GRANT | <6% >m9_l2 | <12% >cp_grant_id_t | memory grant (READ | WRITE) of the buffer containing the pathname |
REQ_PATH_LEN | m9_s2 | int | length of the remaining part of the string to resolve | |
REQ_PATH_SIZE | m9_l5 | size_t | total size of the buffer | |
REQ_DIR_INO | m9_l3 | ino_t | inode number of the starting directory | |
REQ_ROOT_INO | m9_l4 | ino_t | inode number of the root directory of the caller, or 0 if not on this file system | |
REQ_FLAGS | m9_s3 | int | flag field containing a bitwise combination of the following possible flags: PATH_RET_SYMLINK (do not resolve a symlink as the last path component), PATH_GET_UCRED (copy credentials from VFS instead of using REQ_UID and REQ_GID) | |
REQ_UID | m9_s4 | uid_t | user ID of the caller | |
REQ_GID | m9_s1 | gid_t | group ID of the caller | |
REQ_GRANT2 | m9_l1 | cp_grant_id_t | memory grant (READ) of the vfs_ucred_t structure containing supplemental group data | |
REQ_UCRED_SIZE | m9_s4 | size_t | total size of vfs_ucred_t structure |
Reply fields
<16% >RES_INODE_NR | <6% >m9_l1 | <12% >ino_t | upon success: resulting file inode number |
RES_MODE | m9_s2 | mode_t | upon success: resulting file mode |
RES_FILE_SIZE_HI | m9_l2 | u32_t | upon success: resulting file size (upper 32 bits) |
RES_FILE_SIZE_LO | m9_l3 | u32_t | upon success: resulting file size (lower 32 bits) |
RES_DEV | m9_l4 | dev_t | upon success: resulting file device number |
RES_UID | m9_s4 | uid_t | upon success: resulting file user ID |
RES_GID | m9_s1 | gid_t | upon success: resulting file group ID |
RES_INODE_NR | m9_l1 | ino_t | upon EENTERMOUNT: inode number of the mountpoint inode |
RES_OFFSET | m9_s2 | int | upon EENTERMOUNT and ELEAVEMOUNT and ESYMLINK: new starting offset of string within buffer |
RES_SYMLOOP | m9_s3 | unsigned short | upon EENTERMOUNT and ELEAVEMOUNT and ESYMLINK: number of symbolic links followed |
Reply codes
<16% >ENAMETOOLONG | provided path length exceeds what file server can handle |
ENAMETOOLONG | any of the path components is longer than the file system supports |
ENOTDIR | any of the intermediate path components is not a directory |
EACCES | the caller has no search access permission on any of the intermediate directories |
ENFILE | no inodes are available in memory |
ELOOP | more than SYMLOOP_MAX symlinks were encountered during the lookup |
ENAMETOOLONG | resulting path to copy back (including terminating '\0') does not fit in provided buffer |
EENTERMOUNT | a mountpoint was encountered |
ELEAVEMOUNT | “..” is followed from the file system root and the file system root is not the caller root inode |
ESYMLINK | an absolute symlink was encountered |
OK | inode successfully looked up and opened |
Description
Notes
Create a regular file.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of the containing directory for the new file |
REQ_MODE | m9_s3 | mode_t | mode for the file |
REQ_UID | m9_s4 | uid_t | user ID for the file |
REQ_GID | m9_s1 | gid_t | group ID for the file |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for the last path component |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the last path component |
Reply fields
<16% >RES_INODE_NR | <6% >m9_l1 | <12% >ino_t | upon success: inode number of created file |
RES_MODE | m9_s2 | mode_t | upon success: mode of created file |
RES_FILE_SIZE_HI | m9_l2 | u32_t | upon success: file size of created file (upper 32 bits) |
RES_FILE_SIZE_LO | m9_l3 | u32_t | upon success: file size of created file (lower 32 bits) |
RES_UID | m9_s4 | uid_t | upon success: user ID of created file |
RES_GID | m9_s1 | gid_t | upon success: group ID of created file |
Reply codes
<16% >ENAMETOOLONG | the last path component is longer than the file system supports |
EEXIST | an entry with that name already exists in the given directory |
ENFILE | no inodes are available |
ENOSPC | no space is left on the device |
EFBIG | the containing directory can not handle any more entries |
ENOENT | the containing directory has been removed |
OK | regular file created and opened |
Description
Notes
Create an open, unlinked file.
Request fields
<16% >REQ_MODE | <6% >m9_s3 | <12% >mode_t | mode for the inode |
REQ_DEV | m9_l5 | dev_t | device number for the inode |
REQ_UID | m9_s4 | uid_t | user ID for the inode |
REQ_GID | m9_s1 | gid_t | group ID for the inode |
Reply fields
<16% >RES_INODE_NR | <6% >m9_l1 | <12% >ino_t | upon success: inode number of the resulting inode |
RES_MODE | m9_s2 | mode_t | upon success: mode of the resulting inode |
RES_FILE_SIZE_HI | m9_l2 | u32_t | upon success: size of the resulting inode (upper 32 bits) |
RES_FILE_SIZE_LO | m9_l3 | u32_t | upon success: size of the resulting inode (lower 32 bits) |
RES_DEV | m9_l4 | dev_t | upon success: device number of the resulting inode |
RES_UID | m9_s4 | uid_t | upon success: user ID of the resulting inode |
RES_GID | m9_s1 | gid_t | upon success: group ID of the resulting inode |
Reply codes
<16% >ENFILE | no inodes are available |
OK | temporary inode created and opened |
Description
Notes
Decrease an open file's reference count.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_COUNT | m9_l2 | int | number of references to drop |
Reply fields
Reply codes
<16% >OK | reference count decreased |
Description
Notes
Read from a file.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (WRITE) to store the resulting data in |
REQ_SEEK_POS_HI | m9_l3 | u32_t | seek position into the open file (upper 32 bits) |
REQ_SEEK_POS_LO | m9_l4 | u32_t | seek position into the open file (lower 32 bits) |
REQ_NBYTES | m9_l5 | size_t | number of bytes to read |
Reply fields
<16% >RES_SEEK_POS_HI | <6% >m9_l3 | <12% >u32_t | upon success: resulting file position (upper 32 bits) |
RES_SEEK_POS_LO | m9_l4 | u32_t | upon success: resulting file position (lower 32 bits) |
RES_NBYTES | m9_l5 | size_t | upon success: number of bytes read |
Reply codes
<16% >OK | results successfully (partially) read, or EOF reached |
Description
Notes
Write to a file.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) containing the data to write |
REQ_SEEK_POS_HI | m9_l3 | u32_t | seek position into the open file (upper 32 bits) |
REQ_SEEK_POS_LO | m9_l4 | u32_t | seek position into the open file (lower 32 bits) |
REQ_NBYTES | m9_l5 | size_t | number of bytes to write |
Reply fields
<16% >RES_SEEK_POS_HI | <6% >m9_l3 | <12% >u32_t | upon success: resulting file position (upper 32 bits) |
RES_SEEK_POS_LO | m9_l4 | u32_t | upon success: resulting file position (lower 32 bits) |
RES_NBYTES | m9_l5 | size_t | upon success: number of bytes written |
Reply codes
<16% >ENOSPC | no space is left on the device |
EFBIG | the write would make the resulting file size too big |
OK | results successfully written |
Description
Notes
Request filesystem to retrieve the requested inode data.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_SEEK_POS_HI | m9_l3 | u32_t | seek position into the open file (upper 32 bits) |
REQ_SEEK_POS_LO | m9_l4 | u32_t | seek position into the open file (lower 32 bits) |
REQ_NBYTES | m9_l5 | size_t | number of bytes to read |
Reply fields
Reply codes
<16% >OK | peek done, see REQ_NBYTES reply to see how many were available, filesystem cache metadata |
ENOSYS | filesystem does not implement REQ_PEEK and mmap() call of files opened on this FS should fail |
Description
Retrieve directory entries.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of the directory |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (WRITE) to store resulting struct dirent entries and names in |
REQ_MEM_SIZE | m9_l5 | size_t | size of given memory grant |
REQ_SEEK_POS_HI | m9_l3 | u32_t | seek position into the open file (upper 32 bits) |
REQ_SEEK_POS_LO | m9_l4 | u32_t | seek position into the open file (lower 32 bits) |
Reply fields
<16% >RES_SEEK_POS_HI | <6% >m9_l3 | <12% >u32_t | upon success: new seek position into the file (upper 32 bits) |
RES_SEEK_POS_LO | m9_l4 | u32_t | upon success: new seek position into the file (lower 32 bits) |
RES_NBYTES | m9_l5 | size_t | upon success: the amount of resulting bytes stored, with 0 for EOF |
Reply codes
<16% >ENOENT | the given file position is not aligned to the internal data structures (file system specific) |
EINVAL | the given buffer is too small to store even one entry (including padding) |
OK | stored zero or more entries in the user's buffer |
Description
Notes
struct dirent
, with member d_name
containing the null-terminated name of the directory entry and extra padding to make the following struct dirent
32-bit aligned.d_off
indicates the (file-system specific) position of that entry, and d_reclen
represents the total size of the returned struct dirent
including name and padding.Set size, or free space, of an open file.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_TRC_START_HI | m9_l2 | u32_t | new file size or starting position (inclusive) of region to free (upper 32 bits) |
REQ_TRC_START_LO | m9_l3 | u32_t | new file size or starting position (inclusive) of region to free (lower 32 bits) |
REQ_TRC_END_HI | m9_l4 | u32_t | zero or ending position (exclusive) of region to free (upper 32 bits) |
REQ_TRC_END_LO | m9_l5 | u32_t | zero or ending position (exclusive) of region to free (lower 32 bits) |
Reply fields
Reply codes
<16% >EFBIG | the resulting file would be too big |
OK | file size changed and/or holes created |
Description
Notes
Mark file as target of seek operation.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
Reply fields
Reply codes
<16% >OK | request processed successfully |
Description
Notes
Retrieve file status.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (WRITE) to store resulting “struct stat” in |
Reply fields
Reply codes
<16% >OK | result stored in buffer |
Description
Notes
Change file ownership.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_UID | m9_s4 | uid_t | new user ID for the file |
REQ_GID | m9_s1 | gid_t | new group ID for the file |
Reply fields
<16% >RES_MODE | <6% >m9_s2 | <12% >mode_t | upon success: resulting inode mode |
Reply codes
<16% >OK | ownership changed |
Description
Notes
Change file mode.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_MODE | m9_s3 | mode_t | new mode for the file |
Reply fields
<16% >RES_MODE | <6% >m9_s2 | <12% >mode_t | upon success: resulting inode mode |
Reply codes
<16% >OK | mode changed |
Description
Notes
<minix/const.h>
.Set file times.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_ACTIME | m9_l2 | time_t | new access time, in seconds since Epoch |
REQ_MODTIME | m9_l3 | time_t | new modification time, in seconds since Epoch |
REQ_ACNSEC | m9_l4 | long | new access nanoseconds, or special value UTIME_OMIT or UTIME_NOW |
REQ_MODNSEC | m9_l5 | long | new modification nanoseconds, or special value UTIME_OMIT or UTIME_NOW |
Reply fields
Reply codes
<16% >OK | custom file times set |
Description
struct timespec
. For each of the two time stamps, the special value UTIME_OMIT (defined in <sys/stat.h>
) asks to avoid modification of the data stored in the file system; and the special value UTIME_NOW (also defined in <sys/stat.h>
) asks to set the time stamp to the current time.Notes
Create a directory.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of the containing directory for the new file |
REQ_MODE | m9_s3 | mode_t | mode for the directory |
REQ_UID | m9_s4 | uid_t | user ID for the directory |
REQ_GID | m9_s1 | gid_t | group ID for the directory |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for the last path component |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the last path component |
Reply fields
Reply codes
<16% >ENAMETOOLONG | the last path component is longer than the file system supports |
EEXIST | a directory entry with that name already exists |
ENFILE | no inodes are available |
ENOSPC | no space is left on the device |
EFBIG | the containing directory can not handle any more entries |
EMLINK | the containing directory has the maximum number of links already |
ENOENT | the containing directory has been removed |
OK | directory created |
Description
Notes
Create a special file.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of the containing directory for the new file |
REQ_MODE | m9_s3 | mode_t | mode for the file |
REQ_DEV | m9_l5 | dev_t | device number |
REQ_UID | m9_s4 | uid_t | user ID for the file |
REQ_GID | m9_s1 | gid_t | group ID for the file |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for the last path component |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the last path component |
Reply fields
Reply codes
<16% >ENAMETOOLONG | the last path component is longer than the file system supports |
EEXIST | a directory entry with that name already exists |
EINVAL | the given file type is invalid or not supported |
ENFILE | no inodes are available |
ENOSPC | no space is left on the device |
EFBIG | the containing directory can not handle any more entries |
ENOENT | the containing directory has been removed |
OK | special file created |
Description
Notes
Create a hard link to a file.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | link file inode number |
REQ_DIR_INO | m9_l3 | ino_t | inode number of the containing directory for the new link |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for the last path component |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the last path component |
Reply fields
Reply codes
<16% >ENAMETOOLONG | the last path component is longer than the file system supports |
EEXIST | a directory entry with that name already exists |
EPERM | the linked file is a directory |
EMLINK | the linked inode has the maximum number of links already |
ENOSPC | no space is left on the device |
EFBIG | the containing directory can not handle any more entries |
ENOENT | the containing directory has been removed |
OK | new link created |
Description
Notes
Unlink a file.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of the containing directory for the file |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for last path component |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the last path component |
Reply fields
Reply codes
<16% >ENAMETOOLONG | the last path component is longer than the file system supports |
ENOENT | no directory entry with that name exists |
EPERM | the given name refers to a directory |
OK | unlinked file |
Description
Notes
Remove an empty directory.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of the containing directory for the file |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for last path component |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the last path component |
Reply fields
Reply codes
<16% >ENAMETOOLONG | the last path component is longer than the file system supports |
ENOENT | no directory entry with that name exists |
ENOTDIR | the given name does not refer to a directory. |
ENOTEMPTY | the given directory is not empty |
EINVAL | the given directory is “.” or “..” |
EBUSY | the given directory is the root directory of the file system |
OK | removed directory |
Description
Notes
Rename a file or directory.
Request fields
<16% >REQ_REN_OLD_DIR | <6% >m9_l3 | <12% >ino_t | inode number of containing directory for the old file |
REQ_REN_NEW_DIR | m9_l4 | ino_t | inode number of containing directory for the new file |
REQ_REN_GRANT_OLD | m9_l2 | cp_grant_id_t | memory grant (READ) for the old last path component |
REQ_REN_LEN_OLD | m9_s1 | unsigned short | length of the old last path component |
REQ_REN_GRANT_NEW | m9_l1 | cp_grant_id_t | memory grant (READ) for the new last path component |
REQ_REN_LEN_NEW | m9_s2 | unsigned short | length of the new last path component |
Reply fields
Reply codes
<16% >ENAMETOOLONG | the last path component of the old or new file is longer than the file system supports |
ENOENT | the old file does not exist |
OK | the old and new last path component and containing directory are the same |
EBUSY | the old file is a mountpoint directory |
EINVAL | an attempt is made to move a directory to within its own subtree |
EINVAL | the old or new last path component is “.” or “..” |
EMLINK | the old file is a directory and the new file doesn't exist but the new containing directory has the maximum number of links |
ENOTDIR | the old file is a directory and the new file exists but is not a directory |
EISDIR | the old file is not a directory and the new file exists but is a directory |
ENOTEMPTY | the new file is a directory but is not empty |
EBUSY | the new file is the root directory of the file system |
ENOSPC | no space is left on the device |
EFBIG | the new containing directory can not handle any more entries |
ENOENT | the new containing directory has been removed |
OK | file renamed |
Description
Notes
Create a symbolic link.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of the containing directory for the new file |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for the link name's last path component |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the link name's last path component |
REQ_GRANT3 | m9_l3 | cp_grant_id_t | memory grant (READ) for the link target (not including a trailing '\0') |
REQ_MEM_SIZE | m9_l5 | size_t | length of the link target (not including a trailing '\0') |
REQ_UID | m9_s4 | uid_t | user ID for the new symlink |
REQ_GID | m9_s1 | gid_t | group ID for the new symlink |
Reply fields
Reply codes
<16% >ENAMETOOLONG | the last path component is longer than the file system supports |
EEXIST | a directory entry with that name already exists |
ENFILE | no inodes are available |
ENOSPC | no space is left on the device |
EFBIG | the containing directory can not handle any more entries |
ENOENT | the containing directory has been removed |
ENAMETOOLONG | the link target contains '\0' bytes |
OK | symbolic link created |
Description
Notes
Retrieve symbolic link target.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (WRITE) for buffer to write result to |
REQ_MEM_SIZE | m9_l5 | size_t | size of buffer to write to |
Reply fields
<16% >RES_NBYTES | <6% >m9_l5 | <12% >size_t | upon success: number of bytes written |
Reply codes
<16% >OK | result stored in buffer |
Description
Notes
Mark an inode as mountpoint.
Request fields
<16% >REQ_INODE_NR | <6% >m9_l1 | <12% >ino_t | inode number of file to use as mountpoint |
Reply fields
Reply codes
<16% >EBUSY | inode already in use as mountpoint |
ENOTDIR | given inode is not a directory |
OK | inode marked as mountpoint |
Description
Notes
Retrieve file system status.
Request fields
<16% >REQ_GRANT | <6% >m9_l2 | <12% >cp_grant_id_t | memory grant (WRITE) to store resulting “struct statfs” in |
Reply fields
Reply codes
<16% >OK | result stored in buffer |
Description
Notes
Retrieve file system statistics (The POSIX equivalent of REQ_FSTATFS)
Request fields
<16% >REQ_GRANT | <6% >m9_l2 | <12% >cp_grant_id_t | memory grant (WRITE) to store resulting “struct statvfs” in |
Reply fields
Reply codes
<16% >OK | result stored in buffer |
Description
Notes
Write any unwritten data to disk.
Request fields
Reply fields
Reply codes
<16% >OK | request processed successfully |
Description
Notes
Flush and invalidate cached data for an unmounted device.
Request fields
<16% >REQ_DEV | <6% >m9_l5 | <12% >dev_t | device number |
Reply fields
Reply codes
<16% >EBUSY | the device is mounted |
OK | cache flushed and invalidated for this device |
Description
Notes
vm_clear_cache()
(or, for libminixfs users, lmfs_invalidate()
).Set a new driver label for a major device.
Request fields
<16% >REQ_DEV | <6% >m9_l5 | <12% >dev_t | device number |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) for the label of the block device driver to use |
REQ_PATH_LEN | m9_s2 | unsigned short | length of the label |
Reply fields
Reply codes
<16% >OK | request processed successfully |
Description
Notes
Read from a block device directly.
Request fields
<16% >REQ_DEV2 | <6% >m9_l1 | <12% >dev_t | device number |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (WRITE) to store the resulting data in |
REQ_SEEK_POS_HI | m9_l3 | u32_t | read position (upper 32 bits) |
REQ_SEEK_POS_LO | m9_l4 | u32_t | read position (lower 32 bits) |
REQ_NBYTES | m9_l5 | size_t | number of bytes to read |
Reply fields
<16% >RES_SEEK_POS_HI | <6% >m9_l3 | <12% >u32_t | upon success: resulting position (upper 32 bits) |
RES_SEEK_POS_LO | m9_l4 | u32_t | upon success: resulting position (lower 32 bits) |
RES_NBYTES | m9_l5 | size_t | upon success: total number of bytes read |
Reply codes
<16% >EIO | I/O error reported by the device driver |
OK | results successfully (partially) read, or EOF reached |
Description
Notes
Write to a block device directly.
Request fields
<16% >REQ_DEV2 | <6% >m9_l1 | <12% >dev_t | device number |
REQ_GRANT | m9_l2 | cp_grant_id_t | memory grant (READ) containing the data to write |
REQ_SEEK_POS_HI | m9_l3 | u32_t | write position (upper 32 bits) |
REQ_SEEK_POS_LO | m9_l4 | u32_t | write position (lower 32 bits) |
REQ_NBYTES | m9_l5 | size_t | number of bytes to write |
Reply fields
<16% >RES_SEEK_POS_HI | <6% >m9_l3 | <12% >u32_t | upon success: resulting position (upper 32 bits) |
RES_SEEK_POS_LO | m9_l4 | u32_t | upon success: resulting position (lower 32 bits) |
RES_NBYTES | m9_l5 | size_t | upon success: total number of bytes written |
Reply codes
<16% >EIO | I/O error reported by the device driver |
OK | results successfully (partially) written, or EOF reached |
Description
Notes
Request filesystem to retrieve the requested block data.
Request fields
<16% >REQ_DEV2 | <6% >m9_l1 | <12% >dev_t | device number |
REQ_SEEK_POS_HI | m9_l3 | u32_t | seek position into the block device (upper 32 bits) |
REQ_SEEK_POS_LO | m9_l4 | u32_t | seek position into the block device (lower 32 bits) |
REQ_NBYTES | m9_l5 | size_t | number of bytes to read |
Reply fields
Reply codes
<16% >OK | peek done. all requested blocks have been in the cache. |
ENOSYS | filesystem does not implement REQ_BPEEK and mmap() call of files opened on this FS should fail |
Description
Notes
The following pseudocode presents one possible approach to implementing the heart of the REQ_LOOKUP request:
For file servers that do not support symbolic links and/or mountpoints, the lookup can be simplified accordingly.
If at least one symlink was resolved, and the returned error is EENTERMOUNT, ELEAVEMOUNT or ESYMLINK, then the unresolved part of the new path must be copied back to VFS.
Regardless,
This document is not based on the original VFS-FS protocol documentation by Balazs Gerofi. However, that document may still provide additional insights.
Design and implementation of the MINIX Virtual File system by Balazs Gerofi, August, 2006