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
19typedef struct
20{
21 int unused;
22} memfd_t;
23
24extern filesystem_t fs_tmpfs;
25
26static slab_t *memfd_slab = NULL;
27SLAB_AUTOINIT("memfd", memfd_slab, memfd_t);
28
29static dentry_t *memfd_root_dentry = NULL;
30
31static void memfd_file_release(file_t *file)
32{
33 dentry_detach(dentry: file->dentry);
34}
35
36static const file_ops_t memfd_file_ops = {
37 .read = vfs_generic_read,
38 .write = vfs_generic_write,
39 .release = memfd_file_release,
40};
41
42io_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
77static 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
91MOS_INIT(VFS, memfd_init);
92