PatchworkOS
Loading...
Searching...
No Matches
sysfs.c
Go to the documentation of this file.
1#include <kernel/fs/sysfs.h>
2
3#include <kernel/fs/dentry.h>
5#include <kernel/fs/vfs.h>
6#include <kernel/log/log.h>
7#include <kernel/log/panic.h>
8#include <kernel/sync/lock.h>
9
10#include <assert.h>
11#include <errno.h>
12#include <stdatomic.h>
13#include <sys/list.h>
14
16
17static mount_t* devMount = NULL;
18
19static file_ops_t dirOps = {
21};
22
26
27typedef struct
28{
31
32static dentry_t* sysfs_mount(filesystem_t* fs, const char* devName, void* private)
33{
34 (void)devName; // Unused
35 (void)private; // Unused
36
38 if (private != NULL)
39 {
40 sysfs_mount_ctx_t* ctx = (sysfs_mount_ctx_t*)private;
42 }
43
45 if (superblock == NULL)
46 {
47 return NULL;
48 }
49 DEREF_DEFER(superblock);
50
51 inode_t* inode = inode_new(superblock, atomic_fetch_add(&newNum, 1), INODE_DIR, NULL, &dirOps);
52 if (inode == NULL)
53 {
54 return NULL;
55 }
56 DEREF_DEFER(inode);
57
58 dentry_t* dentry = dentry_new(superblock, NULL, VFS_ROOT_ENTRY_NAME);
59 if (dentry == NULL)
60 {
61 return NULL;
62 }
63 DEREF_DEFER(dentry);
64
65 if (dentry_make_positive(dentry, inode) == ERR)
66 {
67 return NULL;
68 }
69
70 superblock->root = REF(dentry);
71 return REF(superblock->root);
72}
73
76 .mount = sysfs_mount,
77};
78
79void sysfs_init(void)
80{
81 LOG_INFO("registering sysfs\n");
82 if (vfs_register_fs(&sysfs) == ERR)
83 {
84 panic(NULL, "Failed to register sysfs");
85 }
86
87 devMount = sysfs_mount_new(NULL, "dev", NULL, NULL);
88 if (devMount == NULL)
89 {
90 panic(NULL, "Failed to create /dev filesystem");
91 }
92 LOG_INFO("sysfs initialized\n");
93}
94
96{
97 return REF(devMount->root);
98}
99
100mount_t* sysfs_mount_new(const path_t* parent, const char* name, namespace_t* ns, const superblock_ops_t* superblockOps)
101{
102 if (name == NULL)
103 {
104 errno = EINVAL;
105 return NULL;
106 }
107
108 if (ns == NULL)
109 {
112 ns = &kernelProcess->namespace;
113 }
114
115 if (parent == NULL)
116 {
117 path_t rootPath = PATH_EMPTY;
118 path_set(&rootPath, ns->rootMount, ns->rootMount->root);
119 PATH_DEFER(&rootPath);
120
121 dentry_t* dentry = vfs_get_or_lookup_dentry(&rootPath, name);
122 if (dentry == NULL)
123 {
124 return NULL;
125 }
126 DEREF_DEFER(dentry);
127
128 path_t mountpoint = PATH_EMPTY;
129 path_set(&mountpoint, ns->rootMount, dentry);
130 PATH_DEFER(&mountpoint);
131
132 sysfs_mount_ctx_t ctx = {
134 };
135
136 return namespace_mount(ns, &mountpoint, VFS_DEVICE_NAME_NONE, SYSFS_NAME, &ctx);
137 }
138
139 if (parent->dentry->superblock->fs != &sysfs)
140 {
141 errno = EXDEV;
142 return NULL;
143 }
144
145 inode_t* inode = inode_new(parent->dentry->superblock, atomic_fetch_add(&newNum, 1), INODE_DIR, NULL, &dirOps);
146 if (inode == NULL)
147 {
148 return NULL;
149 }
150 DEREF_DEFER(inode);
151
152 dentry_t* dentry = dentry_new(parent->dentry->superblock, parent->dentry, name);
153 if (dentry == NULL)
154 {
155 return NULL;
156 }
157 DEREF_DEFER(dentry);
158
159 if (dentry_make_positive(dentry, inode) == ERR)
160 {
161 return NULL;
162 }
163
164 sysfs_mount_ctx_t ctx = {
166 };
167
168 path_t mountpoint = PATH_CREATE(parent->mount, dentry);
169 mount_t* mount = namespace_mount(ns, &mountpoint, VFS_DEVICE_NAME_NONE, SYSFS_NAME, &ctx);
170 path_put(&mountpoint);
171 return mount;
172}
173
174dentry_t* sysfs_dir_new(dentry_t* parent, const char* name, const inode_ops_t* inodeOps, void* private)
175{
176 if (name == NULL)
177 {
178 errno = EINVAL;
179 return NULL;
180 }
181
182 if (parent == NULL)
183 {
184 parent = devMount->root;
185 }
186
187 if (parent->superblock->fs != &sysfs)
188 {
189 errno = EXDEV;
190 return NULL;
191 }
192
193 dentry_t* dir = dentry_new(parent->superblock, parent, name);
194 if (dir == NULL)
195 {
196 return NULL;
197 }
198 DEREF_DEFER(dir);
199
200 inode_t* inode = inode_new(parent->superblock, atomic_fetch_add(&newNum, 1), INODE_DIR, inodeOps, &dirOps);
201 if (inode == NULL)
202 {
203 return NULL;
204 }
205 DEREF_DEFER(inode);
206 inode->private = private;
207
208 if (dentry_make_positive(dir, inode) == ERR)
209 {
210 return NULL;
211 }
212
213 return REF(dir);
214}
215
216dentry_t* sysfs_file_new(dentry_t* parent, const char* name, const inode_ops_t* inodeOps, const file_ops_t* fileOps,
217 void* private)
218{
219 if (name == NULL)
220 {
221 errno = EINVAL;
222 return NULL;
223 }
224
225 if (parent == NULL)
226 {
227 parent = devMount->root;
228 }
229
230 if (parent->superblock->fs != &sysfs)
231 {
232 errno = EXDEV;
233 return NULL;
234 }
235
236 dentry_t* file = dentry_new(parent->superblock, parent, name);
237 if (file == NULL)
238 {
239 return NULL;
240 }
242
243 inode_t* inode = inode_new(parent->superblock, atomic_fetch_add(&newNum, 1), INODE_FILE, inodeOps, fileOps);
244 if (inode == NULL)
245 {
246 return NULL;
247 }
248 DEREF_DEFER(inode);
249 inode->private = private;
250
251 if (dentry_make_positive(file, inode) == ERR)
252 {
253 return NULL;
254 }
255
256 return REF(file);
257}
static mount_t * mount
Definition acpi.c:15
#define assert(expression)
Definition assert.h:29
dentry_t * dentry_new(superblock_t *superblock, dentry_t *parent, const char *name)
Create a new dentry.
Definition dentry.c:51
uint64_t dentry_make_positive(dentry_t *dentry, inode_t *inode)
Make a dentry positive by associating it with an inode.
Definition dentry.c:101
uint64_t dentry_generic_getdents(dentry_t *dentry, dirent_t *buffer, uint64_t count, uint64_t *offset, path_flags_t flags)
Helper function for a basic getdents.
Definition dentry.c:195
uint64_t file_generic_seek(file_t *file, int64_t offset, seek_origin_t origin)
Helper function for basic seeking.
Definition file.c:51
inode_t * inode_new(superblock_t *superblock, inode_number_t number, inode_type_t type, const inode_ops_t *ops, const file_ops_t *fileOps)
Create a new inode.
Definition inode.c:42
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
void path_put(path_t *path)
Put a path.
Definition path.c:257
#define PATH_CREATE(inMount, inDentry)
Helper to create a path.
Definition path.h:195
#define PATH_DEFER(path)
Defer path put.
Definition path.h:53
void path_set(path_t *path, mount_t *mount, dentry_t *dentry)
Set a path.
Definition path.c:207
#define PATH_EMPTY
Helper to create an empty path.
Definition path.h:182
superblock_t * superblock_new(const filesystem_t *fs, const char *deviceName, const superblock_ops_t *ops, const dentry_ops_t *dentryOps)
Create a new superblock.
Definition superblock.c:32
uint64_t vfs_register_fs(filesystem_t *fs)
Registers a filesystem.
Definition vfs.c:102
#define VFS_ROOT_ENTRY_NAME
The name of the root entry.
Definition vfs.h:34
#define VFS_DEVICE_NAME_NONE
The name used to indicate no device.
Definition vfs.h:39
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.
Definition vfs.c:227
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:362
#define LOG_INFO(format,...)
Definition log.h:87
process_t * process_get_kernel(void)
Gets the kernel process.
Definition process.c:594
#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 EINVAL
Invalid argument.
Definition errno.h:142
#define EXDEV
Cross-device link.
Definition errno.h:122
#define errno
Error number variable.
Definition errno.h:27
uint64_t inode_number_t
Inode number enum.
Definition io.h:353
@ INODE_FILE
Is a file.
Definition io.h:345
@ INODE_DIR
Is a directory.
Definition io.h:346
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
static dentry_t * file
Definition log_file.c:17
static process_t kernelProcess
Definition process.c:28
static inode_ops_t inodeOps
Definition ramfs.c:220
static file_ops_t fileOps
Definition ramfs.c:99
static superblock_ops_t superblockOps
Definition socket.c:355
#define _Atomic(T)
Definition stdatomic.h:59
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
#define atomic_fetch_add(object, operand)
Definition stdatomic.h:283
Dentry operations structure.
Definition dentry.h:70
uint64_t(* getdents)(dentry_t *dentry, dirent_t *buffer, uint64_t count, uint64_t *offset, path_flags_t flags)
Used to now what is in a directory.
Definition dentry.h:74
Directory entry structure.
Definition dentry.h:83
superblock_t * superblock
Definition dentry.h:92
File operations structure.
Definition file.h:57
uint64_t(* seek)(file_t *file, int64_t offset, seek_origin_t origin)
Definition file.h:63
Filesystem structure, represents a filesystem type, e.g. fat32, ramfs, sysfs, etc.
Definition vfs.h:45
const char * name
Definition vfs.h:47
Inode structure.
Definition inode.h:54
void * private
Definition inode.h:66
Mount structure.
Definition mount.h:36
dentry_t * root
The root dentry of the mounted filesystem.
Definition mount.h:42
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
Process structure.
Definition process.h:53
Superblock operations structure.
Definition superblock.h:70
Superblock structure.
Definition superblock.h:44
const filesystem_t * fs
Definition superblock.h:54
dentry_t * root
Definition superblock.h:51
const superblock_ops_t * superblockOps
Definition sysfs.c:29
static dentry_ops_t dentryOps
Definition sysfs.c:23
mount_t * sysfs_mount_new(const path_t *parent, const char *name, namespace_t *ns, const superblock_ops_t *superblockOps)
Mount a new instance of SysFS.
Definition sysfs.c:100
dentry_t * sysfs_get_dev(void)
Gets the default SysFS directory.
Definition sysfs.c:95
static filesystem_t sysfs
Definition sysfs.c:74
dentry_t * sysfs_dir_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, void *private)
Create a new directory inside a mounted SysFS instance.
Definition sysfs.c:174
dentry_t * sysfs_file_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, const file_ops_t *fileOps, void *private)
Create a new file inside a mounted SysFS instance.
Definition sysfs.c:216
void sysfs_init(void)
Initializes the SysFS.
Definition sysfs.c:79
static dentry_t * sysfs_mount(filesystem_t *fs, const char *devName, void *private)
Definition sysfs.c:32
#define SYSFS_NAME
Definition sysfs.h:22