PatchworkOS  966e257
A non-POSIX operating system.
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>
4#include <kernel/fs/file.h>
6#include <kernel/fs/inode.h>
7#include <kernel/fs/mount.h>
9#include <kernel/fs/path.h>
11#include <kernel/fs/vfs.h>
12#include <kernel/log/log.h>
13#include <kernel/log/panic.h>
14#include <kernel/sched/sched.h>
15#include <kernel/sync/lock.h>
16
17#include <assert.h>
18#include <errno.h>
19#include <stdatomic.h>
20#include <sys/io.h>
21#include <sys/list.h>
22
24
27};
28
32
33typedef struct
34{
37
38static dentry_t* sysfs_mount(filesystem_t* fs, const char* devName, void* private)
39{
40 (void)devName; // Unused
41 (void)private; // Unused
42
44 if (private != NULL)
45 {
46 sysfs_mount_ctx_t* ctx = (sysfs_mount_ctx_t*)private;
48 }
49
51 if (superblock == NULL)
52 {
53 return NULL;
54 }
55 UNREF_DEFER(superblock);
56
57 inode_t* inode = inode_new(superblock, vfs_id_get(), INODE_DIR, NULL, &dirOps);
58 if (inode == NULL)
59 {
60 return NULL;
61 }
62 UNREF_DEFER(inode);
63
64 dentry_t* dentry = dentry_new(superblock, NULL, VFS_ROOT_ENTRY_NAME);
65 if (dentry == NULL)
66 {
67 return NULL;
68 }
69 UNREF_DEFER(dentry);
70
71 dentry_make_positive(dentry, inode);
72
73 superblock->root = REF(dentry);
74 return REF(superblock->root);
75}
76
79 .mount = sysfs_mount,
80};
81
82void sysfs_init(void)
83{
84 LOG_INFO("registering sysfs\n");
86 {
87 panic(NULL, "Failed to register sysfs");
88 }
89
92 if (devMount == NULL)
93 {
94 panic(NULL, "Failed to create /dev filesystem");
95 }
96 LOG_INFO("sysfs initialized\n");
97}
98
100{
101 return REF(devMount->source);
102}
103
104mount_t* sysfs_mount_new(const path_t* parent, const char* name, namespace_t* ns, mount_flags_t flags, mode_t mode,
106{
107 if (name == NULL)
108 {
109 errno = EINVAL;
110 return NULL;
111 }
112
113 if (ns == NULL)
114 {
115 process_t* process = sched_process();
116 ns = &process->ns;
117 }
118
119 if (parent == NULL)
120 {
121 path_t rootPath = PATH_EMPTY;
122 if (namespace_get_root_path(ns, &rootPath) == ERR)
123 {
124 return NULL;
125 }
126 PATH_DEFER(&rootPath);
127
128 dentry_t* dentry = dentry_lookup(&rootPath, name);
129 if (dentry == NULL)
130 {
131 return NULL;
132 }
133 UNREF_DEFER(dentry);
134
135 path_t mountpoint = PATH_CREATE(rootPath.mount, dentry);
136 PATH_DEFER(&mountpoint);
137
138 sysfs_mount_ctx_t ctx = {
140 };
141
142 return namespace_mount(ns, &mountpoint, VFS_DEVICE_NAME_NONE, SYSFS_NAME, flags, mode, &ctx);
143 }
144
145 if (parent->dentry->superblock->fs != &sysfs)
146 {
147 errno = EXDEV;
148 return NULL;
149 }
150
152 if (inode == NULL)
153 {
154 return NULL;
155 }
156 UNREF_DEFER(inode);
157
158 dentry_t* dentry = dentry_new(parent->dentry->superblock, parent->dentry, name);
159 if (dentry == NULL)
160 {
161 return NULL;
162 }
163 UNREF_DEFER(dentry);
164
165 dentry_make_positive(dentry, inode);
166
167 sysfs_mount_ctx_t ctx = {
169 };
170
171 path_t mountpoint = PATH_CREATE(parent->mount, dentry);
172 mount_t* mount = namespace_mount(ns, &mountpoint, VFS_DEVICE_NAME_NONE, SYSFS_NAME, flags, mode, &ctx);
173 path_put(&mountpoint);
174 return mount;
175}
176
177dentry_t* sysfs_dir_new(dentry_t* parent, const char* name, const inode_ops_t* inodeOps, void* private)
178{
179 if (name == NULL)
180 {
181 errno = EINVAL;
182 return NULL;
183 }
184
185 if (parent == NULL)
186 {
187 parent = devMount->source;
188 }
189
190 if (parent->superblock->fs != &sysfs)
191 {
192 errno = EXDEV;
193 return NULL;
194 }
195
196 dentry_t* dir = dentry_new(parent->superblock, parent, name);
197 if (dir == NULL)
198 {
199 return NULL;
200 }
201 UNREF_DEFER(dir);
202
204 if (inode == NULL)
205 {
206 return NULL;
207 }
208 UNREF_DEFER(inode);
209 inode->private = private;
210
211 dentry_make_positive(dir, inode);
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->source;
228 }
229
230 if (parent->superblock->fs != &sysfs)
231 {
232 errno = EXDEV;
233 return NULL;
234 }
235
236 dentry_t* dentry = dentry_new(parent->superblock, parent, name);
237 if (dentry == NULL)
238 {
239 return NULL;
240 }
241 UNREF_DEFER(dentry);
242
244 if (inode == NULL)
245 {
246 return NULL;
247 }
248 UNREF_DEFER(inode);
249 inode->private = private;
250
251 dentry_make_positive(dentry, inode);
252
253 return REF(dentry);
254}
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
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
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
uint64_t file_generic_seek(file_t *file, int64_t offset, seek_origin_t origin)
Helper function for basic seeking.
Definition file.c:92
uint64_t filesystem_register(filesystem_t *fs)
Registers a filesystem.
Definition filesystem.c:40
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:41
uint64_t namespace_get_root_path(namespace_t *ns, path_t *out)
Get the root path of a namespace.
Definition namespace.c:286
mode_t
Path flags and permissions.
Definition path.h:74
void path_put(path_t *path)
Put a path.
Definition path.c:246
#define PATH_CREATE(inMount, inDentry)
Helper to create a path.
Definition path.h:207
#define PATH_DEFER(path)
Defer path put.
Definition path.h:97
#define PATH_EMPTY
Helper to create an empty path.
Definition path.h:194
@ MODE_ALL_PERMS
Definition path.h:87
@ MODE_DIRECTORY
Definition path.h:84
superblock_t * superblock_new(filesystem_t *fs, const char *deviceName, const superblock_ops_t *ops, const dentry_ops_t *dentryOps)
Create a new superblock.
Definition superblock.c:35
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:266
#define LOG_INFO(format,...)
Definition log.h:106
process_t * sched_process(void)
Retrieves the process of the currently running thread.
Definition sched.c:620
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:54
#define REF(ptr)
Increment reference count.
Definition ref.h:65
#define VFS_ROOT_ENTRY_NAME
The name of the root entry.
Definition vfs.h:32
#define VFS_DEVICE_NAME_NONE
The name used to indicate no device.
Definition vfs.h:37
uint64_t vfs_id_get(void)
Generates a new unique ID, to be used for any VFS object.
Definition vfs.c:765
#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
mount_flags_t
Mount flags type.
Definition io.h:488
@ MOUNT_PROPAGATE_PARENT
Propagate the mount to parent namespaces.
Definition io.h:490
@ MOUNT_PROPAGATE_CHILDREN
Propagate the mount to child namespaces.
Definition io.h:491
@ INODE_FILE
Is a file.
Definition io.h:314
@ INODE_DIR
Is a directory.
Definition io.h:315
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
static const path_flag_t flags[]
Definition path.c:42
static inode_ops_t inodeOps
Definition ramfs.c:173
static mount_t * mount
Definition ramfs.c:28
static file_ops_t fileOps
Definition ramfs.c:84
static superblock_ops_t superblockOps
Definition socket.c:353
Dentry operations structure.
Definition dentry.h:72
uint64_t(* getdents)(dentry_t *dentry, dirent_t *buffer, uint64_t count, uint64_t *offset, mode_t mode)
Definition dentry.h:73
Directory entry structure.
Definition dentry.h:84
superblock_t * superblock
Definition dentry.h:93
File operations structure.
Definition file.h:54
uint64_t(* seek)(file_t *file, int64_t offset, seek_origin_t origin)
Definition file.h:60
Filesystem structure, represents a filesystem type, e.g. fat32, ramfs, sysfs, etc.
Definition filesystem.h:31
const char * name
Definition filesystem.h:35
Inode operations structure.
Definition inode.h:82
Inode structure.
Definition inode.h:56
void * private
Definition inode.h:68
Mount structure.
Definition mount.h:44
dentry_t * source
The dentry to appear at target once mounted, usually the root dentry of the mounted filesystem.
Definition mount.h:48
A mount in a namespace.
Path structure.
Definition path.h:125
mount_t * mount
Definition path.h:126
dentry_t * dentry
Definition path.h:127
Process structure.
Definition process.h:205
namespace_t ns
Definition process.h:211
Superblock operations structure.
Definition superblock.h:70
Superblock structure.
Definition superblock.h:44
filesystem_t * fs
Definition superblock.h:54
dentry_t * root
Definition superblock.h:51
const superblock_ops_t * superblockOps
Definition sysfs.c:35
static dentry_ops_t dentryOps
Definition sysfs.c:29
dentry_t * sysfs_get_dev(void)
Gets the default SysFS directory.
Definition sysfs.c:99
static filesystem_t sysfs
Definition sysfs.c:77
mount_t * sysfs_mount_new(const path_t *parent, const char *name, namespace_t *ns, mount_flags_t flags, mode_t mode, const superblock_ops_t *superblockOps)
Mount a new instance of SysFS.
Definition sysfs.c:104
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:177
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:82
static mount_t * devMount
Definition sysfs.c:23
static dentry_t * sysfs_mount(filesystem_t *fs, const char *devName, void *private)
Definition sysfs.c:38
static file_ops_t dirOps
Definition sysfs.c:25
#define SYSFS_NAME
Definition sysfs.h:23