feat: a better boot command line parser
[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/ldga.h>
10 #include <lunaix/ds/llist.h>
11 #include <lunaix/ds/lru.h>
12 #include <lunaix/ds/mutex.h>
13 #include <lunaix/status.h>
14
15 #include <stdatomic.h>
16
17 #include <usr/lunaix/fstypes.h>
18
19 #define VFS_NAME_MAXLEN 128
20 #define VFS_MAX_FD 32
21
22 #define VFS_IFDIR F_DIR
23 #define VFS_IFFILE F_FILE
24 #define VFS_IFDEV (F_DEV | F_FILE)
25 #define VFS_IFSEQDEV (F_SEQDEV | F_FILE)
26 #define VFS_IFVOLDEV (F_VOLDEV | F_FILE)
27 #define VFS_IFSYMLINK (F_SYMLINK | F_FILE)
28
29 #define VFS_DEVFILE(type) ((type) & F_DEV)
30 #define VFS_DEVTYPE(type) ((type) & ((F_SEQDEV | F_VOLDEV) ^ F_DEV))
31
32 // Walk, mkdir if component encountered is non-exists.
33 #define VFS_WALK_MKPARENT 0x1
34
35 // Walk, relative to current FS.
36 #define VFS_WALK_FSRELATIVE 0x2
37
38 /*
39     Terminate the walk on the immediate parent,
40     name of child (last component) is returned through `component`
41 */
42 #define VFS_WALK_PARENT 0x4
43
44 // Do not follow the symbolic link
45 #define VFS_WALK_NOFOLLOW 0x8
46
47 #define VFS_HASHTABLE_BITS 10
48 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
49 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
50 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
51
52 #define VFS_PATH_DELIM '/'
53
54 #define FSTYPE_ROFS 0x1
55
56 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
57
58 #define EXPORT_FILE_SYSTEM(fs_id, init_fn)                                     \
59     export_ldga_el(fs, fs_id, ptr_t, init_fn)
60
61 #define VFS_VALID_CHAR(chr)                                                    \
62     (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') ||       \
63      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
64      (chr) == '-' || (chr) == ':')
65
66 #define unlock_inode(inode) mutex_unlock(&inode->lock)
67 #define lock_inode(inode)                                                      \
68     ({                                                                         \
69         mutex_lock(&inode->lock);                                              \
70         lru_use_one(inode_lru, &inode->lru);                                   \
71     })
72
73 #define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
74 #define lock_dnode(dnode)                                                      \
75     ({                                                                         \
76         mutex_lock(&dnode->lock);                                              \
77         lru_use_one(dnode_lru, &dnode->lru);                                   \
78     })
79
80 typedef u32_t inode_t;
81
82 struct v_dnode;
83 struct v_inode;
84 struct v_superblock;
85 struct v_file;
86 struct v_file_ops;
87 struct v_inode_ops;
88 struct v_fd;
89 struct pcache;
90 struct v_xattr_entry;
91
92 extern struct v_file_ops default_file_ops;
93 extern struct v_inode_ops default_inode_ops;
94
95 extern struct hstr vfs_ddot;
96 extern struct hstr vfs_dot;
97 extern struct v_dnode* vfs_sysroot;
98
99 struct filesystem
100 {
101     struct hlist_node fs_list;
102     struct hstr fs_name;
103     u32_t types;
104     int fs_id;
105     int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
106     int (*unmount)(struct v_superblock* vsb);
107 };
108
109 struct v_superblock
110 {
111     struct llist_header sb_list;
112     struct device* dev;
113     struct v_dnode* root;
114     struct filesystem* fs;
115     struct hbucket* i_cache;
116     void* data;
117     size_t blksize;
118     struct
119     {
120         u32_t (*read_capacity)(struct v_superblock* vsb);
121         u32_t (*read_usage)(struct v_superblock* vsb);
122         void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
123     } ops;
124 };
125
126 struct dir_context
127 {
128     int index;
129     void* cb_data;
130     void (*read_complete_callback)(struct dir_context* dctx,
131                                    const char* name,
132                                    const int len,
133                                    const int dtype);
134 };
135
136 struct v_file_ops
137 {
138     int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
139     int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
140
141     // for operatiosn {write|read}_page, following are true:
142     //  + `len` always equals to PG_SIZE
143     //  + `fpos` always PG_SIZE aligned.
144     // These additional operations allow underlying fs to use more specialized
145     // and optimized code.
146
147     int (*write_page)(struct v_inode* inode, void* pg, size_t fpos);
148     int (*read_page)(struct v_inode* inode, void* pg, size_t fpos);
149
150     int (*readdir)(struct v_file* file, struct dir_context* dctx);
151     int (*seek)(struct v_inode* inode, size_t offset); // optional
152     int (*close)(struct v_file* file);
153     int (*sync)(struct v_file* file);
154 };
155
156 struct v_inode_ops
157 {
158     int (*create)(struct v_inode* this, struct v_dnode* dnode);
159     int (*open)(struct v_inode* this, struct v_file* file);
160     int (*sync)(struct v_inode* this);
161     int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
162     int (*rmdir)(struct v_inode* this, struct v_dnode* dir);
163     int (*unlink)(struct v_inode* this);
164     int (*link)(struct v_inode* this, struct v_dnode* new_name);
165     int (*read_symlink)(struct v_inode* this, const char** path_out);
166     int (*set_symlink)(struct v_inode* this, const char* target);
167     int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
168     int (*rename)(struct v_inode* from_inode,
169                   struct v_dnode* from_dnode,
170                   struct v_dnode* to_dnode);
171     int (*getxattr)(struct v_inode* this,
172                     struct v_xattr_entry* entry); // optional
173     int (*setxattr)(struct v_inode* this,
174                     struct v_xattr_entry* entry); // optional
175     int (*delxattr)(struct v_inode* this,
176                     struct v_xattr_entry* entry); // optional
177 };
178
179 struct v_xattr_entry
180 {
181     struct llist_header entries;
182     struct hstr name;
183     const void* value;
184     size_t len;
185 };
186
187 struct v_file
188 {
189     struct v_inode* inode;
190     struct v_dnode* dnode;
191     struct llist_header* f_list;
192     u32_t f_pos;
193     atomic_ulong ref_count;
194     struct v_file_ops* ops; // for caching
195 };
196
197 struct v_fd
198 {
199     struct v_file* file;
200     int flags;
201 };
202
203 //  [v_inode::aka_nodes]
204 //  how do we invalidate corresponding v_dnodes given the v_inode?
205 /*
206     Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
207     info of every process being accessible via file system. Each process's
208     creation will result a creation of a directory under the root of task fs
209     with it's pid as name. But that dir must delete when process is killed, and
210     such deletion does not mediated by vfs itself, so there is a need of cache
211     syncing.
212     And this is also the case of all ramfs where argumentation to file tree is
213     performed by third party.
214 */
215
216 struct v_inode
217 {
218     inode_t id;
219     mutex_t lock;
220     u32_t itype;
221     time_t ctime;
222     time_t mtime;
223     time_t atime;
224     lba_t lb_addr;
225     u32_t open_count;
226     u32_t link_count;
227     u32_t lb_usage;
228     u32_t fsize;
229     void* data; // 允许底层FS绑定他的一些专有数据
230     struct llist_header aka_dnodes;
231     struct llist_header xattrs;
232     struct v_superblock* sb;
233     struct hlist_node hash_list;
234     struct lru_node lru;
235     struct pcache* pg_cache;
236     struct v_inode_ops* ops;
237     struct v_file_ops* default_fops;
238
239     void (*destruct)(struct v_inode* inode);
240 };
241
242 struct v_mount
243 {
244     mutex_t lock;
245     struct llist_header list;
246     struct llist_header submnts;
247     struct llist_header sibmnts;
248     struct v_mount* parent;
249     struct v_dnode* mnt_point;
250     struct v_superblock* super_block;
251     u32_t busy_counter;
252     int flags;
253 };
254
255 struct v_dnode
256 {
257     mutex_t lock; // sync the path walking
258     struct lru_node lru;
259     struct hstr name;
260     struct v_inode* inode;
261     struct v_dnode* parent;
262     struct hlist_node hash_list;
263     struct llist_header aka_list;
264     struct llist_header children;
265     struct llist_header siblings;
266     struct v_superblock* super_block;
267     struct v_mount* mnt;
268     atomic_ulong ref_count;
269
270     void* data;
271 };
272
273 struct v_fdtable
274 {
275     struct v_fd* fds[VFS_MAX_FD];
276 };
277
278 struct pcache
279 {
280     struct v_inode* master;
281     struct btrie tree;
282     struct llist_header pages;
283     struct llist_header dirty;
284     u32_t n_dirty;
285     u32_t n_pages;
286 };
287
288 struct pcache_pg
289 {
290     struct llist_header pg_list;
291     struct llist_header dirty_list;
292     struct lru_node lru;
293     struct pcache* holder;
294     void* pg;
295     u32_t flags;
296     u32_t fpos;
297     u32_t len;
298 };
299
300 void
301 fsm_init();
302
303 void
304 fsm_register_all();
305
306 struct filesystem*
307 fsm_new_fs(char* name, size_t name_len);
308
309 void
310 fsm_register(struct filesystem* fs);
311
312 struct filesystem*
313 fsm_get(const char* fs_name);
314
315 void
316 vfs_init();
317
318 void
319 vfs_export_attributes();
320
321 struct v_dnode*
322 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
323
324 void
325 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
326
327 void
328 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
329
330 void
331 vfs_dcache_remove(struct v_dnode* dnode);
332
333 int
334 vfs_walk(struct v_dnode* start,
335          const char* path,
336          struct v_dnode** dentry,
337          struct hstr* component,
338          int walk_options);
339
340 int
341 vfs_walk_proc(const char* path,
342               struct v_dnode** dentry,
343               struct hstr* component,
344               int options);
345
346 int
347 vfs_mount(const char* target,
348           const char* fs_name,
349           struct device* device,
350           int options);
351
352 int
353 vfs_unmount(const char* target);
354
355 int
356 vfs_mount_at(const char* fs_name,
357              struct device* device,
358              struct v_dnode* mnt_point,
359              int options);
360
361 int
362 vfs_unmount_at(struct v_dnode* mnt_point);
363
364 int
365 vfs_mkdir(const char* path, struct v_dnode** dentry);
366
367 int
368 vfs_open(struct v_dnode* dnode, struct v_file** file);
369
370 int
371 vfs_pclose(struct v_file* file, pid_t pid);
372
373 int
374 vfs_close(struct v_file* file);
375
376 void
377 vfs_free_fd(struct v_fd* fd);
378
379 int
380 vfs_fsync(struct v_file* file);
381
382 void
383 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
384
385 struct v_superblock*
386 vfs_sb_alloc();
387
388 void
389 vfs_sb_free(struct v_superblock* sb);
390
391 struct v_dnode*
392 vfs_d_alloc();
393
394 void
395 vfs_d_free(struct v_dnode* dnode);
396
397 struct v_inode*
398 vfs_i_find(struct v_superblock* sb, u32_t i_id);
399
400 void
401 vfs_i_addhash(struct v_inode* inode);
402
403 struct v_inode*
404 vfs_i_alloc(struct v_superblock* sb);
405
406 void
407 vfs_i_free(struct v_inode* inode);
408
409 int
410 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
411
412 int
413 vfs_getfd(int fd, struct v_fd** fd_s);
414
415 int
416 vfs_get_dtype(int itype);
417
418 void
419 vfs_ref_dnode(struct v_dnode* dnode);
420
421 void
422 vfs_ref_file(struct v_file* file);
423
424 void
425 vfs_unref_dnode(struct v_dnode* dnode);
426
427 int
428 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
429
430 void
431 pcache_init(struct pcache* pcache);
432
433 void
434 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
435
436 struct pcache_pg*
437 pcache_new_page(struct pcache* pcache, u32_t index);
438
439 void
440 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
441
442 int
443 pcache_get_page(struct pcache* pcache,
444                 u32_t index,
445                 u32_t* offset,
446                 struct pcache_pg** page);
447
448 int
449 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
450
451 int
452 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
453
454 void
455 pcache_release(struct pcache* pcache);
456
457 int
458 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
459
460 void
461 pcache_commit_all(struct v_inode* inode);
462
463 void
464 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
465
466 /**
467  * @brief 将挂载点标记为繁忙
468  *
469  * @param mnt
470  */
471 void
472 mnt_mkbusy(struct v_mount* mnt);
473
474 /**
475  * @brief 将挂载点标记为清闲
476  *
477  * @param mnt
478  */
479 void
480 mnt_chillax(struct v_mount* mnt);
481
482 int
483 vfs_mount_root(const char* fs_name, struct device* device);
484
485 struct v_mount*
486 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
487
488 int
489 vfs_check_writable(struct v_dnode* dnode);
490
491 int
492 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
493
494 int
495 default_file_write(struct v_inode* inode,
496                    void* buffer,
497                    size_t len,
498                    size_t fpos);
499
500 int
501 default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
502
503 int
504 default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
505
506 int
507 default_file_readdir(struct v_file* file, struct dir_context* dctx);
508
509 int
510 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
511
512 int
513 default_inode_rename(struct v_inode* from_inode,
514                      struct v_dnode* from_dnode,
515                      struct v_dnode* to_dnode);
516
517 int
518 default_file_close(struct v_file* file);
519
520 int
521 default_file_seek(struct v_inode* inode, size_t offset);
522
523 int
524 default_inode_open(struct v_inode* this, struct v_file* file);
525
526 int
527 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
528
529 int
530 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
531
532 struct v_xattr_entry*
533 xattr_new(struct hstr* name);
534
535 struct v_xattr_entry*
536 xattr_getcache(struct v_inode* inode, struct hstr* name);
537
538 void
539 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
540
541 #endif /* __LUNAIX_VFS_H */