PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
namespace.c
Go to the documentation of this file.
2
4#include <kernel/fs/dentry.h>
6#include <kernel/fs/mount.h>
7#include <kernel/fs/path.h>
9#include <kernel/fs/vfs.h>
10#include <kernel/log/log.h>
11#include <kernel/proc/process.h>
12#include <kernel/sched/thread.h>
13#include <kernel/sync/lock.h>
14#include <kernel/sync/rwlock.h>
15#include <kernel/utils/map.h>
16
17#include <errno.h>
18#include <stdlib.h>
19#include <sys/fs.h>
20#include <sys/list.h>
21
22static map_key_t mount_key(mount_id_t parentId, dentry_id_t mountpointId)
23{
24 struct
25 {
26 mount_id_t parentId;
27 dentry_id_t mountpointId;
28 } buffer;
29 buffer.parentId = parentId;
30 buffer.mountpointId = mountpointId;
31
32 return map_key_buffer(&buffer, sizeof(buffer));
33}
34
35static map_key_t root_key(void)
36{
37 struct
38 {
39 mount_id_t parentId;
40 dentry_id_t mountpointId;
41 } buffer = {.parentId = UINT64_MAX, .mountpointId = UINT64_MAX};
42
43 return map_key_buffer(&buffer, sizeof(buffer));
44}
45
47{
48 if (mount->parent == NULL)
49 {
50 return root_key();
51 }
52
53 return mount_key(mount->parent->id, mount->target->id);
54}
55
57{
58 if (stack->count >= ARRAY_SIZE(stack->mounts))
59 {
60 errno = ENOMEM;
61 return ERR;
62 }
63
64 stack->mounts[stack->count] = REF(mount);
65 stack->count++;
66
67 return 0;
68}
69
71{
72 for (uint64_t i = 0; i < stack->count; i++)
73 {
74 if (stack->mounts[i] != mount)
75 {
76 continue;
77 }
78
79 UNREF(stack->mounts[i]);
80 stack->mounts[i] = NULL;
81
82 memmove(&stack->mounts[i], &stack->mounts[i + 1], (stack->count - i - 1) * sizeof(mount_t*));
83 stack->count--;
84 break;
85 }
86}
87
89{
90 list_entry_init(&stack->entry);
91 map_entry_init(&stack->mapEntry);
92 stack->count = 0;
93
94 if (map_insert(&ns->mountMap, key, &stack->mapEntry) == ERR)
95 {
96 return ERR;
97 }
98 list_push_back(&ns->stacks, &stack->entry);
99 return 0;
100}
101
103{
104 if (stack == NULL)
105 {
106 return;
107 }
108
109 for (uint64_t i = 0; i < stack->count; i++)
110 {
111 UNREF(stack->mounts[i]);
112 stack->mounts[i] = NULL;
113 }
114 stack->count = 0;
115
116 list_remove(&stack->entry);
117 map_remove(&ns->mountMap, &stack->mapEntry);
118
119 if (&ns->root == stack)
120 {
121 return;
122 }
123
124 free(stack);
125}
126
128{
129 return CONTAINER_OF_SAFE(map_get(&ns->mountMap, key), mount_stack_t, mapEntry);
130}
131
133{
134 if (MOUNT_IS_ROOT(mount))
135 {
136 if (mount_stack_push(&ns->root, mount) == ERR)
137 {
138 return ERR;
139 }
140 goto propagate;
141 }
142
145 if (stack == NULL)
146 {
147 stack = malloc(sizeof(mount_stack_t));
148 if (stack == NULL)
149 {
150 errno = ENOMEM;
151 return ERR;
152 }
153
154 if (mount_stack_init(ns, stack, &key) == ERR)
155 {
156 free(stack);
157 return ERR;
158 }
159 }
160
162 {
163 return ERR;
164 }
165
166propagate:
167 if (mount->mode & MODE_PROPAGATE)
168 {
169 namespace_t* child;
170 LIST_FOR_EACH(child, &ns->children, entry)
171 {
172 RWLOCK_WRITE_SCOPE(&child->lock);
173
174 if (namespace_add(child, mount) == ERR)
175 {
176 return ERR;
177 }
178 }
179 }
180
181 return 0;
182}
183
185{
186 if (mount->mode & MODE_LOCKED)
187 {
188 return;
189 }
190
191 if (MOUNT_IS_ROOT(mount))
192 {
194 goto propagate;
195 }
196
199 if (stack != NULL)
200 {
202
203 if (stack->count == 0)
204 {
206 }
207 }
208
209propagate:
210 if (mode & MODE_PROPAGATE)
211 {
212 namespace_t* child;
213 LIST_FOR_EACH(child, &ns->children, entry)
214 {
215 RWLOCK_WRITE_SCOPE(&child->lock);
216
217 namespace_remove(child, mount, mode);
218 }
219 }
220}
221
223{
224 if (ns == NULL)
225 {
226 return;
227 }
228
229 if (ns->parent != NULL)
230 {
232 list_remove(&ns->entry);
234 UNREF(ns->parent);
235 ns->parent = NULL;
236 }
237
239
240 while (!list_is_empty(&ns->stacks))
241 {
244 }
245
246 map_deinit(&ns->mountMap);
247
249
250 free(ns);
251}
252
254{
255 namespace_t* ns = malloc(sizeof(namespace_t));
256 if (ns == NULL)
257 {
258 errno = ENOMEM;
259 return NULL;
260 }
263 list_init(&ns->children);
264 ns->parent = NULL;
265 list_init(&ns->stacks);
266 map_init(&ns->mountMap);
267
268 map_key_t key = root_key();
269 if (mount_stack_init(ns, &ns->root, &key) == ERR)
270 {
271 free(ns);
272 return NULL;
273 }
274
275 rwlock_init(&ns->lock);
276
277 if (parent != NULL)
278 {
279 RWLOCK_WRITE_SCOPE(&parent->lock);
280 ns->parent = REF(parent);
281 list_push_back(&parent->children, &ns->entry);
282 }
283
284 return ns;
285}
286
288{
289 if (dest == NULL || src == NULL)
290 {
291 errno = EINVAL;
292 return ERR;
293 }
294
295 RWLOCK_WRITE_SCOPE(&dest->lock);
297
299 LIST_FOR_EACH(stack, &src->stacks, entry)
300 {
301 for (uint64_t i = 0; i < stack->count; i++)
302 {
303 if (stack->mounts[i]->mode & MODE_PRIVATE)
304 {
305 continue;
306 }
307
308 if (namespace_add(dest, stack->mounts[i]) == ERR)
309 {
310 return ERR;
311 }
312 }
313 }
314
315 return 0;
316}
317
318static bool namespace_is_descendant(namespace_t* ancestor, namespace_t* descendant)
319{
320 // To prevent deadlocks we cant do a search starting from the child, we must always acquire looks from the top down.
321 // So this is a bit inefficient.
322
323 if (ancestor == descendant)
324 {
325 return true;
326 }
327
328 namespace_t* child;
329 LIST_FOR_EACH(child, &ancestor->children, entry)
330 {
331 RWLOCK_READ_SCOPE(&child->lock);
332 if (namespace_is_descendant(child, descendant))
333 {
334 return true;
335 }
336 }
337
338 return false;
339}
340
342{
343 if (ns == NULL || other == NULL)
344 {
345 return false;
346 }
347
349 return namespace_is_descendant(ns, other);
350}
351
353{
354 if (ns == NULL || mount == NULL || dentry == NULL || *mount == NULL || *dentry == NULL)
355 {
356 return false;
357 }
358
360
361 bool traversed = false;
362 for (uint64_t i = 0; i < NAMESPACE_MAX_TRAVERSE; i++)
363 {
364 if (atomic_load(&(*dentry)->mountCount) == 0)
365 {
366 return traversed;
367 }
368
369 map_key_t key = mount_key((*mount)->id, (*dentry)->id);
371 if (stack == NULL)
372 {
373 return traversed;
374 }
375
376 assert(stack->count > 0);
377 mount_t* mnt = stack->mounts[stack->count - 1];
378
379 *mount = mnt;
380 *dentry = mnt->source;
381 traversed = true;
382 }
383
384 return traversed;
385}
386
387mount_t* namespace_mount(namespace_t* ns, path_t* target, filesystem_t* fs, const char* options, mode_t mode,
388 void* data)
389{
390 if (ns == NULL || fs == NULL)
391 {
392 errno = EINVAL;
393 return NULL;
394 }
395
396 dentry_t* root = fs->mount(fs, options, data);
397 if (root == NULL)
398 {
399 return NULL;
400 }
402
403 if (root->superblock->root != root)
404 {
405 errno = EIO;
406 return NULL;
407 }
408
410
411 mount_t* mount = mount_new(root->superblock, root, target != NULL ? target->dentry : NULL,
412 target != NULL ? target->mount : NULL, mode);
413 if (mount == NULL)
414 {
415 return NULL;
416 }
417
418 if (namespace_add(ns, mount) == ERR)
419 {
420 UNREF(mount);
421 return NULL;
422 }
423
424 return mount;
425}
426
428{
429 if (ns == NULL || !PATH_IS_VALID(source))
430 {
431 errno = EINVAL;
432 return NULL;
433 }
434
435 if (mode_check(&mode, source->mount->mode) == ERR)
436 {
437 return NULL;
438 }
439
441
442 mount_t* mount = mount_new(source->dentry->superblock, source->dentry, target != NULL ? target->dentry : NULL,
443 target != NULL ? target->mount : NULL, mode);
444 if (mount == NULL)
445 {
446 return NULL;
447 }
448
449 if (namespace_add(ns, mount) == ERR)
450 {
451 UNREF(mount);
452 errno = ENOMEM;
453 return NULL;
454 }
455
456 return mount;
457}
458
460{
461 if (ns == NULL || mount == NULL)
462 {
463 return;
464 }
465
467 namespace_remove(ns, mount, mode);
468}
469
471{
472 if (ns == NULL || out == NULL)
473 {
474 path_set(out, NULL, NULL);
475 return;
476 }
477
479
480 if (ns->root.count == 0)
481 {
482 path_set(out, NULL, NULL);
483 return;
484 }
485
486 mount_t* mnt = ns->root.mounts[ns->root.count - 1];
487 path_set(out, mnt, mnt->source);
488}
489
491{
492 if (ns == NULL || mount == NULL || dentry == NULL)
493 {
494 if (mount != NULL)
495 {
496 *mount = NULL;
497 }
498 if (dentry != NULL)
499 {
500 *dentry = NULL;
501 }
502 return;
503 }
504
506
507 if (ns->root.count == 0)
508 {
509 *mount = NULL;
510 *dentry = NULL;
511 return;
512 }
513
514 mount_t* mnt = ns->root.mounts[ns->root.count - 1];
515 *mount = mnt;
516 *dentry = mnt->source;
517}
518
519SYSCALL_DEFINE(SYS_MOUNT, uint64_t, const char* mountpoint, const char* fs, const char* options)
520{
521 thread_t* thread = thread_current();
522 process_t* process = thread->process;
523
524 pathname_t mountname;
525 if (thread_copy_from_user_pathname(thread, &mountname, mountpoint) == ERR)
526 {
527 return ERR;
528 }
529
530 namespace_t* ns = process_get_ns(process);
531 if (ns == NULL)
532 {
533 return ERR;
534 }
535 UNREF_DEFER(ns);
536
537 path_t mountpath = cwd_get(&process->cwd, ns);
538 PATH_DEFER(&mountpath);
539
540 if (path_walk(&mountpath, &mountname, ns) == ERR)
541 {
542 return ERR;
543 }
544
545 char fsCopy[MAX_PATH];
546 if (thread_copy_from_user_string(thread, fsCopy, fs, MAX_PATH) == ERR)
547 {
548 return ERR;
549 }
550
551 char optionsCopy[MAX_PATH];
552 if (options != NULL && thread_copy_from_user_string(thread, optionsCopy, options, MAX_PATH) == ERR)
553 {
554 return ERR;
555 }
556
557 filesystem_t* filesystem = filesystem_get_by_path(fsCopy, process);
558 if (filesystem == NULL)
559 {
560 return ERR;
561 }
562
563 mount_t* mount =
564 namespace_mount(ns, &mountpath, filesystem, options != NULL ? optionsCopy : NULL, mountname.mode, NULL);
565 if (mount == NULL)
566 {
567 return ERR;
568 }
569 UNREF(mount);
570 return 0;
571}
572
573SYSCALL_DEFINE(SYS_UNMOUNT, uint64_t, const char* mountpoint)
574{
575 thread_t* thread = thread_current();
576 process_t* process = thread->process;
577
578 pathname_t mountname;
579 if (thread_copy_from_user_pathname(thread, &mountname, mountpoint) == ERR)
580 {
581 return ERR;
582 }
583
584 namespace_t* ns = process_get_ns(process);
585 if (ns == NULL)
586 {
587 return ERR;
588 }
589 UNREF_DEFER(ns);
590
591 path_t mountpath = cwd_get(&process->cwd, ns);
592 PATH_DEFER(&mountpath);
593
594 if (path_walk(&mountpath, &mountname, ns) == ERR)
595 {
596 return ERR;
597 }
598
599 namespace_unmount(ns, mountpath.mount, mountname.mode);
600 return 0;
601}
602
603SYSCALL_DEFINE(SYS_BIND, uint64_t, const char* mountpoint, fd_t source)
604{
605 thread_t* thread = thread_current();
606 process_t* process = thread->process;
607
608 pathname_t mountname;
609 if (thread_copy_from_user_pathname(thread, &mountname, mountpoint) == ERR)
610 {
611 return ERR;
612 }
613
614 namespace_t* ns = process_get_ns(process);
615 if (ns == NULL)
616 {
617 return ERR;
618 }
619 UNREF_DEFER(ns);
620
621 path_t mountpath = cwd_get(&process->cwd, ns);
622 PATH_DEFER(&mountpath);
623
624 if (path_walk(&mountpath, &mountname, ns) == ERR)
625 {
626 return ERR;
627 }
628
629 file_t* sourceFile = file_table_get(&process->fileTable, source);
630 if (sourceFile == NULL)
631 {
632 return ERR;
633 }
634 UNREF_DEFER(sourceFile);
635
636 mount_t* bind = namespace_bind(ns, &mountpath, &sourceFile->path, mountname.mode);
637 if (bind == NULL)
638 {
639 return ERR;
640 }
641 UNREF(bind);
642 return 0;
643}
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
#define assert(expression)
Definition assert.h:29
EFI_PHYSICAL_ADDRESS buffer
Definition main.c:237
static dentry_t * root
Definition devfs.c:25
static fd_t data
Definition dwm.c:21
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscall.h:172
@ SYS_MOUNT
Definition syscall.h:102
@ SYS_UNMOUNT
Definition syscall.h:103
@ SYS_BIND
Definition syscall.h:96
static clock_source_t source
Structure to describe the HPET to the sys time subsystem.
Definition hpet.c:193
path_t cwd_get(cwd_t *cwd, namespace_t *ns)
Get the current working directory.
Definition cwd.c:19
uint64_t dentry_id_t
Dentry ID type.
Definition dentry.h:49
file_t * file_table_get(file_table_t *table, fd_t fd)
Get a file from its file descriptor.
Definition file_table.c:33
filesystem_t * filesystem_get_by_path(const char *path, process_t *process)
Gets a filesystem by path.
Definition filesystem.c:284
mount_t * mount_new(superblock_t *superblock, dentry_t *source, dentry_t *target, mount_t *parent, mode_t mode)
Create a new mount.
Definition mount.c:40
#define MOUNT_IS_ROOT(mount)
Check if a mount is a root mount within its namespace.
Definition mount.h:34
uint64_t mount_id_t
Mount ID type.
Definition mount.h:39
mount_t * namespace_bind(namespace_t *ns, path_t *target, path_t *source, mode_t mode)
Bind a source path to a target path in a namespace.
Definition namespace.c:427
void namespace_unmount(namespace_t *ns, mount_t *mount, mode_t mode)
Remove a mount in a namespace.
Definition namespace.c:459
uint64_t namespace_copy(namespace_t *dest, namespace_t *src)
Copy mounts from one namespace to another.
Definition namespace.c:287
namespace_t * namespace_new(namespace_t *parent)
Create a new namespace.
Definition namespace.c:253
mount_t * namespace_mount(namespace_t *ns, path_t *target, filesystem_t *fs, const char *options, mode_t mode, void *data)
Mount a filesystem in a namespace.
Definition namespace.c:387
void namespace_rcu_get_root(namespace_t *ns, mount_t **mount, dentry_t **dentry)
Get the root mount of a namespace in an RCU read critical section.
Definition namespace.c:490
#define NAMESPACE_MAX_TRAVERSE
Maximum number of iterative mount traversals when following mountpoints.
Definition namespace.h:31
void namespace_get_root(namespace_t *ns, path_t *out)
Get the root path of a namespace.
Definition namespace.c:470
bool namespace_rcu_traverse(namespace_t *ns, mount_t **mount, dentry_t **dentry)
If the given path is a mountpoint in the namespace, traverse to the mounted filesystem in an RCU read...
Definition namespace.c:352
bool namespace_accessible(namespace_t *ns, namespace_t *other)
Check if mounts in a namespace can be propagated to another namespace.
Definition namespace.c:341
mode_t
Path flags and permissions.
Definition path.h:79
#define PATH_IS_VALID(path)
Check if a path is valid.
Definition path.h:196
uint64_t mode_check(mode_t *mode, mode_t maxPerms)
Check and adjust mode permissions.
Definition path.c:816
#define PATH_DEFER(path)
Defer path put.
Definition path.h:106
void path_set(path_t *path, mount_t *mount, dentry_t *dentry)
Set a path.
Definition path.c:242
uint64_t path_walk(path_t *path, const pathname_t *pathname, namespace_t *ns)
Walk a pathname to a path.
Definition path.c:593
@ MODE_LOCKED
Definition path.h:95
@ MODE_PRIVATE
Definition path.h:93
@ MODE_PROPAGATE
Definition path.h:94
namespace_t * process_get_ns(process_t *process)
Gets the namespace of a process.
Definition process.c:206
static thread_t * thread_current(void)
Retrieves the currently running thread.
Definition thread.h:126
uint64_t thread_copy_from_user_pathname(thread_t *thread, pathname_t *pathname, const char *userPath)
Safely copy a string from user space and use it to initialize a pathname.
Definition thread.c:300
uint64_t thread_copy_from_user_string(thread_t *thread, char *dest, const char *userSrc, uint64_t size)
Safely copy a string from user space.
Definition thread.c:278
static void rwlock_write_release(rwlock_t *lock)
Releases a rwlock from writing.
Definition rwlock.h:196
static void rwlock_init(rwlock_t *lock)
Initializes a rwlock.
Definition rwlock.h:79
#define RWLOCK_READ_SCOPE(lock)
Acquires a rwlock for reading for the reminder of the current scope.
Definition rwlock.h:34
static void rwlock_write_acquire(rwlock_t *lock)
Acquires a rwlock for writing, blocking until it is available.
Definition rwlock.h:158
#define RWLOCK_WRITE_SCOPE(lock)
Acquires a rwlock for writing for the reminder of the current scope.
Definition rwlock.h:43
static map_key_t map_key_buffer(const void *buffer, uint64_t length)
Create a map key from a buffer.
Definition map.h:113
void map_init(map_t *map)
Initialize a map.
Definition map.c:142
void map_deinit(map_t *map)
Deinitialize a map.
Definition map.c:150
void map_entry_init(map_entry_t *entry)
Initialize a map entry.
Definition map.c:37
uint64_t map_insert(map_t *map, const map_key_t *key, map_entry_t *value)
Insert a key-value pair into the map.
Definition map.c:170
void map_remove(map_t *map, map_entry_t *entry)
Remove a entry from the map.
Definition map.c:319
map_entry_t * map_get(map_t *map, const map_key_t *key)
Get a value from the map by key.
Definition map.c:253
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:122
#define REF(ptr)
Increment reference count.
Definition ref.h:82
static void ref_init(ref_t *ref, void *callback)
Initialize a reference counter.
Definition ref.h:130
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:109
#define EINVAL
Invalid argument.
Definition errno.h:142
#define ENOMEM
Out of memory.
Definition errno.h:92
#define EIO
I/O error.
Definition errno.h:57
#define errno
Error number variable.
Definition errno.h:27
#define ARRAY_SIZE(x)
Get the number of elements in a static array.
Definition defs.h:111
uint64_t mount(const char *mountpoint, const char *fs, const char *options)
System call for mounting a filesystem.
Definition mount.c:5
uint64_t bind(const char *mountpoint, fd_t source)
System call for binding a file descriptor to a mountpoint.
Definition bind.c:5
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:58
static void list_remove(list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:290
static list_entry_t * list_first(list_t *list)
Gets the first entry in the list without removing it.
Definition list.h:406
static void list_push_back(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:322
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:210
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:173
static void list_init(list_t *list)
Initializes a list.
Definition list.h:185
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
#define CONTAINER_OF(ptr, type, member)
Container of macro.
__UINT64_TYPE__ fd_t
File descriptor type.
Definition fd_t.h:10
#define CONTAINER_OF_SAFE(ptr, type, member)
Safe container of macro.
static void namespace_remove(namespace_t *ns, mount_t *mount, mode_t mode)
Definition namespace.c:184
static map_key_t root_key(void)
Definition namespace.c:35
static bool namespace_is_descendant(namespace_t *ancestor, namespace_t *descendant)
Definition namespace.c:318
static uint64_t mount_stack_init(namespace_t *ns, mount_stack_t *stack, map_key_t *key)
Definition namespace.c:88
static void mount_stack_remove(mount_stack_t *stack, mount_t *mount)
Definition namespace.c:70
static void namespace_free(namespace_t *ns)
Definition namespace.c:222
static map_key_t mount_key_from_mount(mount_t *mount)
Definition namespace.c:46
static map_key_t mount_key(mount_id_t parentId, dentry_id_t mountpointId)
Definition namespace.c:22
static uint64_t namespace_add(namespace_t *ns, mount_t *mount)
Definition namespace.c:132
static uint64_t mount_stack_push(mount_stack_t *stack, mount_t *mount)
Definition namespace.c:56
static mount_stack_t * namespace_get_stack(namespace_t *ns, const map_key_t *key)
Definition namespace.c:127
static void mount_stack_free(namespace_t *ns, mount_stack_t *stack)
Definition namespace.c:102
static page_stack_t * stack
Definition pmm.c:40
#define atomic_load(object)
Definition stdatomic.h:288
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
#define UINT64_MAX
Definition stdint.h:74
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC void * memmove(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Directory entry structure.
Definition dentry.h:155
superblock_t * superblock
Definition dentry.h:163
File structure.
Definition file.h:39
path_t path
Definition file.h:44
Filesystem structure, represents a filesystem type, e.g. fat32, tmpfs, devfs, etc.
Definition filesystem.h:53
dentry_t *(* mount)(filesystem_t *fs, const char *details, void *data)
Mount a filesystem.
Definition filesystem.h:68
Map key stucture.
Definition map.h:57
Mount stack.
Definition namespace.h:45
uint64_t count
Definition namespace.h:49
mount_t * mounts[MOUNT_STACK_MAX_MOUNTS]
Definition namespace.h:48
Mount structure.
Definition mount.h:48
dentry_t * source
The dentry to appear at target once mounted, usually the root dentry of the mounted filesystem.
Definition mount.h:52
Namespace structure.
Definition namespace.h:57
mount_stack_t root
The root mount stack.
Definition namespace.h:64
list_entry_t entry
The entry for the parent's children list.
Definition namespace.h:59
ref_t ref
Definition namespace.h:58
rwlock_t lock
Definition namespace.h:65
namespace_t * parent
The parent namespace, can be NULL.
Definition namespace.h:61
list_t stacks
List of mount_stack_t in this namespace.
Definition namespace.h:62
map_t mountMap
Map used to go from source dentries to namespace mount stacks.
Definition namespace.h:63
list_t children
List of child namespaces.
Definition namespace.h:60
Path structure.
Definition path.h:127
mount_t * mount
Definition path.h:128
dentry_t * dentry
Definition path.h:129
Pathname structure.
Definition path.h:139
mode_t mode
Definition path.h:141
Process structure.
Definition process.h:76
file_table_t fileTable
Definition process.h:88
cwd_t cwd
Definition process.h:87
dentry_t * root
Root dentry of the filesystem, should not take a reference.
Definition superblock.h:40
Thread of execution structure.
Definition thread.h:61
process_t * process
The parent process that the thread executes within.
Definition thread.h:62