PatchworkOS
Loading...
Searching...
No Matches
namespace.c
Go to the documentation of this file.
2
4#include <kernel/fs/dentry.h>
5#include <kernel/fs/mount.h>
6#include <kernel/fs/path.h>
8#include <kernel/fs/vfs.h>
9#include <kernel/log/log.h>
10#include <kernel/proc/process.h>
11#include <kernel/sched/thread.h>
12
13#include <errno.h>
14
15static map_key_t mount_cache_key(mount_id_t parentId, dentry_id_t mountpointId)
16{
17 struct
18 {
19 mount_id_t parentId;
20 dentry_id_t mountpointId;
21 } buffer;
22 buffer.parentId = parentId;
23 buffer.mountpointId = mountpointId;
24
25 return map_key_buffer(&buffer, sizeof(buffer));
26}
27
29{
30 if (ns == NULL)
31 {
32 errno = EINVAL;
33 return ERR;
34 }
35
36 if (map_init(&ns->mountPoints) == ERR)
37 {
38 return ERR;
39 }
40
41 rwlock_init(&ns->lock);
42 ns->parent = parent;
43 ns->owner = owner;
44 ns->rootMount = (parent != NULL && parent->rootMount != NULL) ? REF(parent->rootMount) : NULL;
45 return 0;
46}
47
49{
50 if (ns == NULL)
51 {
52 return;
53 }
54
55 DEREF(ns->rootMount);
56
58 for (uint64_t i = 0; i < ns->mountPoints.capacity; i++)
59 {
60 map_entry_t* entry = ns->mountPoints.entries[i];
61 if (!MAP_ENTRY_PTR_IS_VALID(entry))
62 {
63 continue;
64 }
65 mount_t* mount = CONTAINER_OF(entry, mount_t, mapEntry);
66 DEREF(mount);
67 }
69
71}
72
74{
75 if (mountpoint == NULL || mountpoint->mount == NULL || mountpoint->dentry == NULL || outRoot == NULL)
76 {
77 errno = EINVAL;
78 return ERR;
79 }
80
81 map_key_t key = mount_cache_key(mountpoint->mount->id, mountpoint->dentry->id);
82 namespace_t* currentNs = ns;
83 while (currentNs != NULL)
84 {
85 RWLOCK_READ_SCOPE(&currentNs->lock);
86
87 mount_t* mount = CONTAINER_OF_SAFE(map_get(&currentNs->mountPoints, &key), mount_t, mapEntry);
88 if (mount != NULL)
89 {
90 if (mount->superblock == NULL || mount->root == NULL)
91 {
92 errno = ESTALE;
93 return ERR;
94 }
95
96 path_set(outRoot, mount, mount->root);
97 return 0;
98 }
99
100 currentNs = currentNs->parent;
101 }
102
103 path_copy(outRoot, mountpoint);
104 return 0;
105}
106
107mount_t* namespace_mount(namespace_t* ns, path_t* mountpoint, const char* deviceName, const char* fsName, void* private)
108{
109 if (deviceName == NULL || fsName == NULL)
110 {
111 errno = EINVAL;
112 return NULL;
113 }
114
115 if (ns == NULL)
116 {
119 ns = &kernelProcess->namespace;
120 }
121
122 filesystem_t* fs = vfs_get_fs(fsName);
123 if (fs == NULL)
124 {
125 errno = ENODEV;
126 return NULL;
127 }
128
129 dentry_t* root = fs->mount(fs, deviceName, private);
130 if (root == NULL)
131 {
132 return NULL;
133 }
134 DEREF_DEFER(root);
135
136 if (atomic_load(&root->flags) & DENTRY_NEGATIVE)
137 {
138 errno = EIO; // This should never happen.
139 return NULL;
140 }
141
142 if (mountpoint == NULL)
143 {
145 if (ns->rootMount != NULL)
146 {
147 errno = EBUSY;
148 return NULL;
149 }
150
151 ns->rootMount = mount_new(root->superblock, root, NULL, NULL);
152 if (ns->rootMount == NULL)
153 {
154 return NULL;
155 }
156
157 LOG_INFO("mounted %s as root with %s\n", deviceName, fsName);
158 return REF(ns->rootMount);
159 }
160
161 if (ns->rootMount == NULL)
162 {
163 errno = ENOENT;
164 return NULL;
165 }
166
167 if (atomic_load(&mountpoint->dentry->flags) & DENTRY_NEGATIVE)
168 {
169 errno = ENOENT;
170 return NULL;
171 }
172
173 mount_t* mount = mount_new(root->superblock, root, mountpoint->dentry, mountpoint->mount);
174 if (mount == NULL)
175 {
176 return NULL;
177 }
178
179 map_key_t key = mount_cache_key(mountpoint->mount->id, mountpoint->dentry->id);
181 if (map_insert(&ns->mountPoints, &key, &mount->mapEntry) == ERR)
182 {
183 DEREF(mount);
185 return NULL;
186 }
188
189 // superblock_expose(superblock); // TODO: Expose the sysfsDir for the superblock
190
191 LOG_DEBUG("mounted %s with %s\n", deviceName, fsName);
192 return REF(mount);
193}
194
196{
197 if (source == NULL || mountpoint == NULL || mountpoint->dentry == NULL || mountpoint->mount == NULL)
198 {
199 errno = EINVAL;
200 return NULL;
201 }
202
203 if (atomic_load(&source->flags) & DENTRY_NEGATIVE)
204 {
205 errno = ENOENT;
206 return NULL;
207 }
208
209 if (ns == NULL)
210 {
213 ns = &kernelProcess->namespace;
214 }
215
216 mount_t* mount = mount_new(source->superblock, source, mountpoint->dentry, mountpoint->mount);
217 if (mount == NULL)
218 {
219 return NULL;
220 }
221
222 map_key_t key = mount_cache_key(mountpoint->mount->id, mountpoint->dentry->id);
224 if (map_insert(&ns->mountPoints, &key, &mount->mapEntry) == ERR)
225 {
226 DEREF(mount);
228 return NULL;
229 }
231
232 return REF(mount);
233}
234
235SYSCALL_DEFINE(SYS_BIND, uint64_t, fd_t source, const char* mountpointString)
236{
237 if (mountpointString == NULL)
238 {
239 errno = EINVAL;
240 return ERR;
241 }
242
243 thread_t* thread = sched_thread();
244 process_t* process = thread->process;
245
246 pathname_t pathname;
247 if (thread_copy_from_user_pathname(thread, &pathname, mountpointString) == ERR)
248 {
249 return ERR;
250 }
251
252 path_t mountpoint;
253 if (vfs_walk(&mountpoint, &pathname, WALK_NONE, process) == ERR)
254 {
255 return ERR;
256 }
257
258 file_t* sourceFile = vfs_ctx_get_file(&process->vfsCtx, source);
259 if (sourceFile == NULL)
260 {
261 return ERR;
262 }
263 DEREF_DEFER(sourceFile);
264
265 mount_t* bind = namespace_bind(&process->namespace, sourceFile->path.dentry, &mountpoint);
266 if (bind == NULL)
267 {
268 return ERR;
269 }
270 DEREF(bind);
271 return 0;
272}
273
275{
276 if (outPath == NULL)
277 {
278 errno = EINVAL;
279 return ERR;
280 }
281
282 if (ns == NULL)
283 {
286 ns = &kernelProcess->namespace;
287 }
288
290 if (ns->rootMount == NULL || ns->rootMount->superblock == NULL || ns->rootMount->root == NULL)
291 {
293 errno = ENOENT;
294 return ERR;
295 }
296 path_set(outPath, ns->rootMount, ns->rootMount->root);
298 return 0;
299}
static mount_t * mount
Definition acpi.c:15
#define assert(expression)
Definition assert.h:29
static map_key_t mount_cache_key(mount_id_t parentId, dentry_id_t mountpointId)
Definition namespace.c:15
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscalls.h:100
#define SYS_BIND
Definition syscalls.h:54
uint64_t dentry_id_t
Dentry ID type.
Definition dentry.h:33
@ DENTRY_NEGATIVE
Definition dentry.h:59
uint64_t mount_id_t
Mount ID type.
Definition mount.h:28
mount_t * mount_new(superblock_t *superblock, dentry_t *root, dentry_t *mountpoint, mount_t *parent)
Create a new mount.
Definition mount.c:39
uint64_t namespace_get_root_path(namespace_t *ns, path_t *outPath)
Get the root path of a namespace.
Definition namespace.c:274
uint64_t namespace_traverse_mount(namespace_t *ns, const path_t *mountpoint, path_t *outRoot)
Traverse a mountpoint path to the root of the mounted filesystem.
Definition namespace.c:73
void namespace_deinit(namespace_t *ns)
Deinitializes a namespace.
Definition namespace.c:48
mount_t * namespace_bind(namespace_t *ns, dentry_t *source, path_t *mountpoint)
Bind a directory to a mountpoint in a namespace.
Definition namespace.c:195
mount_t * namespace_mount(namespace_t *ns, path_t *mountpoint, const char *deviceName, const char *fsName, void *private)
Mount a filesystem in a namespace.
Definition namespace.c:107
uint64_t namespace_init(namespace_t *ns, namespace_t *parent, process_t *owner)
Initializes a namespace.
Definition namespace.c:28
void path_set(path_t *path, mount_t *mount, dentry_t *dentry)
Set a path.
Definition path.c:207
void path_copy(path_t *dest, const path_t *src)
Copy a path.
Definition path.c:232
@ WALK_NONE
No flags.
Definition path.h:101
file_t * vfs_ctx_get_file(vfs_ctx_t *ctx, fd_t fd)
Get a file from a VFS context.
Definition vfs_ctx.c:48
filesystem_t * vfs_get_fs(const char *name)
Gets a filesystem by name.
Definition vfs.c:152
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.
Definition vfs.c:341
#define LOG_INFO(format,...)
Definition log.h:87
#define LOG_DEBUG(format,...)
Definition log.h:81
process_t * process_get_kernel(void)
Gets the kernel process.
Definition process.c:594
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:307
thread_t * sched_thread(void)
Retrieves the currently running thread.
Definition sched.c:157
void rwlock_write_acquire(rwlock_t *lock)
Acquires a rwlock for writing, blocking until it is available.
Definition rwlock.c:65
void rwlock_read_acquire(rwlock_t *lock)
Acquires a rwlock for reading, blocking until it is available.
Definition rwlock.c:18
#define RWLOCK_READ_SCOPE(lock)
Acquires a rwlock for reading for the reminder of the current scope.
Definition rwlock.h:27
void rwlock_read_release(rwlock_t *lock)
Releases a rwlock from reading.
Definition rwlock.c:57
void rwlock_write_release(rwlock_t *lock)
Releases a rwlock from writing.
Definition rwlock.c:116
void rwlock_init(rwlock_t *lock)
Initializes a rwlock.
Definition rwlock.c:8
#define RWLOCK_WRITE_SCOPE(lock)
Acquires a rwlock for writing for the reminder of the current scope.
Definition rwlock.h:36
static map_key_t map_key_buffer(const void *buffer, uint64_t length)
Create a map key from a buffer.
Definition map.h:99
void map_deinit(map_t *map)
Deinitialize a map.
Definition map.c:182
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:191
uint64_t map_init(map_t *map)
Initialize a map.
Definition map.c:172
#define MAP_ENTRY_PTR_IS_VALID(entryPtr)
Check if a map entry pointer is valid (not NULL or tombstone).
Definition map.h:67
map_entry_t * map_get(map_t *map, const map_key_t *key)
Get a value from the map by key.
Definition map.c:236
#define DEREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:54
#define REF(ptr)
Increment reference count.
Definition ref.h:65
#define DEREF(ptr)
Decrement reference count.
Definition ref.h:80
#define ENOENT
No such file or directory.
Definition errno.h:42
#define ESTALE
Stale NFS file handle.
Definition errno.h:607
#define EINVAL
Invalid argument.
Definition errno.h:142
#define EIO
I/O error.
Definition errno.h:57
#define EBUSY
Device or resource busy.
Definition errno.h:112
#define errno
Error number variable.
Definition errno.h:27
#define ENODEV
No such device.
Definition errno.h:127
uint64_t bind(fd_t source, const char *mountpoint)
System call for binding a file descriptor to a mountpoint.
Definition bind.c:5
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
#define CONTAINER_OF(ptr, type, member)
Container of macro.
__UINT64_TYPE__ fd_t
A file descriptor.
Definition fd_t.h:12
#define CONTAINER_OF_SAFE(ptr, type, member)
Safe container of macro.
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static process_t kernelProcess
Definition process.c:28
#define atomic_load(object)
Definition stdatomic.h:288
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
Directory entry structure.
Definition dentry.h:83
dentry_id_t id
Definition dentry.h:85
superblock_t * superblock
Definition dentry.h:92
File structure.
Definition file.h:37
path_t path
Definition file.h:42
Filesystem structure, represents a filesystem type, e.g. fat32, ramfs, sysfs, etc.
Definition vfs.h:45
dentry_t *(* mount)(filesystem_t *fs, const char *devName, void *private)
Definition vfs.h:48
Map entry structure.
Definition map.h:57
Map key stucture.
Definition map.h:45
uint64_t capacity
Definition map.h:78
map_entry_t ** entries
Definition map.h:77
Mount structure.
Definition mount.h:36
superblock_t * superblock
The superblock of the mounted filesystem.
Definition mount.h:40
map_entry_t mapEntry
Definition mount.h:39
dentry_t * root
The root dentry of the mounted filesystem.
Definition mount.h:42
mount_id_t id
Definition mount.h:38
map_t mountPoints
Definition namespace.h:39
process_t * owner
The process that owns this namespace, will not take a reference.
Definition namespace.h:42
rwlock_t lock
Definition namespace.h:40
namespace_t * parent
Definition namespace.h:41
mount_t * rootMount
The root mount of the namespace, will be inherited from the parent namespace.
Definition namespace.h:43
Path structure.
Definition path.h:110
mount_t * mount
Definition path.h:111
dentry_t * dentry
Definition path.h:112
Pathname structure.
Definition path.h:122
Process structure.
Definition process.h:53
vfs_ctx_t vfsCtx
Definition process.h:61
Thread of execution structure.
Definition thread.h:55
process_t * process
The parent process that the thread executes within.
Definition thread.h:57