refactor: add a simple ramfs for rootfs. Twifs should have more specific job in future.
[lunaix-os.git] / lunaix-os / includes / lunaix / fs.h
1 #ifndef __LUNAIX_VFS_H
2 #define __LUNAIX_VFS_H
3
4 #include <lunaix/clock.h>
5 #include <lunaix/device.h>
6 #include <lunaix/ds/btrie.h>
7 #include <lunaix/ds/hashtable.h>
8 #include <lunaix/ds/hstr.h>
9 #include <lunaix/ds/llist.h>
10 #include <lunaix/ds/lru.h>
11 #include <lunaix/ds/mutex.h>
12 #include <lunaix/status.h>
13 #include <stdatomic.h>
14
15 #define VFS_NAME_MAXLEN 128
16 #define VFS_MAX_FD 32
17
18 #define VFS_IFDIR 0x1
19 #define VFS_IFFILE 0x2
20 #define VFS_IFSEQDEV 0x4
21 #define VFS_IFVOLDEV 0x8
22 #define VFS_IFSYMLINK 0x16
23
24 #define VFS_WALK_MKPARENT 0x1
25 #define VFS_WALK_FSRELATIVE 0x2
26 #define VFS_WALK_PARENT 0x4
27 #define VFS_WALK_NOFOLLOW 0x8
28
29 #define VFS_HASHTABLE_BITS 10
30 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
31 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
32 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
33
34 #define FSTYPE_ROFS 0x1
35
36 #define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
37 #define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; })
38
39 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
40
41 #define VFS_VALID_CHAR(chr)                                                    \
42     (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') ||       \
43      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
44      (chr) == '-')
45
46 typedef uint32_t inode_t;
47
48 struct v_dnode;
49 struct v_inode;
50 struct v_superblock;
51 struct v_file;
52 struct v_file_ops;
53 struct v_inode_ops;
54 struct v_fd;
55 struct pcache;
56
57 extern struct v_file_ops default_file_ops;
58 extern struct v_inode_ops default_inode_ops;
59
60 extern struct hstr vfs_ddot;
61 extern struct hstr vfs_dot;
62 extern struct v_dnode* vfs_sysroot;
63
64 struct filesystem
65 {
66     struct hlist_node fs_list;
67     struct hstr fs_name;
68     uint32_t types;
69     int fs_id;
70     int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
71     int (*unmount)(struct v_superblock* vsb);
72 };
73
74 struct v_superblock
75 {
76     struct llist_header sb_list;
77     struct device* dev;
78     struct v_dnode* root;
79     struct filesystem* fs;
80     uint32_t iobuf_size;
81     struct hbucket* i_cache;
82     struct
83     {
84         uint32_t (*read_capacity)(struct v_superblock* vsb);
85         uint32_t (*read_usage)(struct v_superblock* vsb);
86         void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
87     } ops;
88 };
89
90 struct dir_context
91 {
92     int index;
93     void* cb_data;
94     void (*read_complete_callback)(struct dir_context* dctx,
95                                    const char* name,
96                                    const int len,
97                                    const int dtype);
98 };
99
100 struct v_file_ops
101 {
102     int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
103     int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
104     int (*readdir)(struct v_file* file, struct dir_context* dctx);
105     int (*seek)(struct v_inode* inode, size_t offset);
106     int (*close)(struct v_file* file);
107     int (*sync)(struct v_file* file);
108 };
109
110 struct v_inode_ops
111 {
112     int (*create)(struct v_inode* this, struct v_dnode* dnode);
113     int (*open)(struct v_inode* this, struct v_file* file);
114     int (*sync)(struct v_inode* this);
115     int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
116     int (*rmdir)(struct v_inode* this, struct v_dnode* dir);
117     int (*unlink)(struct v_inode* this);
118     int (*link)(struct v_inode* this, struct v_dnode* new_name);
119     int (*read_symlink)(struct v_inode* this, const char** path_out);
120     int (*set_symlink)(struct v_inode* this, const char* target);
121     int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
122     int (*rename)(struct v_inode* from_inode,
123                   struct v_dnode* from_dnode,
124                   struct v_dnode* to_dnode);
125 };
126
127 struct v_file
128 {
129     struct v_inode* inode;
130     struct v_dnode* dnode;
131     struct llist_header* f_list;
132     uint32_t f_pos;
133     atomic_ulong ref_count;
134     struct v_file_ops* ops; // for caching
135 };
136
137 struct v_fd
138 {
139     struct v_file* file;
140     int flags;
141 };
142
143 struct v_inode
144 {
145     inode_t id;
146     mutex_t lock;
147     uint32_t itype;
148     time_t ctime;
149     time_t mtime;
150     time_t atime;
151     lba_t lb_addr;
152     uint32_t open_count;
153     uint32_t link_count;
154     uint32_t lb_usage;
155     uint32_t fsize;
156     struct v_superblock* sb;
157     struct hlist_node hash_list;
158     struct lru_node lru;
159     struct pcache* pg_cache;
160     void* data; // 允许底层FS绑定他的一些专有数据
161     struct v_inode_ops* ops;
162     struct v_file_ops* default_fops;
163 };
164
165 struct v_mount
166 {
167     mutex_t lock;
168     struct llist_header list;
169     struct llist_header submnts;
170     struct llist_header sibmnts;
171     struct v_mount* parent;
172     struct v_dnode* mnt_point;
173     struct v_superblock* super_block;
174     uint32_t busy_counter;
175 };
176
177 struct v_dnode
178 {
179     mutex_t lock; // sync the path walking
180     struct lru_node lru;
181     struct hstr name;
182     struct v_inode* inode;
183     struct v_dnode* parent;
184     struct hlist_node hash_list;
185     struct llist_header children;
186     struct llist_header siblings;
187     struct v_superblock* super_block;
188     struct v_mount* mnt;
189     atomic_ulong ref_count;
190
191     void* data;
192 };
193
194 struct v_fdtable
195 {
196     struct v_fd* fds[VFS_MAX_FD];
197 };
198
199 struct pcache
200 {
201     struct v_inode* master;
202     struct btrie tree;
203     struct llist_header pages;
204     struct llist_header dirty;
205     uint32_t n_dirty;
206     uint32_t n_pages;
207 };
208
209 struct pcache_pg
210 {
211     struct llist_header pg_list;
212     struct llist_header dirty_list;
213     struct lru_node lru;
214     struct pcache* holder;
215     void* pg;
216     uint32_t flags;
217     uint32_t fpos;
218 };
219 /* --- file system manager --- */
220 void
221 fsm_init();
222
223 void
224 fsm_register_all();
225
226 struct filesystem*
227 fsm_new_fs(char* name, size_t name_len);
228
229 void
230 fsm_register(struct filesystem* fs);
231
232 struct filesystem*
233 fsm_get(const char* fs_name);
234
235 void
236 vfs_init();
237
238 struct v_dnode*
239 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
240
241 void
242 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
243
244 int
245 vfs_walk(struct v_dnode* start,
246          const char* path,
247          struct v_dnode** dentry,
248          struct hstr* component,
249          int walk_options);
250
251 int
252 vfs_mount(const char* target, const char* fs_name, struct device* device);
253
254 int
255 vfs_unmount(const char* target);
256
257 int
258 vfs_mount_at(const char* fs_name,
259              struct device* device,
260              struct v_dnode* mnt_point);
261
262 int
263 vfs_unmount_at(struct v_dnode* mnt_point);
264
265 int
266 vfs_mkdir(const char* path, struct v_dnode** dentry);
267
268 int
269 vfs_open(struct v_dnode* dnode, struct v_file** file);
270
271 int
272 vfs_close(struct v_file* file);
273
274 int
275 vfs_fsync(struct v_file* file);
276
277 void
278 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
279
280 struct v_superblock*
281 vfs_sb_alloc();
282
283 void
284 vfs_sb_free(struct v_superblock* sb);
285
286 struct v_dnode*
287 vfs_d_alloc();
288
289 void
290 vfs_d_free(struct v_dnode* dnode);
291
292 struct v_inode*
293 vfs_i_find(struct v_superblock* sb, uint32_t i_id);
294
295 void
296 vfs_i_addhash(struct v_inode* inode);
297
298 struct v_inode*
299 vfs_i_alloc(struct v_superblock* sb);
300
301 void
302 vfs_i_free(struct v_inode* inode);
303
304 int
305 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
306
307 void
308 pcache_init(struct pcache* pcache);
309
310 void
311 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
312
313 struct pcache_pg*
314 pcache_new_page(struct pcache* pcache, uint32_t index);
315
316 void
317 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
318
319 struct pcache_pg*
320 pcache_get_page(struct pcache* pcache,
321                 uint32_t index,
322                 uint32_t* offset,
323                 struct pcache_pg** page);
324
325 int
326 pcache_write(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos);
327
328 int
329 pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos);
330
331 void
332 pcache_release(struct pcache* pcache);
333
334 int
335 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
336
337 void
338 pcache_commit_all(struct v_inode* inode);
339
340 void
341 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
342
343 /**
344  * @brief 将挂载点标记为繁忙
345  *
346  * @param mnt
347  */
348 void
349 mnt_mkbusy(struct v_mount* mnt);
350
351 /**
352  * @brief 将挂载点标记为清闲
353  *
354  * @param mnt
355  */
356 void
357 mnt_chillax(struct v_mount* mnt);
358
359 int
360 vfs_mount_root(const char* fs_name, struct device* device);
361
362 struct v_mount*
363 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
364
365 int
366 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
367
368 int
369 default_file_write(struct v_inode* inode,
370                    void* buffer,
371                    size_t len,
372                    size_t fpos);
373
374 int
375 default_file_readdir(struct v_file* file, struct dir_context* dctx);
376
377 int
378 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
379
380 int
381 default_inode_rename(struct v_inode* from_inode,
382                      struct v_dnode* from_dnode,
383                      struct v_dnode* to_dnode);
384
385 int
386 default_file_close(struct v_file* file);
387
388 int
389 default_file_seek(struct v_inode* inode, size_t offset);
390
391 int
392 default_inode_open(struct v_inode* this, struct v_file* file);
393
394 int
395 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
396
397 int
398 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
399
400 #endif /* __LUNAIX_VFS_H */