• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef TMPFS_DEFS_H
13 #define TMPFS_DEFS_H
14 
15 #include <chcore/container/hashtable.h>
16 #include <chcore/container/radix.h>
17 #include <chcore/cpio.h>
18 #include <chcore/type.h>
19 #include <chcore/idman.h>
20 #include <stdlib.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/statfs.h>
24 #include <stddef.h>
25 #include <string.h>
26 
27 #define DEBUG 0
28 
29 /*
30  * To track tmpfs memory usage:
31  * 1. Set DEBUG_MEM_USAGE to 1, and rebuild ChCore.
32  *
33  * 2. In ChCore shell, run tmpfs_mem.bin, which will start
34  * recording **any** malloc()s and free()s in tmpfs afterwards.
35  *
36  * !!LIMITATION!!: memory usage in fs_base is **NOT** tracked,
37  * and other modules like IPC will allocate/free memory on behalf of tmpfs,
38  * causing mem tool to blame tmpfs for mem leakage, but this internal
39  * tool won't help in these cases.
40  *
41  * 3. Run a program, for example fs_full_test.bin.
42  * NOTE: the program should do proper cleaning up for its FS operations after
43  * execution. If the program creates a file and does not delete it, it will
44  * appear to be a memory leakage.
45  *
46  * 4. Run tmpfs_mem.bin again, and it will show the memory usage of
47  * tmpfs ever since the first run of tmpfs_mem.bin
48  *
49  * 5. In normal cases (programs executed have cleaned up all the files and dirs
50  * they created during execution), tmpfs_mem.bin will show nothing if no memory
51  * leakage happened.
52  * If the program actually created some files and dirs and did not
53  * clean them up intentionally, then tmpfs_mem.bin show no leakage but may be
54  * legal memory usage to creat and keep all these files.
55  *
56  * NOTE: Used only for debugging tmpfs, the memory tracking tool it self may
57  * incur memory usage. Set to 0 when running tmpfs unit tests or compilation
58  * will fail.
59  */
60 #define DEBUG_MEM_USAGE 0
61 
62 #define DENT_SIZE (1) /* A faked directory entry size */
63 
64 #define MAX_PATH    (4096)
65 #define MAX_SYM_LEN MAX_PATH
66 
67 #define MAX_NR_FID_RECORDS   (1024)
68 #define MAX_DIR_HASH_BUCKETS (1024)
69 
70 /* inode types */
71 #define FS_REG (1)
72 #define FS_DIR (2)
73 #define FS_SYM (3)
74 
75 #define PREFIX         "[tmpfs]"
76 #define info(fmt, ...) printf(PREFIX " " fmt, ##__VA_ARGS__)
77 #if 1
78 #define debug(fmt, ...) \
79     printf(PREFIX "<%s:%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
80 #else
81 #define debug(fmt, ...) \
82     do {                \
83     } while (0)
84 #endif
85 #define warn(fmt, ...)  printf(PREFIX " " fmt, ##__VA_ARGS__)
86 #define error(fmt, ...) printf(PREFIX " " fmt, ##__VA_ARGS__)
87 
88 /* a simple string definition */
89 struct string {
90     char *str;
91     size_t len;
92     u32 hash;
93 };
94 
95 int init_string(struct string *s, const char *name, size_t len);
96 void free_string(struct string *s);
97 
98 struct fid_record {
99     struct inode *inode;
100     u64 flags;
101     off_t offset;
102 };
103 
104 struct inode {
105     bool opened;
106     int type;
107     int nlinks;
108     off_t size;
109     mode_t mode; /* not supported now */
110 
111     /* type-specific file content */
112     union {
113         char *symlink;
114         struct radix data;
115         struct htable dentries;
116     };
117 
118     /* shared behaviour of all inodes */
119     struct base_inode_ops *base_ops;
120 
121     /* type-specific operations */
122     union {
123         struct regfile_ops *f_ops;
124         struct dir_ops *d_ops;
125         struct symlink_ops *sym_ops;
126     };
127 
128     /* other fields used by mmap */
129     struct {
130         bool valid;
131         vaddr_t *array;
132         size_t nr_used; /* Number of entries filled. */
133         size_t size; /* Total capacity. */
134         cap_t translated_pmo_cap; /* PMO cap of translated array. */
135     } aarray;
136 };
137 
138 struct dentry {
139     struct string name;
140     struct inode *inode;
141     struct hlist_node node;
142 };
143 
144 /* Internal operations of different types of inodes */
145 
146 struct base_inode_ops {
147     void (*open)(struct inode *inode);
148     void (*close)(struct inode *inode);
149     void (*dec_nlinks)(struct inode *inode);
150     void (*inc_nlinks)(struct inode *inode);
151     void (*free)(struct inode *inode);
152     void (*stat)(struct inode *inode, struct stat *stat);
153 };
154 
155 struct regfile_ops {
156     ssize_t (*read)(struct inode *reg, char *buff, size_t len, off_t offset);
157     ssize_t (*write)(struct inode *reg, const char *buff, size_t len,
158                      off_t offset);
159     int (*truncate)(struct inode *reg, off_t len);
160     int (*punch_hole)(struct inode *reg, off_t offset, off_t len);
161     int (*collapse_range)(struct inode *reg, off_t offset, off_t len);
162     int (*zero_range)(struct inode *reg, off_t offset, off_t len, mode_t mode);
163     int (*insert_range)(struct inode *reg, off_t offset, off_t len);
164     int (*allocate)(struct inode *reg, off_t offset, off_t len, int keep_size);
165 };
166 
167 struct dir_ops {
168     struct dentry *(*alloc_dentry)();
169     void (*free_dentry)(struct dentry *dentry);
170     int (*add_dentry)(struct inode *dir, struct dentry *dentry, char *name,
171                       size_t len);
172     void (*remove_dentry)(struct inode *dir, struct dentry *dentry);
173     bool (*is_empty)(struct inode *dir);
174     void (*link)(struct inode *dir, struct dentry *dentry, struct inode *inode);
175     void (*unlink)(struct inode *dir, struct dentry *dentry);
176     int (*mkdir)(struct inode *dir, struct dentry *dentry, mode_t mode);
177     int (*rmdir)(struct inode *dir, struct dentry *dentry);
178     void (*rename)(struct inode *old_dir, struct dentry *old_dentry,
179                    struct inode *new_dir, struct dentry *new_dentry);
180     int (*mknod)(struct inode *dir, struct dentry *dentry, mode_t mode,
181                  int type);
182     struct dentry *(*dirlookup)(struct inode *dir, const char *name,
183                                 size_t len);
184     int (*scan)(struct inode *dir, unsigned int start, void *buf, void *end,
185                 int *read_bytes);
186 };
187 
188 struct symlink_ops {
189     ssize_t (*read_link)(struct inode *symlink, char *buff, size_t len);
190     ssize_t (*write_link)(struct inode *symlink, const char *buff, size_t len);
191 };
192 
193 /* internal_ops.c */
194 u64 hash_chars(const char *str, size_t len);
195 struct inode *tmpfs_inode_init(int type, mode_t mode);
196 void tmpfs_fs_stat(struct statfs *statbuf);
197 
198 /* main.c */
199 void init_root(void);
200 
201 /* tmpfs.c */
202 int tmpfs_mkdir(const char *path, mode_t mode);
203 
204 /* tmpfs.c */
205 int tmpfs_mkdir(const char *path, mode_t mode);
206 
207 extern struct inode *tmpfs_root;
208 extern struct dentry *tmpfs_root_dent;
209 extern struct id_manager fidman;
210 extern struct fid_record fid_records[MAX_NR_FID_RECORDS];
211 
212 extern struct {
213     struct cpio_file head;
214     struct cpio_file *tail;
215 } g_files;
216 
217 extern char __binary_ramdisk_cpio_start;
218 
219 #if DEBUG_MEM_USAGE
220 
221 #define DENTRY    0
222 #define STRING    1
223 #define INODE     2
224 #define SYMLINK   3
225 #define DATA_PAGE 4
226 
227 /* 5 types of object will be created in tmpfs */
228 #define RECORD_SIZE 5
229 
230 struct addr_to_size {
231     vaddr_t addr;
232     size_t size;
233     struct list_head node;
234     struct list_head order_list_node;
235 };
236 
237 struct memory_use_msg {
238     /* dentry, string, inode, symlink, data page */
239     char *typename;
240     struct list_head addr_to_size_head;
241 };
242 
243 void tmpfs_get_mem_usage();
244 void tmpfs_revoke_mem_usage(void *addr, int type);
245 void tmpfs_record_mem_usage(void *addr, size_t size, int type);
246 
247 #endif
248 
249 #endif /* TMPFS_DEFS_H */