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 */