Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
dentry.c
Go to the documentation of this file.
1#include <hash.h>
2#include <llist.h>
3#include <str.h>
4#include <string.h>
5#include <type.h>
6#include <vector.h>
7#include <vfs/dentry.h>
8
9#include "libk/serial.h"
10#include "llist.h"
11#include "memory/kalloc.h"
12#include "memory/slab.h"
13#include "vfs/cache.h"
14#include "vfs/dev.h"
15#include "vfs/enum.h"
16#include "vfs/rcu.h"
17#include "vfs/vnode.h"
18#include <spinlock.h>
19#include <type.h>
20
21static struct slab_cache* dentry_cache = 0;
23
25 auto h = hash32(name, 0);
26 if (parent) {
28 h ^= (uint32_t)(p & 0xFFFFFFFF);
29 h ^= (uint32_t)(p >> 32);
30 }
31 return h;
32}
33
34static spinlock_t lock = {0};
35
38 if (!dentry_cache)
40 sizeof(struct dentry), 0, 0);
41
44 // dentry_t* dentry = (dentry_t*)kalloc(sizeof(struct dentry));
45 memset(dentry, 0, sizeof(dentry_t));
46
47 __atomic_fetch_add(&dentry->refcount.counter, 1, __ATOMIC_RELAXED);
48 dentry->hash = hash_dentry(name->c_str, parent);
49 dentry->name = name;
52
54 dentry->hash_node.dentry = (void*)dentry;
55
56 llist_init(&dentry->siblings);
59
60 return dentry;
61}
62
63static void dentry_free_rcu(struct rcu_head* head) {
64 auto dentry = container_of(head, struct dentry, rcu);
66}
67
69 __atomic_fetch_add(&dentry->refcount.counter, 1, __ATOMIC_RELAXED);
70}
71
73 if (__atomic_fetch_sub(&dentry->refcount.counter, 1,
74 __ATOMIC_RELAXED) == 1) {
76 }
77}
78
81 // vector_push_back(&vnode->dentry_list, dentry);
82}
83
85
87
89 uint8_t flag) {
90 if (!path || !out)
91 return -1;
92
93 auto root_cache = get_root_cache();
94 auto path_copy = str(path);
95 if (!path_copy)
96 return -1;
97
99 dentry_get(curr);
100
101 char* path_ = path_copy->c_str;
102 while (path_ != NULL && *path_ != '\0') {
103 char* component = strsep2(&path_, "/");
104
105 if (!component || *component == '\0')
106 continue;
107
108 // strip trailing slash dan whitespace
109 size_t len = strlen(component);
110 while (len > 0 &&
111 (component[len - 1] == '/' || component[len - 1] == ' '))
112 component[--len] = '\0';
113
114 if (len == 0)
115 continue;
116
117 if (strcmp(component, ".") == 0)
118 continue;
119
120 if (strcmp(component, "..") == 0) {
121 dentry_t* up = curr->parent; // baca sekali
122 if (up) {
123 dentry_get(up);
124 dentry_put(curr);
125 curr = up;
126 }
127 continue;
128 }
129
130 dentry_t* next = cache_lookup(root_cache, curr, component);
131
132 if (!next) {
133 if (flag & CREATE_MISSING_ENTRY) {
134 dentry_t* new_entry =
135 create_dentry(str(component), 0, curr);
136 if (!new_entry)
137 goto fail;
138
139 vfs_cache_insert(root_cache, new_entry);
140 dentry_get(new_entry);
141 dentry_put(curr);
142 curr = new_entry;
143 continue;
144
145 } else {
146 auto curr_vnode = curr->vnode;
147 if (!curr_vnode)
148 goto fail;
149
150 auto fs_instance = curr_vnode->fs_instance;
151 if (!fs_instance)
152 goto fail;
153
154 if (!fs_instance->fs || !fs_instance->cdev)
155 goto fail;
156
157 auto ops = fs_instance->fs->data.ops;
158 if (!ops || !ops->lookup)
159 goto fail;
160
161 serial2_printf("lookup into fs %s\n", component);
162 if (ops->lookup(fs_instance, component, curr,
163 &next) != VFS_OK)
164 goto fail;
165
166 serial2_printf("success lokup from fs %s\n",
167 component);
168
169 vfs_cache_insert(root_cache, next);
171 dentry_put(curr);
172 curr = next;
173 continue;
174 }
175 }
176
178 dentry_put(curr);
179 curr = next;
180 }
181
182 *out = curr;
183 str_release(path_copy);
184 return VFS_OK;
185
186fail:
187 LOG2_DEBUG("Dentry", "missing '%s'", path);
188 dentry_put(curr);
189 *out = NULL;
190 str_release(path_copy);
191 return -1;
192}
193
194int KERNEL_API vxnamei(const char* path, dentry_ptr* out) {
195 if (!path || !out)
196 return -1;
197
198 *out = NULL;
199
200 size_t len = strlen(path);
201
202 if (len == 0) {
203 return -1;
204 }
205
206 char* temp = (char*)kalloc(len + 1);
207
208 if (!temp) {
209 return -1;
210 }
211
212 memset(temp, 0, len + 1);
213 memcopy(temp, (void*)path, len);
214
215 auto root_cache = get_root_cache();
216
217 dentry_t* curr = root_dentry;
218
219 if (!curr) {
220 kfree2(temp);
221 return -1;
222 }
223
224 dentry_get(curr);
225
226 char* path_iter = temp;
227
228 while (path_iter && *path_iter != '\0') {
229 char* component = strsep2(&path_iter, "/");
230
231 if (!component || component[0] == '\0')
232 continue;
233
234 dentry_t* next = cache_lookup(root_cache, curr, component);
235
236 if (!next) {
237 dentry_t* new_entry =
238 create_dentry(str(component), 0, curr);
239
240 if (!new_entry) {
241 dentry_put(curr);
242 kfree2(temp);
243 return -1;
244 }
245
246 vfs_cache_insert(root_cache, new_entry);
247
248 dentry_get(new_entry);
249 dentry_put(curr);
250 curr = new_entry;
251 continue;
252 }
253
255 dentry_put(curr);
256
257 curr = next;
258 }
259
260 kfree2(temp);
261
262 *out = curr;
263
264 return VFS_OK;
265}
266
267// TODO: need to recheck, maybe can merged with umount
269 if (!node)
270 return;
271
272 size_t n = 0;
273 struct llist_head* pos = node->child_list.next;
274 while (pos != &node->child_list) {
275 n++;
276 pos = pos->next;
277 }
278
279 dentry_t** children = NULL;
280 if (n > 0) {
281 children = (dentry_t**)kalloc(sizeof(dentry_t*) * n);
282 int i = 0;
283 pos = node->child_list.next;
284 while (pos != &node->child_list) {
285 children[i++] = container_of(pos, dentry_t, siblings);
286 pos = pos->next;
287 }
288 }
289
291 dentry_put(node);
292
293 for (size_t i = 0; i < n; i++)
294 delete_dentry(children[i]);
295
296 if (children)
297 kfree(children, sizeof(dentry_t*) * n);
298}
299
301 if (!dentry)
302 return;
303
304 // indent
305 char indent[128] = {0};
306 for (int i = 0; i < depth; i++) {
307 indent[i * 2] = ' ';
308 indent[i * 2 + 1] = ' ';
309 }
310
311 serial2_printf("%s└── %s (0x%x) (%x) (reff %d)", indent,
314
315 auto vnode = dentry->vnode;
316 if (vnode) {
317 serial2_printf(" permission %d ", vnode->permission);
318 if (vnode->type == VNODE_TYPE_BLK) {
319 serial2_printf("BLOCK DEVICE %d:%d",
322 } else if (vnode->type == VNODE_TYPE_CHR) {
323 serial2_printf("CHAR DEVICE");
324 } else {
325 serial2_printf("[%s]",
328 : "NO Filesystem");
329
330 if (vnode->mountedhere) {
331 auto block_dentry =
333 auto full_path =
334 get_full_path_from_dentry(block_dentry);
335 serial2_printf(" <%s>", full_path->c_str);
336 str_release(full_path);
337 }
338 }
339 }
340 serial2_printf("\n");
341
342 /* dong recursive in all children */
344 while (pos != &dentry->child_list) {
345 dentry_t* child = container_of(pos, dentry_t, siblings);
346
347 print_dentry_tree(child, depth + 1);
348 pos = pos->next;
349 }
350}
351
353 return __atomic_load_n(&dentry->refcount.counter, __ATOMIC_RELAXED);
354}
355
357 if (!dentry)
358 return 0;
359
360 if (!dentry->parent)
361 return str(dentry->name->c_str);
362
363 if (!dentry->name)
364 return 0;
365
366 kstring curr_name = str(dentry->name->c_str);
367 if (!curr_name)
368 return 0;
369
370 auto curr = dentry->parent;
371 while (curr) {
372 if (!curr->parent || !curr->name) {
373 kstring rooted = str_concat_prefix(curr_name, "/");
374 str_release(curr_name);
375 return rooted;
376 }
377
378 kstring with_slash = str_concat(curr->name, "/");
379 if (!with_slash) {
380 str_release(curr_name);
381 return NULL;
382 }
383
384 kstring merged = str_concat(with_slash, curr_name->c_str);
385 str_release(with_slash);
386 str_release(curr_name);
387
388 if (!merged)
389 return NULL;
390
391 curr_name = merged;
392 curr = curr->parent;
393 }
394
395 return curr_name;
396}
struct SDT h
Definition acpi.h:0
struct vfs_cache * get_root_cache()
void vfs_cache_insert(struct vfs_cache *cache, struct dentry *dentry)
uint8_t lock
Definition cache.h:1
void cache_remove(struct vfs_cache *cache, struct dentry *dentry)
Definition cache.c:116
struct dentry * cache_lookup(struct vfs_cache *cache, struct dentry *parent, const char *name)
Definition cache.c:92
int get_reffcount(dentry_ptr dentry)
Definition dentry.c:352
static dentry_t * root_dentry
Definition dentry.c:22
static struct slab_cache * dentry_cache
Definition dentry.c:21
void dentry_get(dentry_ptr dentry)
Definition dentry.c:68
uint32_t hash_dentry(const char *name, dentry_ptr parent)
Definition dentry.c:24
void print_dentry_tree(dentry_t *dentry, int depth)
Definition dentry.c:300
void delete_dentry(dentry_t *node)
Definition dentry.c:268
void dentry_put(dentry_ptr dentry)
Definition dentry.c:72
void vxSetDentryAsRoot(dentry_ptr dentry)
Definition dentry.c:84
kstring get_full_path_from_dentry(dentry_ptr dentry)
Definition dentry.c:356
static void dentry_free_rcu(struct rcu_head *head)
Definition dentry.c:63
kstring name
Definition dentry.h:5
void vxAttachDentryToVnode(dentry_ptr dentry, vnode_ptr_t vnode)
struct dentry * dentry_ptr
Definition dentry.h:20
dentry_ptr parent
Definition dentry.h:7
int resolve_dentry(char *path, dentry_ptr parent, dentry_ptr *out, uint8_t flag)
Resolves a path to a directory entry (dentry) with configurable start point and strictness.
struct rcu_head rcu
Definition dentry.h:9
int vxnamei(const char *path, dentry_ptr *out)
Resolves a file path to a directory entry (dentry).
struct dentry dentry_t
Definition dentry.h:19
dentry_ptr get_root_dentry()
@ CREATE_MISSING_ENTRY
Definition dentry.h:81
struct cdev * next
Definition dev.h:4
void * ops
Definition dev.h:2
@ VFS_OK
Definition enum.h:5
uint64_t pos
Definition fd.h:4
struct vnode vnode_t
Definition filesystem.h:10
uint32_t hash32(const char *str, size_t max_size)
Definition hash.c:16
void serial2_printf(const char *fmt,...)
void kfree(void *ptr, size_t size)
void * kalloc(size_t size)
void kfree2(void *ptr)
static void llist_init(struct llist_head *head)
Definition llist.h:18
size_t len
Definition oct2bin.h:7
void call_rcu(struct rcu_head *head, void(*func)(struct rcu_head *))
Definition rcu.c:3
#define LOG2_DEBUG(mod, fmt,...)
Definition serial.h:35
void * vxSlabAlloc(struct slab_cache *cache)
Definition slab.c:93
void slab_free(struct slab_cache *cache, void *obj)
Definition slab.c:235
void vxCreateSlabCache(struct slab_cache **cache, const char *name, const size_t obj_size, size_t alignment, const uintptr_t virt_addr)
Definition slab.c:44
void spin_acquire(spinlock_t *lock)
Definition spinlock.c:8
void spin_release(spinlock_t *lock)
Definition spinlock.c:19
int strcmp(const char *s1, const char *s2)
char * strsep2(char **stringp, const char *delim)
Definition str.c:228
size_t strlen(const char *s)
Definition str.c:105
void memset(void *ptr, int value, size_t num)
void memcopy(void *dest, void *src, size_t size)
void str_release(kstring str)
kstring str_concat(kstring s, const char *suffix)
kstring str(const char *str)
kstring str_concat_prefix(kstring s, const char *prefix)
int counter
Definition type.h:80
struct hlist_node hash_node
Definition dentry.h:35
kstring name
Definition dentry.h:32
struct rcu_head rcu
Definition dentry.h:36
dentry_ptr parent
Definition dentry.h:34
uint32_t hash
Definition dentry.h:30
struct vnode * vnode
Definition dentry.h:33
atomic_t refcount
Definition dentry.h:29
struct llist_head child_list
Definition dentry.h:27
uint32_t major
Definition vnode.h:55
uint32_t minor
Definition vnode.h:56
struct fs_data data
Definition filesystem.h:33
char name[16]
Definition filesystem.h:32
fs_operations_t * ops
Definition filesystem.h:28
dentry_ptr block_dentry
Definition filesystem.h:39
cdev_ptr_t cdev
Definition filesystem.h:40
filesystem_ptr_t fs
Definition filesystem.h:41
struct hlist_node * next
Definition cache.h:9
struct hlist_node * prev
Definition cache.h:10
void * dentry
Definition cache.h:11
char * c_str
Definition string.h:12
struct llist_head * next
Definition llist.h:11
Definition rcu.h:6
Definition vnode.h:59
struct device_id device
Definition vnode.h:73
uint8_t type
Definition vnode.h:62
uint16_t permission
Definition vnode.h:65
struct fs_instance * fs_instance
Definition vnode.h:67
cdev_ptr_t mountedhere
Definition vnode.h:68
uint32_t head
Definition tty.h:10
#define NULL
Definition type.h:76
unsigned int uint32_t
Definition type.h:19
#define KERNEL_API
Definition type.h:93
unsigned long uintptr_t
Definition type.h:73
unsigned char uint8_t
Definition type.h:7
#define container_of(ptr, type, member)
Definition type.h:108
@ VNODE_TYPE_CHR
Definition vnode.h:15
@ VNODE_TYPE_BLK
Definition vnode.h:16
kstring path
Definition voxmo.h:7