PatchworkOS  c9fea19
A non-POSIX operating system.
Loading...
Searching...
No Matches
dentry.h
Go to the documentation of this file.
1#pragma once
2
3#include <kernel/fs/path.h>
4#include <kernel/sync/mutex.h>
6#include <kernel/utils/map.h>
7#include <kernel/utils/ref.h>
8
9#include <stdatomic.h>
10#include <stdint.h>
11#include <sys/io.h>
12#include <sys/list.h>
13
14typedef struct dentry dentry_t;
15typedef struct dentry_ops dentry_ops_t;
16typedef struct inode inode_t;
17typedef struct superblock superblock_t;
18
19/**
20 * @brief Directory entry.
21 * @defgroup kernel_fs_dentry Dentry
22 * @ingroup kernel_fs
23 *
24 * A dentry represents the actual name in the filesystem hierarchy. It can be either positive, meaning it has an
25 * associated inode, or negative, meaning it does not have an associated inode.
26 *
27 * ## Mountpoints and Root Dentries
28 *
29 * The difference between a mountpoint dentry and a root dentry can be a bit confusing, so here is a quick
30 * explanation. When a filesystem is mounted the dentry that it gets mounted to becomes a mountpoint, any data that
31 * was there before becomes hidden and when we traverse to that dentry we "jump" to the root dentry of the
32 * mounted filesystem. The root dentry of the mounted filesystem is simply the root directory of that filesystem.
33 *
34 * This means that the mountpoint does not "become" the root of the mounted filesystem, it simply points to it.
35 *
36 * Finally, note that just becouse a dentry is a mountpoint does not mean that it can be traversed by the current
37 * process, a process can only traverse a mountpoint if it is visible in its namespace, if its not visible the
38 * dentry acts exactly like a normal dentry.
39 *
40 * @{
41 */
42
43/**
44 * @brief Dentry flags.
45 * @enum dentry_flags_t
46 */
47typedef enum
48{
49 DENTRY_NEGATIVE = 1 << 0, ///< Dentry is negative (no associated inode).
51
52/**
53 * @brief Dentry ID type.
54 */
56
57/**
58 * @brief Macro to check if a dentry is the root entry in its filesystem.
59 *
60 * A dentry is considered the root if its parent is itself.
61 *
62 * @param dentry The dentry to check.
63 * @return true if the dentry is the root, false otherwise.
64 */
65#define DENTRY_IS_ROOT(dentry) ((dentry)->parent == (dentry))
66
67/**
68 * @brief Dentry operations structure.
69 * @struct dentry_ops_t
70 */
71typedef struct dentry_ops
72{
74 void (*cleanup)(dentry_t* entry); ///< Called when the dentry is being freed.
76
77/**
78 * @brief Directory entry structure.
79 * @struct dentry_t
80 *
81 * A dentry structure is protected by the mutex of its inode.
82 */
83typedef struct dentry
84{
87 char name[MAX_NAME]; ///< Constant after creation.
88 inode_t* inode; ///< Will be `NULL` if the dentry is negative, once positive it will never be `NULL`.
95 void* private;
97 _Atomic(uint64_t) mountCount; ///< Number of mounts targeting this dentry.
98 list_entry_t otherEntry; ///< Made available for use by any other subsystems for convenience.
99} dentry_t;
100
101/**
102 * @brief Create a new dentry.
103 *
104 * Will not add the dentry to its parent's list of children but it will appear in the dentry cache as a negative dentry
105 * until `dentry_make_positive()` is called making it positive. This is needed to solve some race conditions when
106 * creating new files. While the dentry is negative it is not possible to create another dentry of the same name in the
107 * same parent, and any lookup to the dentry will fail until it is made positive.
108 *
109 * There is no `dentry_free()` instead use `UNREF()`.
110 *
111 * @param superblock The superblock the dentry belongs to.
112 * @param parent The parent dentry, can be NULL if this is a root dentry.
113 * @param name The name of the dentry.
114 * @return On success, the new dentry. On failure, returns `NULL` and `errno` is set.
115 */
116dentry_t* dentry_new(superblock_t* superblock, dentry_t* parent, const char* name);
117
118/**
119 * @brief Get a dentry for the given name. Will NOT traverse mountpoints.
120 *
121 * Will only check the dentry cache and return a dentry if it exists there, will not call the filesystem's lookup
122 * function.
123 *
124 * @param parent The parent path.
125 * @param name The name of the dentry.
126 * @return On success, the dentry, might be negative. On failure, returns `NULL` and `errno` is set.
127 */
128dentry_t* dentry_get(const dentry_t* parent, const char* name);
129
130/**
131 * @brief Lookup a dentry for the given name. Will NOT traverse mountpoints.
132 *
133 * If the dentry is not found in the dentry cache, the filesystem's lookup function will be called to try to find it.
134 *
135 * @param parent The parent path.
136 * @param name The name of the dentry.
137 * @return On success, the dentry, might be negative. On failure, returns `NULL` and `errno` is set.
138 */
139dentry_t* dentry_lookup(const path_t* parent, const char* name);
140
141/**
142 * @brief Make a dentry positive by associating it with an inode.
143 *
144 * This function is expected to be protected by the parent inode's mutex.
145 *
146 * @param dentry The dentry to make positive, or `NULL` for no-op.
147 * @param inode The inode to associate with the dentry, or `NULL` for no-op.
148 */
149void dentry_make_positive(dentry_t* dentry, inode_t* inode);
150
151/**
152 * @brief Check if a dentry is positive.
153 *
154 * @param dentry The dentry to check.
155 * @return true if the dentry is positive, false if it is negative.
156 */
157bool dentry_is_positive(dentry_t* dentry);
158
159/**
160 * @brief Check if the inode associated with a dentry is a file.
161 *
162 * @param dentry The dentry to check.
163 * @return true if the dentry is a file, false otherwise or if the dentry is negative.
164 */
165bool dentry_is_file(dentry_t* dentry);
166
167/**
168 * @brief Check if the inode associated with a dentry is a directory.
169 *
170 * @param dentry The dentry to check.
171 * @return true if the dentry is a directory, false otherwise or if the dentry is negative.
172 */
173bool dentry_is_dir(dentry_t* dentry);
174
175/**
176 * @brief Helper function for a basic getdents.
177 *
178 * This function can be used by filesystems that do not have any special requirements for getdents.
179 *
180 * In practice this is only useful for in-memory filesystems.
181 *
182 * Used by setting the dentry ops getdents to this function.
183 */
185
186/** @} */
#define MAX_NAME
Maximum length of names.
Definition MAX_NAME.h:11
void dentry_make_positive(dentry_t *dentry, inode_t *inode)
Make a dentry positive by associating it with an inode.
Definition dentry.c:226
dentry_t * dentry_new(superblock_t *superblock, dentry_t *parent, const char *name)
Create a new dentry.
Definition dentry.c:114
uint64_t dentry_id_t
Dentry ID type.
Definition dentry.h:55
dentry_t * dentry_lookup(const path_t *parent, const char *name)
Lookup a dentry for the given name. Will NOT traverse mountpoints.
Definition dentry.c:176
bool dentry_is_positive(dentry_t *dentry)
Check if a dentry is positive.
Definition dentry.c:243
uint64_t dentry_generic_getdents(dentry_t *dentry, dirent_t *buffer, uint64_t count, uint64_t *offset, mode_t mode)
Helper function for a basic getdents.
Definition dentry.c:345
bool dentry_is_dir(dentry_t *dentry)
Check if the inode associated with a dentry is a directory.
Definition dentry.c:268
dentry_t * dentry_get(const dentry_t *parent, const char *name)
Get a dentry for the given name. Will NOT traverse mountpoints.
Definition dentry.c:164
dentry_flags_t
Dentry flags.
Definition dentry.h:48
bool dentry_is_file(dentry_t *dentry)
Check if the inode associated with a dentry is a file.
Definition dentry.c:253
@ DENTRY_NEGATIVE
Dentry is negative (no associated inode).
Definition dentry.h:49
mode_t
Path flags and permissions.
Definition path.h:74
uint64_t getdents(fd_t fd, dirent_t *buffer, uint64_t count)
System call for reading directory entires.
Definition getdents.c:9
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static const path_flag_t flags[]
Definition path.c:42
static atomic_long count
Definition main.c:10
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
Dentry operations structure.
Definition dentry.h:72
Directory entry structure.
Definition dentry.h:84
list_t children
Definition dentry.h:92
inode_t * inode
Will be NULL if the dentry is negative, once positive it will never be NULL.
Definition dentry.h:88
ref_t ref
Definition dentry.h:85
dentry_id_t id
Definition dentry.h:86
const dentry_ops_t * ops
Definition dentry.h:94
_Atomic(uint64_t) mountCount
Number of mounts targeting this dentry.
list_entry_t otherEntry
Made available for use by any other subsystems for convenience.
Definition dentry.h:98
dentry_t * parent
Definition dentry.h:90
superblock_t * superblock
Definition dentry.h:93
list_entry_t siblingEntry
Definition dentry.h:91
_Atomic(dentry_flags_t) flags
map_entry_t mapEntry
Definition dentry.h:96
Directory entry struct.
Definition io.h:393
Inode structure.
Definition inode.h:56
A entry in a doubly linked list.
Definition list.h:36
A doubly linked list.
Definition list.h:49
Map entry structure.
Definition map.h:68
Path structure.
Definition path.h:125
Reference counting structure.
Definition ref.h:30
Superblock structure.
Definition superblock.h:44