3 * @author Lunaixsky (zelong56@gmail.com)
4 * @brief TwiFS - A pseudo file system for kernel state exposure.
8 * @copyright Copyright (c) 2022
11 #include <klibc/strfmt.h>
12 #include <klibc/string.h>
13 #include <lunaix/clock.h>
14 #include <lunaix/fs/api.h>
15 #include <lunaix/fs/twifs.h>
16 #include <lunaix/fs/twimap.h>
17 #include <lunaix/mm/cake.h>
18 #include <lunaix/mm/valloc.h>
19 #include <lunaix/spike.h>
21 #include <asm/pagetable.h>
23 static struct twifs_node* fs_root;
24 static struct cake_pile* twi_pile;
25 static volatile u32_t inode_id = 0;
27 extern const struct v_file_ops twifs_file_ops;
28 extern const struct v_inode_ops twifs_inode_ops;
30 static struct twifs_node*
31 __twifs_new_node(struct twifs_node* parent,
32 const char* name, int name_len, u32_t itype)
34 struct twifs_node* node = cake_grab(twi_pile);
35 memset(node, 0, sizeof(*node));
37 strncpy(node->name_val, name, VFS_NAME_MAXLEN);
39 node->name = HSTR(node->name_val, MIN(name_len, VFS_NAME_MAXLEN));
41 node->ino_id = inode_id++;
42 hstr_rehash(&node->name, HSTR_FULL_HASH);
43 llist_init_head(&node->children);
46 llist_append(&parent->children, &node->siblings);
53 __twifs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
55 inode->ops = (struct v_inode_ops*)&twifs_inode_ops;
56 inode->default_fops = (struct v_file_ops*)&twifs_file_ops;
59 // we set default access right to be 0660.
60 // TODO need a way to allow this to be changed
62 fsapi_inode_setaccess(inode, FSACL_DEFAULT);
63 fsapi_inode_setowner(inode, 0, 0);
67 __twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
69 vsb->ops.init_inode = __twifs_init_inode;
71 struct v_inode* inode = vfs_i_alloc(vsb);
76 inode->id = fs_root->ino_id;
77 inode->itype = fs_root->itype;
78 inode->data = fs_root;
81 vfs_assign_inode(mount_point, inode);
86 __twifs_unmount(struct v_superblock* vsb)
92 __twifs_fwrite(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
94 struct twifs_node* twi_node = (struct twifs_node*)inode->data;
95 if (!twi_node || !twi_node->ops.write) {
98 return twi_node->ops.write(inode, buffer, len, fpos);
102 __twifs_fwrite_pg(struct v_inode* inode, void* buffer, size_t fpos)
104 return __twifs_fwrite(inode, buffer, PAGE_SIZE, fpos);
108 __twifs_fread(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
110 struct twifs_node* twi_node = (struct twifs_node*)inode->data;
111 if (!twi_node || !twi_node->ops.read) {
114 return twi_node->ops.read(inode, buffer, len, fpos);
118 __twifs_fread_pg(struct v_inode* inode, void* buffer, size_t fpos)
120 return __twifs_fread(inode, buffer, PAGE_SIZE, fpos);
123 static struct twifs_node*
124 __twifs_get_node(struct twifs_node* parent, struct hstr* name)
129 struct twifs_node *pos, *n;
130 llist_for_each(pos, n, &parent->children, siblings)
132 if (HSTR_EQ(&pos->name, name)) {
140 __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode)
142 struct twifs_node* twi_node = (struct twifs_node*)inode->data;
144 if (!check_directory_node(inode)) {
148 struct twifs_node* twinode = __twifs_get_node(twi_node, &dnode->name);
150 struct v_inode* child_inode = vfs_i_find(inode->sb, twinode->ino_id);
155 if (!(child_inode = vfs_i_alloc(inode->sb))) {
159 child_inode->id = twinode->ino_id;
160 child_inode->itype = twinode->itype;
161 child_inode->data = twinode;
163 if (twinode->acl != -1) {
164 fsapi_inode_setaccess(child_inode, twinode->acl);
167 vfs_i_addhash(child_inode);
170 dnode->data = twinode->data;
171 vfs_assign_inode(dnode, child_inode);
178 __twifs_iterate_dir(struct v_file* file, struct dir_context* dctx)
180 struct twifs_node* twi_node = (struct twifs_node*)(file->inode->data);
181 unsigned int counter = 2;
182 struct twifs_node *pos, *n;
184 if (fsapi_handle_pseudo_dirent(file, dctx)) {
188 llist_for_each(pos, n, &twi_node->children, siblings)
190 if (counter++ >= file->f_pos) {
192 dctx, pos->name.value, pos->name.len, vfs_get_dtype(pos->itype));
201 __twifs_openfile(struct v_inode* inode, struct v_file* file)
203 struct twifs_node* twi_node = (struct twifs_node*)inode->data;
210 static inline struct twifs_node*
211 __twifs_create_node(struct twifs_node* parent,
212 const char* name, int acl)
214 struct twifs_node* twi_node;
218 parent = parent ?: fs_root;
219 twi_node = __twifs_new_node(parent, name, size, F_FILE);
226 __twifs_twimap_file_read(struct v_inode* inode,
227 void* buf, size_t len, size_t fpos)
229 struct twimap* map = twinode_getdata(inode, struct twimap*);
230 return twimap_read(map, buf, len, fpos);
235 twifs_rm_node(struct twifs_node* node)
237 if (check_itype(node->itype, VFS_IFDIR) && !llist_empty(&node->children)) {
240 llist_delete(&node->siblings);
241 cake_release(twi_pile, node);
246 twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args)
248 char buf[VFS_NAME_MAXLEN];
249 size_t len = ksnprintfv(buf, fmt, VFS_NAME_MAXLEN, args);
251 return __twifs_new_node(parent ? parent : fs_root, buf, len, F_FILE);
255 twifs_dir_node(struct twifs_node* parent, const char* fmt, ...)
258 char buf[VFS_NAME_MAXLEN];
259 struct twifs_node* twi_node;
264 len = ksnprintfv(buf, fmt, VFS_NAME_MAXLEN, args);
266 __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFDIR);
268 twi_node->acl = FSACL_aR | FSACL_aX;
277 twifs_basic_node_from(struct twifs_node* parent,
278 struct twifs_export* def, void* data)
280 struct twifs_node* twi_node;
282 twi_node = __twifs_create_node(parent, def->name, def->acl);
283 twi_node->ops = def->ops;
284 twi_node->data = data;
290 twifs_mapped_node_from(struct twifs_node* parent,
291 struct twimap_export* def, void* data)
293 struct twifs_node* twi_node;
296 map_ = twimap_create(data);
297 twi_node = __twifs_create_node(parent, def->name, def->acl);
299 twi_node->data = map_;
300 twi_node->ops.read = __twifs_twimap_file_read;
301 // twi_node->ops.write = __twifs_twimap_file_write;
303 if (def->ops.go_next) {
304 map_->ops.go_next = def->ops.go_next;
307 if (def->ops.reset) {
308 map_->ops.reset = def->ops.reset;
311 map_->ops.read = def->ops.read;
317 twifs_mapping(struct twifs_node* parent,
318 void* data, int acl, const char* fmt, ...)
323 struct twimap* map = twimap_create(data);
324 struct twifs_node* node = twifs_file_node_vargs(parent, fmt, args);
326 node->ops.read = __twifs_twimap_file_read;
334 twifs_register_plugins()
336 ldga_invoke_fn0(twiplugin_inits);
339 const struct v_file_ops twifs_file_ops = { .close = default_file_close,
340 .read = __twifs_fread,
341 .read_page = __twifs_fread_pg,
342 .write = __twifs_fwrite,
343 .write_page = __twifs_fwrite_pg,
344 .readdir = __twifs_iterate_dir };
346 const struct v_inode_ops twifs_inode_ops = { .dir_lookup = __twifs_dirlookup,
347 .mkdir = default_inode_mkdir,
348 .rmdir = default_inode_rmdir,
349 .open = __twifs_openfile };
355 struct filesystem* fs;
356 fs = fsapi_fs_declare("twifs", FSTYPE_PSEUDO | FSTYPE_ROFS);
358 fsapi_fs_set_mntops(fs, __twifs_mount, __twifs_unmount);
359 fsapi_fs_finalise(fs);
361 twi_pile = cake_new_pile("twifs_node", sizeof(struct twifs_node), 1, 0);
362 fs_root = twifs_dir_node(NULL, NULL, 0, 0);
364 EXPORT_FILE_SYSTEM(twifs, twifs_init);