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