1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include "defs.h"
13 #include "namei.h"
14 #include <chcore/cpio.h>
15 #include <chcore/ipc.h>
16 #include <chcore/syscall.h>
17
18 #include "../fs_base/fs_wrapper_defs.h"
19 #include "../fs_base/fs_vnode.h"
20 #include <stdlib.h>
21 #include <string.h>
22
23 struct id_manager fidman;
24 struct fid_record fid_records[MAX_NR_FID_RECORDS];
25
26 bool mounted;
27 bool using_page_cache;
28
29 #ifdef TEST_COUNT_PAGE_CACHE
30 struct test_count count;
31 #endif
32
33 struct server_entry *server_entrys[MAX_SERVER_ENTRY_NUM];
34 struct rb_root *fs_vnode_list;
35
tmpfs_load_image(const char * start)36 int tmpfs_load_image(const char *start)
37 {
38 struct cpio_file *f;
39 struct inode *inode;
40 struct dentry *dentry;
41 const char *path;
42 size_t len;
43 int err = 0;
44 ssize_t write_count;
45 struct nameidata nd;
46
47 BUG_ON(start == NULL);
48
49 cpio_init_g_files();
50 cpio_extract(start, "/");
51
52 char *tmp = malloc(MAX_PATH);
53
54 for (f = g_files.head.next; f; f = f->next) {
55 if (!(f->header.c_filesize))
56 continue;
57
58 path = f->name;
59
60 memset(tmp, 0, MAX_PATH);
61 tmp[0] = '/';
62
63 int i_tmp = 1;
64
65 /* skipping '/'s. maybe this is unnecessary */
66 while (*path == '/') {
67 path++;
68 }
69
70 /* copying path to tmp while creating every directory
71 * encountered during the copying process */
72 while (*path) {
73 if (*path == '/') {
74 err = tmpfs_mkdir(tmp, 0);
75 if (err && err != -EEXIST) {
76 goto error;
77 }
78 }
79 tmp[i_tmp++] = *path;
80 path++;
81 }
82
83 if (*(path - 1) == '/') {
84 warn("empty dir in cpio\n");
85 continue;
86 }
87
88 /* create the last non-directory component as a regular file,
89 * simply by calling path_openat() with O_CREAT */
90 err = path_openat(&nd, tmp, O_CREAT, 0, &dentry);
91 if (err) {
92 goto error;
93 }
94
95 inode = dentry->inode;
96
97 len = f->header.c_filesize;
98 write_count = inode->f_ops->write(inode, f->data, len, 0);
99 if (write_count != len) {
100 err = -ENOSPC;
101 goto error;
102 }
103 }
104
105 err = tmpfs_mkdir("/tafs", 0);
106 BUG_ON(err);
107
108 error:
109 free(tmp);
110 cpio_free_g_files();
111 return err;
112 }
113
114 /* init tmpfs root, creating . and .. inside */
init_root(void)115 void init_root(void)
116 {
117 int err;
118 tmpfs_root_dent = malloc(sizeof(struct dentry));
119 assert(tmpfs_root_dent);
120
121 tmpfs_root = tmpfs_inode_init(FS_DIR, 0);
122 assert(tmpfs_root);
123 tmpfs_root_dent->inode = tmpfs_root;
124
125 struct dentry *d_root_dot = tmpfs_root->d_ops->alloc_dentry();
126 assert(!CHCORE_IS_ERR(d_root_dot));
127 err = tmpfs_root->d_ops->add_dentry(tmpfs_root, d_root_dot, ".", 1);
128 assert(!err);
129
130 struct dentry *d_root_dotdot = tmpfs_root->d_ops->alloc_dentry();
131 assert(!CHCORE_IS_ERR(d_root_dotdot));
132 err = tmpfs_root->d_ops->add_dentry(tmpfs_root, d_root_dotdot, "..", 2);
133 assert(!err);
134
135 tmpfs_root->d_ops->link(tmpfs_root, d_root_dot, tmpfs_root);
136 tmpfs_root->d_ops->link(tmpfs_root, d_root_dotdot, tmpfs_root);
137 }
138
init_tmpfs(void)139 static int init_tmpfs(void)
140 {
141 init_root();
142
143 init_id_manager(&fidman, MAX_NR_FID_RECORDS, DEFAULT_INIT_ID);
144 assert(alloc_id(&fidman) == 0);
145
146 init_fs_wrapper();
147
148 /* tmpfs should never use page cache. */
149 using_page_cache = false;
150 BUG_ON(using_page_cache);
151
152 mounted = true;
153
154 return 0;
155 }
156
main(int argc,char * argv[],char * envp[])157 int main(int argc, char *argv[], char *envp[])
158 {
159 init_tmpfs();
160
161 tmpfs_load_image((char *)&__binary_ramdisk_cpio_start);
162
163 info("register server value = %u\n",
164 ipc_register_server_with_destructor(fs_server_dispatch,
165 DEFAULT_CLIENT_REGISTER_HANDLER,
166 fs_server_destructor));
167
168 usys_exit(0);
169 return 0;
170 }
171