1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #include "mos/ipc/memfd.h" |
4 | |
5 | #include "mos/filesystem/dentry.h" |
6 | #include "mos/filesystem/inode.h" |
7 | #include "mos/filesystem/vfs.h" |
8 | #include "mos/filesystem/vfs_types.h" |
9 | #include "mos/filesystem/vfs_utils.h" |
10 | #include "mos/io/io.h" |
11 | #include "mos/misc/setup.h" |
12 | #include "mos/mm/slab_autoinit.h" |
13 | #include "mos/syslog/printk.h" |
14 | |
15 | #include <mos/filesystem/fs_types.h> |
16 | #include <mos_stdlib.h> |
17 | #include <stdio.h> |
18 | |
19 | typedef struct |
20 | { |
21 | int unused; |
22 | } memfd_t; |
23 | |
24 | extern filesystem_t fs_tmpfs; |
25 | |
26 | static slab_t *memfd_slab = NULL; |
27 | SLAB_AUTOINIT("memfd" , memfd_slab, memfd_t); |
28 | |
29 | static dentry_t *memfd_root_dentry = NULL; |
30 | |
31 | static void memfd_file_release(file_t *file) |
32 | { |
33 | dentry_detach(dentry: file->dentry); |
34 | } |
35 | |
36 | static const file_ops_t memfd_file_ops = { |
37 | .read = vfs_generic_read, |
38 | .write = vfs_generic_write, |
39 | .release = memfd_file_release, |
40 | }; |
41 | |
42 | io_t *memfd_create(const char *name) |
43 | { |
44 | memfd_t *memfd = kmalloc(memfd_slab); |
45 | if (!memfd) |
46 | { |
47 | pr_emerg("Failed to allocate memfd" ); |
48 | return ERR_PTR(error: -ENOMEM); |
49 | } |
50 | |
51 | dentry_t *dentry = dentry_get_from_parent(sb: memfd_root_dentry->superblock, parent: memfd_root_dentry, name); |
52 | |
53 | if (!memfd_root_dentry->inode->ops->newfile(memfd_root_dentry->inode, dentry, FILE_TYPE_REGULAR, (PERM_READ | PERM_WRITE) & PERM_OWNER)) |
54 | { |
55 | pr_emerg("Failed to create file for memfd" ); |
56 | kfree(ptr: memfd); |
57 | kfree(ptr: dentry); |
58 | return ERR_PTR(error: -ENOMEM); |
59 | } |
60 | |
61 | file_t *file = vfs_do_open_dentry(entry: dentry, created: true, read: true, write: true, exec: false, truncate: false); |
62 | if (IS_ERR(ptr: file)) |
63 | { |
64 | pr_emerg("Failed to open file for memfd" ); |
65 | kfree(ptr: memfd); |
66 | kfree(ptr: dentry); |
67 | return ERR(ptr: file); |
68 | } |
69 | |
70 | dentry_ref(dentry), dentry_ref(dentry: memfd_root_dentry); |
71 | file->private_data = memfd; |
72 | file->dentry->inode->file_ops = &memfd_file_ops; |
73 | inode_unlink(dir: memfd_root_dentry->inode, dentry: file->dentry); |
74 | return &file->io; |
75 | } |
76 | |
77 | static void memfd_init() |
78 | { |
79 | memfd_root_dentry = fs_tmpfs.mount(&fs_tmpfs, "none" , NULL); |
80 | if (!memfd_root_dentry) |
81 | { |
82 | pr_emerg("Failed to mount memfd filesystem" ); |
83 | return; |
84 | } |
85 | |
86 | memfd_root_dentry->is_mountpoint = true; |
87 | dentry_ref(dentry: memfd_root_dentry); |
88 | dentry_ref(dentry: memfd_root_dentry); |
89 | } |
90 | |
91 | MOS_INIT(VFS, memfd_init); |
92 | |