|
PatchworkOS
|
Filesystems and Virtual File System. More...
Modules | |
| Ctl | |
| Helpers to implement ctl (control) file operations. | |
| Dentry | |
| Directory entry. | |
| File | |
| Underlying type of a file descriptor. | |
| Inode | |
| Index node. | |
| Keys | |
| Keys for sharing file descriptors between processes. | |
| Mount | |
| Mount point. | |
| Namespaces | |
| Per-process Namespaces. | |
| Path | |
| Unique location in the filesystem. | |
| RAMFS | |
| RAM filesystem. | |
| Superblock | |
| Mountable filesystem. | |
| SysFS | |
| Filesystem for exposing kernel resources. | |
| VFS Context | |
| Virtual File System context. | |
Data Structures | |
| struct | filesystem_t |
| Filesystem structure, represents a filesystem type, e.g. fat32, ramfs, sysfs, etc. More... | |
| struct | vfs_list_t |
| Helper structure for lists with a lock. More... | |
| struct | vfs_map_t |
| Helper structure for maps with a lock. More... | |
Macros | |
| #define | VFS_ROOT_ENTRY_NAME "__root__" |
| The name of the root entry. | |
| #define | VFS_DEVICE_NAME_NONE "__no_device__" |
| The name used to indicate no device. | |
| #define | BUFFER_READ(buffer, count, offset, src, size) |
| Helper macros for implementing file operations dealing with simple buffers. | |
Functions | |
| void | vfs_init (void) |
| Initializes the VFS. | |
| uint64_t | vfs_get_new_id (void) |
| Generates a new unique ID. | |
| uint64_t | vfs_register_fs (filesystem_t *fs) |
| Registers a filesystem. | |
| uint64_t | vfs_unregister_fs (filesystem_t *fs) |
| Unregisters a filesystem. | |
| filesystem_t * | vfs_get_fs (const char *name) |
| Gets a filesystem by name. | |
| inode_t * | vfs_get_inode (superblock_t *superblock, inode_number_t number) |
| Get an inode for the given superblock and inode number. | |
| dentry_t * | vfs_get_dentry (const dentry_t *parent, const char *name) |
| Get a dentry for the given name. Will NOT traverse mountpoints. | |
| dentry_t * | vfs_get_or_lookup_dentry (const path_t *parent, const char *name) |
| Get or lookup a dentry for the given name. Will NOT traverse mountpoints. | |
| uint64_t | vfs_add_inode (inode_t *inode) |
| Add a inode to the inode cache. | |
| uint64_t | vfs_add_dentry (dentry_t *dentry) |
| Add a dentry to the dentry cache. | |
| void | vfs_remove_superblock (superblock_t *superblock) |
| Remove a superblock from the superblock list. | |
| void | vfs_remove_inode (inode_t *inode) |
| Remove an inode from the inode cache. | |
| void | vfs_remove_dentry (dentry_t *dentry) |
| Remove a dentry from the dentry cache. | |
| uint64_t | vfs_walk (path_t *outPath, const pathname_t *pathname, walk_flags_t flags, process_t *process) |
| Walk a pathname to a path, starting from the current process's working directory. | |
| uint64_t | vfs_walk_parent (path_t *outPath, const pathname_t *pathname, char *outLastName, walk_flags_t flags, process_t *process) |
| Walk a pathname to its parent path, starting from the current process's working directory. | |
| uint64_t | vfs_walk_parent_and_child (path_t *outParent, path_t *outChild, const pathname_t *pathname, walk_flags_t flags, process_t *process) |
| Walk a pathname to path and its parent path, starting from the current process's working directory. | |
| bool | vfs_is_name_valid (const char *name) |
| Check if a name is valid. | |
| file_t * | vfs_open (const pathname_t *pathname, process_t *process) |
| Open a file. | |
| uint64_t | vfs_open2 (const pathname_t *pathname, file_t *files[2], process_t *process) |
| Open one file, returning two file handles. | |
| uint64_t | vfs_read (file_t *file, void *buffer, uint64_t count) |
| Read from a file. | |
| uint64_t | vfs_write (file_t *file, const void *buffer, uint64_t count) |
| Write to a file. | |
| uint64_t | vfs_seek (file_t *file, int64_t offset, seek_origin_t origin) |
| Seek in a file. | |
| uint64_t | vfs_ioctl (file_t *file, uint64_t request, void *argp, uint64_t size) |
| Perform an ioctl operation on a file. | |
| void * | vfs_mmap (file_t *file, void *address, uint64_t length, pml_flags_t flags) |
| Memory map a file. | |
| uint64_t | vfs_poll (poll_file_t *files, uint64_t amount, clock_t timeout) |
| Poll multiple files. | |
| uint64_t | vfs_getdents (file_t *file, dirent_t *buffer, uint64_t count) |
| Get directory entries from a directory file. | |
| uint64_t | vfs_stat (const pathname_t *pathname, stat_t *buffer, process_t *process) |
| Get file information. | |
| uint64_t | vfs_link (const pathname_t *oldPathname, const pathname_t *newPathname, process_t *process) |
| Make the same file appear twice in the filesystem. | |
| uint64_t | vfs_remove (const pathname_t *pathname, process_t *process) |
| Remove a file or directory. | |
Filesystems and Virtual File System.
Virtual File System.
TODO: Implement improved caching, LRU.
Helper macros for implementing file operations dealing with simple buffers.
| buffer | The destination buffer. |
| count | The number of bytes to read/write. |
| offset | A pointer to the current offset, will be updated. |
| src | The source buffer. |
| size | The size of the source buffer. |
| #define VFS_DEVICE_NAME_NONE "__no_device__" |
| #define VFS_ROOT_ENTRY_NAME "__root__" |
Add a dentry to the dentry cache.
Should not be used manually, instead use dentry_make_positive().
| dentry | The dentry to add. |
0. On failure, ERR and errno is set. Definition at line 288 of file vfs.c.
References dentry_cache_key(), ERR, dentry_t::id, vfs_map_t::lock, vfs_map_t::map, map_insert(), dentry_t::mapEntry, dentry_t::name, dentry_t::parent, and RWLOCK_WRITE_SCOPE.
Referenced by dentry_new().
Add a inode to the inode cache.
Should not be used manually, as it will be called in inode_new().
| inode | The inode to add. |
0. On failure, ERR and errno is set. Definition at line 275 of file vfs.c.
References ERR, superblock_t::id, vfs_map_t::lock, vfs_map_t::map, map_insert(), inode_t::mapEntry, inode_t::number, RWLOCK_WRITE_SCOPE, and inode_t::superblock.
Referenced by inode_new().
Get a dentry for the given name. Will NOT traverse mountpoints.
Note that there is a period of time where a dentrys reference count has dropped to zero but its free function has not had the time to remove it from the cache yet. In this case, this function will return NULL and set errno to ESTALE.
| parent | The parent path. |
| name | The name of the dentry. |
NULL and errno is set. Definition at line 215 of file vfs.c.
References dentry_cache_key(), EINVAL, errno, dentry_t::id, NULL, and vfs_get_dentry_internal().
| filesystem_t * vfs_get_fs | ( | const char * | name | ) |
Gets a filesystem by name.
| name | The name of the filesystem. |
NULL, does not set errno. Definition at line 152 of file vfs.c.
References vfs_list_t::list, LIST_FOR_EACH, vfs_list_t::lock, filesystem_t::name, NULL, RWLOCK_READ_SCOPE, and strcmp().
Referenced by namespace_mount().
| inode_t * vfs_get_inode | ( | superblock_t * | superblock, |
| inode_number_t | number | ||
| ) |
Get an inode for the given superblock and inode number.
Note that there is a period of time where a inodes reference count has dropped to zero but its free function has not had the time to remove it from the cache yet. In this case, this function will return NULL and set errno to ESTALE.
| superblock | The superblock. |
| number | The inode number. |
NULL and errno is set. Definition at line 168 of file vfs.c.
References atomic_load, CONTAINER_OF_SAFE, ref_t::count, ENOENT, errno, ESTALE, superblock_t::id, vfs_map_t::lock, vfs_map_t::map, map_get(), NULL, inode_t::ref, REF, and RWLOCK_READ_SCOPE.
| uint64_t vfs_get_new_id | ( | void | ) |
Generates a new unique ID.
Definition at line 97 of file vfs.c.
References atomic_fetch_add.
Referenced by dentry_new(), mount_new(), and superblock_new().
Get or lookup a dentry for the given name. Will NOT traverse mountpoints.
| parent | The parent path. |
| name | The name of the dentry. |
NULL and errno is set. Definition at line 227 of file vfs.c.
References assert, path_t::dentry, dentry_cache_key(), dentry_new(), DEREF_DEFER, EEXIST, EINVAL, ENOENT, ERR, errno, dentry_t::id, dentry_t::inode, inode_ops_t::lookup, path_t::mount, inode_t::mutex, MUTEX_SCOPE, NULL, inode_t::ops, REF, RFLAGS_INTERRUPT_ENABLE, rflags_read(), dentry_t::superblock, vfs_get_dentry_internal(), and vfs_remove_dentry().
Referenced by path_walk_single_step(), and sysfs_mount_new().
Get directory entries from a directory file.
| file | The directory file to read from. |
| buffer | The buffer to read into. |
| count | The number of bytes to read. |
ERR and errno is set. Definition at line 1166 of file vfs.c.
References assert, buffer, count, EINVAL, ENOSYS, ENOTDIR, ERR, errno, file, dentry_ops_t::getdents, dentry_t::inode, INODE_DIR, inode_notify_access(), NULL, dentry_t::ops, dentry_t::parent, RFLAGS_INTERRUPT_ENABLE, rflags_read(), and inode_t::type.
Referenced by SYSCALL_DEFINE().
| void vfs_init | ( | void | ) |
Initializes the VFS.
Definition at line 83 of file vfs.c.
References key_init(), LOG_INFO, path_flags_init(), vfs_list_init(), and vfs_map_init().
Referenced by init_finalize().
Perform an ioctl operation on a file.
| file | The file to perform the ioctl on. |
| request | The ioctl request. |
| argp | The argument pointer. |
| size | The size of the argument. |
ERR and errno is set. Definition at line 839 of file vfs.c.
References assert, EINVAL, EISDIR, ENOTTY, ERR, errno, file, dentry_t::inode, INODE_DIR, inode_notify_access(), NULL, dentry_t::ops, RFLAGS_INTERRUPT_ENABLE, rflags_read(), and inode_t::type.
Referenced by SYSCALL_DEFINE().
| bool vfs_is_name_valid | ( | const char * | name | ) |
Check if a name is valid.
A valid name is not "." or "..", only contains chars considered valid by PATH_VALID_CHAR, and is not longer than MAX_NAME - 1.
| name | The name to check. |
true if the name is valid, false otherwise. Definition at line 401 of file vfs.c.
References MAX_NAME, PATH_VALID_CHAR, and strcmp().
Referenced by path_walk_single_step().
| uint64_t vfs_link | ( | const pathname_t * | oldPathname, |
| const pathname_t * | newPathname, | ||
| process_t * | process | ||
| ) |
Make the same file appear twice in the filesystem.
| oldPathname | The existing file. |
| newPathname | The new link to create, must not exist and be in the same filesystem as the oldPathname. |
| process | The process performing the linking. |
0. On failure, ERR and errno is set. Definition at line 1281 of file vfs.c.
References assert, atomic_load, path_t::dentry, DENTRY_NEGATIVE, EBADFLAG, EEXIST, EINVAL, ENOSYS, ERR, errno, EXDEV, pathname_t::flags, superblock_t::id, dentry_t::inode, inode_notify_change(), inode_notify_modify(), inode_ops_t::link, inode_t::mutex, mutex_acquire(), mutex_release(), NULL, inode_t::ops, PATH_DEFER, PATH_EMPTY, PATH_NONE, PATHNAME_IS_VALID, RFLAGS_INTERRUPT_ENABLE, rflags_read(), dentry_t::superblock, vfs_walk_parent_and_child(), WALK_NEGATIVE_IS_OK, and WALK_NONE.
Referenced by SYSCALL_DEFINE().
| void * vfs_mmap | ( | file_t * | file, |
| void * | address, | ||
| uint64_t | length, | ||
| pml_flags_t | flags | ||
| ) |
Memory map a file.
| file | The file to memory map. |
| address | The address to map to, or NULL to let the kernel choose. |
| length | The length to map. |
| flags | The page table flags for the mapping. |
NULL and errno is set. Definition at line 889 of file vfs.c.
References address, assert, EISDIR, errno, file, dentry_t::inode, INODE_DIR, inode_notify_access(), NULL, dentry_t::ops, RFLAGS_INTERRUPT_ENABLE, rflags_read(), and inode_t::type.
Referenced by SYSCALL_DEFINE().
| file_t * vfs_open | ( | const pathname_t * | pathname, |
| process_t * | process | ||
| ) |
Open a file.
| pathname | The pathname of the file to open. |
| process | The process opening the file. |
NULL and errno is set. Definition at line 531 of file vfs.c.
References assert, path_t::dentry, DEREF_DEFER, EINVAL, ERR, errno, file, file_new(), pathname_t::flags, dentry_t::inode, INODE_FILE, inode_notify_access(), inode_truncate(), NULL, dentry_t::ops, PATH_DEFER, PATH_EMPTY, PATH_TRUNCATE, PATHNAME_IS_VALID, REF, RFLAGS_INTERRUPT_ENABLE, rflags_read(), inode_t::type, and vfs_open_lookup().
Referenced by init_process_spawn(), loader_load_program(), and SYSCALL_DEFINE().
| uint64_t vfs_open2 | ( | const pathname_t * | pathname, |
| file_t * | files[2], | ||
| process_t * | process | ||
| ) |
Open one file, returning two file handles.
Used to for example implement pipes.
| pathname | The pathname of the file to open. |
| files | The output array of two file pointers. |
| process | The process opening the file. |
0. On failure, ERR and errno is set. Definition at line 593 of file vfs.c.
References assert, path_t::dentry, DEREF_DEFER, EINVAL, ENOSYS, ERR, errno, file_new(), files, pathname_t::flags, dentry_t::inode, INODE_FILE, inode_notify_access(), inode_truncate(), NULL, ops, PATH_DEFER, PATH_EMPTY, PATH_TRUNCATE, PATHNAME_IS_VALID, REF, RFLAGS_INTERRUPT_ENABLE, rflags_read(), inode_t::type, and vfs_open_lookup().
Referenced by SYSCALL_DEFINE().
| uint64_t vfs_poll | ( | poll_file_t * | files, |
| uint64_t | amount, | ||
| clock_t | timeout | ||
| ) |
Poll multiple files.
| files | The array of files to poll. |
| amount | The number of files in the array. |
| timeout | The timeout in clock ticks, or CLOCKS_NEVER to wait indefinitely. |
ERR and errno is set. Definition at line 1021 of file vfs.c.
References CLOCKS_NEVER, CONFIG_MAX_FD, EINVAL, EISDIR, ENOSYS, ERR, errno, ETIMEDOUT, file, files, dentry_t::inode, INODE_DIR, NULL, dentry_t::ops, vfs_poll_ctx_t::queueAmount, vfs_poll_ctx_t::queues, timer_uptime(), inode_t::type, uptime(), vfs_poll_ctx_check_events(), vfs_poll_ctx_init(), wait_block_cancel(), wait_block_commit(), and wait_block_setup().
Referenced by SYSCALL_DEFINE().
Read from a file.
Follows POSIX semantics.
| file | The file to read from. |
| buffer | The buffer to read into. |
| count | The number of bytes to read. |
ERR and errno is set. Definition at line 694 of file vfs.c.
References assert, buffer, count, EINVAL, EISDIR, ENOSYS, ERR, errno, file, dentry_t::inode, INODE_DIR, inode_notify_access(), NULL, dentry_t::ops, RFLAGS_INTERRUPT_ENABLE, rflags_read(), and inode_t::type.
Referenced by loader_load_program(), and SYSCALL_DEFINE().
| uint64_t vfs_register_fs | ( | filesystem_t * | fs | ) |
Registers a filesystem.
| fs | The filesystem to register. |
0. On failure, ERR and errno is set. Definition at line 102 of file vfs.c.
References EEXIST, EINVAL, filesystem_t::entry, ERR, errno, vfs_list_t::list, list_entry_init(), LIST_FOR_EACH, list_push(), vfs_list_t::lock, MAX_NAME, filesystem_t::name, NULL, RWLOCK_WRITE_SCOPE, strcmp(), and strnlen_s().
Referenced by ramfs_init(), and sysfs_init().
| uint64_t vfs_remove | ( | const pathname_t * | pathname, |
| process_t * | process | ||
| ) |
Remove a file or directory.
| pathname | The pathname of the file or directory to remove. |
| process | The process performing the removal. |
0. On failure, ERR and errno is set. Definition at line 1377 of file vfs.c.
References assert, path_t::dentry, EINVAL, EISDIR, ENOTDIR, EPERM, ERR, errno, pathname_t::flags, dentry_t::inode, INODE_DIR, INODE_FILE, inode_notify_change(), inode_t::mutex, mutex_acquire(), mutex_release(), NULL, inode_t::ops, PATH_DEFER, PATH_DIRECTORY, PATH_EMPTY, PATHNAME_IS_VALID, inode_ops_t::remove, RFLAGS_INTERRUPT_ENABLE, rflags_read(), inode_t::type, vfs_remove_dentry(), vfs_walk_parent_and_child(), and WALK_NONE.
Referenced by SYSCALL_DEFINE().
| void vfs_remove_dentry | ( | dentry_t * | dentry | ) |
Remove a dentry from the dentry cache.
| dentry | The dentry to remove. |
Definition at line 324 of file vfs.c.
References dentry_cache_key(), dentry_t::id, vfs_map_t::lock, vfs_map_t::map, map_remove(), dentry_t::name, NULL, dentry_t::parent, and RWLOCK_WRITE_SCOPE.
Referenced by dentry_free(), vfs_get_or_lookup_dentry(), and vfs_remove().
| void vfs_remove_inode | ( | inode_t * | inode | ) |
Remove an inode from the inode cache.
| inode | The inode to remove. |
Definition at line 312 of file vfs.c.
References superblock_t::id, vfs_map_t::lock, vfs_map_t::map, map_remove(), NULL, inode_t::number, RWLOCK_WRITE_SCOPE, and inode_t::superblock.
Referenced by inode_free().
| void vfs_remove_superblock | ( | superblock_t * | superblock | ) |
Remove a superblock from the superblock list.
| superblock | The superblock to remove. |
Definition at line 301 of file vfs.c.
References superblock_t::entry, vfs_list_t::list, list_remove(), vfs_list_t::lock, NULL, and RWLOCK_WRITE_SCOPE.
Referenced by superblock_free().
| uint64_t vfs_seek | ( | file_t * | file, |
| int64_t | offset, | ||
| seek_origin_t | origin | ||
| ) |
Seek in a file.
Follows POSIX semantics.
| file | The file to seek in. |
| offset | The offset to seek to. |
| origin | The origin to seek from. |
ERR and errno is set. Definition at line 807 of file vfs.c.
References assert, EINVAL, ERR, errno, ESPIPE, file, NULL, dentry_t::ops, RFLAGS_INTERRUPT_ENABLE, and rflags_read().
Referenced by loader_load_program(), and SYSCALL_DEFINE().
| uint64_t vfs_stat | ( | const pathname_t * | pathname, |
| stat_t * | buffer, | ||
| process_t * | process | ||
| ) |
Get file information.
| pathname | The pathname of the file to get information about. |
| buffer | The buffer to store the file information in. |
| process | The process performing the stat. |
0. On failure, ERR and errno is set. Definition at line 1222 of file vfs.c.
References inode_t::accessTime, inode_t::blocks, buffer, inode_t::changeTime, inode_t::createTime, path_t::dentry, EBADFLAG, EINVAL, ERR, errno, pathname_t::flags, dentry_t::inode, inode_t::linkCount, MAX_NAME, memset(), inode_t::modifyTime, inode_t::mutex, MUTEX_SCOPE, dentry_t::name, NULL, inode_t::number, PATH_DEFER, PATH_EMPTY, PATH_NONE, PATHNAME_IS_VALID, inode_t::size, strncpy(), inode_t::type, vfs_walk(), and WALK_NONE.
Referenced by loader_spawn(), and SYSCALL_DEFINE().
| uint64_t vfs_unregister_fs | ( | filesystem_t * | fs | ) |
Unregisters a filesystem.
| fs | The filesystem to unregister. |
0. On failure, ERR and errno is set. Definition at line 127 of file vfs.c.
References EBUSY, EINVAL, filesystem_t::entry, ERR, errno, superblock_t::fs, vfs_list_t::list, LIST_FOR_EACH, list_remove(), vfs_list_t::lock, filesystem_t::name, NULL, RWLOCK_READ_SCOPE, RWLOCK_WRITE_SCOPE, and strcmp().
| uint64_t vfs_walk | ( | path_t * | outPath, |
| const pathname_t * | pathname, | ||
| walk_flags_t | flags, | ||
| process_t * | process | ||
| ) |
Walk a pathname to a path, starting from the current process's working directory.
| outPath | The output path. |
| pathname | The pathname to walk. |
| flags | Flags for the path walk. |
| process | The process whose namespace and working directory to use. |
0. On failure, ERR and errno is set. Definition at line 341 of file vfs.c.
References EINVAL, ERR, errno, NULL, PATH_DEFER, PATH_EMPTY, path_walk(), PATHNAME_IS_VALID, vfs_ctx_get_cwd(), and process_t::vfsCtx.
Referenced by SYSCALL_DEFINE(), SYSCALL_DEFINE(), SYSCALL_DEFINE(), vfs_open_lookup(), and vfs_stat().
| uint64_t vfs_walk_parent | ( | path_t * | outPath, |
| const pathname_t * | pathname, | ||
| char * | outLastName, | ||
| walk_flags_t | flags, | ||
| process_t * | process | ||
| ) |
Walk a pathname to its parent path, starting from the current process's working directory.
| outPath | The output parent path. |
| pathname | The pathname to walk. |
| outLastName | The output last component name. |
| flags | Flags for the path walk. |
| process | The process whose namespace and working directory to use. |
0. On failure, ERR and errno is set. Definition at line 359 of file vfs.c.
References EINVAL, ERR, errno, NULL, PATH_DEFER, PATH_EMPTY, path_walk_parent(), PATHNAME_IS_VALID, vfs_ctx_get_cwd(), and process_t::vfsCtx.
Referenced by vfs_walk_parent_and_child().
| uint64_t vfs_walk_parent_and_child | ( | path_t * | outParent, |
| path_t * | outChild, | ||
| const pathname_t * | pathname, | ||
| walk_flags_t | flags, | ||
| process_t * | process | ||
| ) |
Walk a pathname to path and its parent path, starting from the current process's working directory.
| outParent | The output parent path. |
| outChild | The output path. |
| pathname | The pathname to walk. |
| flags | Flags for the path walk. |
| process | The process whose namespace and working directory to use. |
0. On failure, ERR and errno is set. Definition at line 378 of file vfs.c.
References ERR, MAX_NAME, path_copy(), PATH_DEFER, PATH_EMPTY, path_walk_single_step(), vfs_walk_parent(), and WALK_NONE.
Referenced by vfs_create(), vfs_link(), and vfs_remove().
Write to a file.
Follows POSIX semantics.
| file | The file to write to. |
| buffer | The buffer to write from. |
| count | The number of bytes to write. |
ERR and errno is set. Definition at line 748 of file vfs.c.
References assert, buffer, count, EINVAL, EISDIR, ENOSYS, ERR, errno, file, dentry_t::inode, INODE_DIR, inode_notify_modify(), NULL, dentry_t::ops, PATH_APPEND, RFLAGS_INTERRUPT_ENABLE, rflags_read(), SEEK_END, and inode_t::type.
Referenced by SYSCALL_DEFINE().