4 * @brief RamFS - a file system sit in RAM
8 * @copyright Copyright (c) 2022
11 #include <klibc/string.h>
12 #include <lunaix/fs/api.h>
13 #include <lunaix/fs/ramfs.h>
14 #include <lunaix/mm/valloc.h>
15 #include <lunaix/spike.h>
18 A RAM FS will play a role of being a root.
20 This is an temporary meaure as we don't have any concrete fs
21 yet. In the near future, we will have an ISO-9660 as our first
22 fs and mount our boot medium as root. And similar thing could
23 be done when we have installed our OS into hard disk, in that
24 case, our rootfs will be something like ext2.
26 RamFS vs. TwiFS: Indeed, they are both fs that lives in RAM so
27 there is no foundmental differences. However, TwiFS is designed
28 to be a 'virtual FIlesystem for KERnel space' (FIKER), so other
29 kernel sub-modules can just create node and attach their own
30 implementation of read/write, without brothering to create a
31 full featured concrete filesystem. This particularly useful for
32 kernel state exposure. In Lunaix, TwiFS is summation of procfs,
33 sysfs and kernfs in Linux world.
35 However, there is a smell of bad-design in the concept of TwiFS.
36 Since it tries to integrate too much responsibility. The TwiFS may
37 be replaced by more specific fs in the future.
39 On the other hand, RamFS is designed to be act like a dummy fs
40 that just ensure 'something there at least' and thus provide basic
41 'mountibility' for other fs.
44 static volatile inode_t ino = 0;
46 extern const struct v_inode_ops ramfs_inode_ops;
47 extern const struct v_file_ops ramfs_file_ops;
50 __ramfs_mknod(struct v_dnode* dnode, struct v_inode** nod_out, u32_t flags)
52 struct v_inode* inode = vfs_i_alloc(dnode->super_block);
58 struct ram_inode* rinode = valloc(sizeof(struct ram_inode));
65 rinode->flags = flags;
67 inode->itype = VFS_IFFILE;
69 if ((flags & RAMF_DIR)) {
70 inode->itype |= VFS_IFDIR;
73 if ((flags & RAMF_SYMLINK)) {
74 inode->itype |= VFS_IFSYMLINK;
82 vfs_assign_inode(dnode, inode);
88 ramfs_readdir(struct v_file* file, struct dir_context* dctx)
91 struct v_dnode *pos, *n;
93 if (fsapi_handle_pseudo_dirent(file, dctx)) {
97 llist_for_each(pos, n, &file->dnode->children, siblings)
99 if (i++ >= file->f_pos) {
100 dctx->read_complete_callback(dctx,
103 vfs_get_dtype(pos->inode->itype));
111 ramfs_mkdir(struct v_inode* this, struct v_dnode* dnode)
113 return __ramfs_mknod(dnode, NULL, RAMF_DIR);
117 ramfs_create(struct v_inode* this, struct v_dnode* dnode, unsigned int itype)
119 return __ramfs_mknod(dnode, NULL, RAMF_FILE);
123 ramfs_inode_init(struct v_superblock* vsb, struct v_inode* inode)
126 inode->ops = (struct v_inode_ops*)&ramfs_inode_ops;
127 inode->default_fops = (struct v_file_ops*)&ramfs_file_ops;
131 ramfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
133 vsb->ops.init_inode = ramfs_inode_init;
135 int errno = __ramfs_mknod(mount_point, NULL, RAMF_DIR);
138 fsapi_inode_setaccess(mount_point->inode, FSACL_DEFAULT);
145 ramfs_unmount(struct v_superblock* vsb)
151 ramfs_mksymlink(struct v_inode* this, const char* target)
153 struct ram_inode* rinode = RAM_INODE(this->data);
155 assert(!(rinode->flags & RAMF_SYMLINK));
157 size_t len = strlen(target) + 1;
158 char* symlink = valloc(len);
164 memcpy(symlink, target, len);
166 this->itype = VFS_IFSYMLINK;
167 rinode->flags |= RAMF_SYMLINK;
168 rinode->symlink = symlink;
175 ramfs_read_symlink(struct v_inode* this, const char** path_out)
177 struct ram_inode* rinode = RAM_INODE(this->data);
179 if (!(rinode->flags & RAMF_SYMLINK)) {
183 *path_out = rinode->symlink;
189 ramfs_unlink(struct v_inode* this, struct v_dnode* name)
191 struct ram_inode* rinode = RAM_INODE(this->data);
193 if ((rinode->flags & RAMF_SYMLINK)) {
194 rinode->flags &= ~RAMF_SYMLINK;
195 this->itype &= ~F_SYMLINK;
197 vfree(rinode->symlink);
210 struct filesystem* fs;
211 fs = fsapi_fs_declare("ramfs", FSTYPE_PSEUDO);
213 fsapi_fs_set_mntops(fs, ramfs_mount, ramfs_unmount);
214 fsapi_fs_finalise(fs);
216 EXPORT_FILE_SYSTEM(ramfs, ramfs_init);
218 const struct v_inode_ops ramfs_inode_ops = { .mkdir = ramfs_mkdir,
219 .rmdir = default_inode_rmdir,
221 default_inode_dirlookup,
222 .create = ramfs_create,
223 .open = default_inode_open,
224 .unlink = ramfs_unlink,
225 .set_symlink = ramfs_mksymlink,
226 .read_symlink = ramfs_read_symlink,
227 .rename = default_inode_rename };
229 const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir,
230 .close = default_file_close,
231 .read = default_file_read,
232 .read_page = default_file_read_page,
233 .write = default_file_write,
235 default_file_write_page,
236 .seek = default_file_seek };