a33b1d0fed3c9f0c0123d2723d1dcb2b228b9ccc
[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 #include <lunaix/spike.h>
15 #include <lunaix/bcache.h>
16
17 #include <stdatomic.h>
18
19 #include <usr/lunaix/fstypes.h>
20
21 #define VFS_NAME_MAXLEN 128
22 #define VFS_MAX_FD 32
23
24 #define VFS_IFFILE       F_FILE
25 #define VFS_IFDIR       (F_FILE | F_DIR    )
26 #define VFS_IFDEV       (F_FILE | F_DEV    )
27 #define VFS_IFSYMLINK   (F_FILE | F_SYMLINK)
28 #define VFS_IFVOLDEV    (F_FILE | F_SVDEV  )
29 #define VFS_IFSEQDEV    VFS_IFDEV
30
31 // Walk, mkdir if component encountered is non-exists.
32 #define VFS_WALK_MKPARENT 0x1
33
34 // Walk, relative to current FS.
35 #define VFS_WALK_FSRELATIVE 0x2
36
37 /*
38     Terminate the walk on the immediate parent,
39     name of child (last component) is returned through `component`
40 */
41 #define VFS_WALK_PARENT 0x4
42
43 // Do not follow the symbolic link
44 #define VFS_WALK_NOFOLLOW 0x8
45
46 #define VFS_HASHTABLE_BITS 10
47 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
48 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
49 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
50
51 #define VFS_PATH_DELIM '/'
52
53 #define FSTYPE_ROFS     0b00000001
54 #define FSTYPE_PSEUDO   0x00000010
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 #define assert_fs(cond) assert_p(cond, "FS")
81 #define fail_fs(msg) fail_p(msg, "FS")
82
83 typedef u32_t inode_t;
84
85 struct v_dnode;
86 struct v_inode;
87 struct v_superblock;
88 struct v_file;
89 struct v_file_ops;
90 struct v_inode_ops;
91 struct v_fd;
92 struct pcache;
93 struct v_xattr_entry;
94
95 extern struct v_file_ops default_file_ops;
96 extern struct v_inode_ops default_inode_ops;
97
98 extern struct hstr vfs_ddot;
99 extern struct hstr vfs_dot;
100 extern struct v_dnode* vfs_sysroot;
101
102 typedef int (*mntops_mnt)(struct v_superblock* vsb, struct v_dnode* mount_point);
103 typedef int (*mntops_umnt)(struct v_superblock* vsb);
104
105 struct filesystem
106 {
107     struct llist_header fs_flat;
108     struct hlist_node fs_list;
109     struct hstr fs_name;
110     u32_t types;
111     int fs_id;
112     mntops_mnt mount;
113     mntops_umnt unmount;
114 };
115
116 struct fs_iter
117 {
118     struct filesystem* fs;
119 };
120
121 struct v_superblock
122 {
123     struct llist_header sb_list;
124     struct device* dev;
125     struct v_dnode* root;
126     struct filesystem* fs;
127     struct blkbuf_cache* blks;
128     struct hbucket* i_cache;
129     void* data;
130     unsigned int ref_count;
131     size_t blksize;
132     struct
133     {
134         size_t (*read_capacity)(struct v_superblock* vsb);
135         size_t (*read_usage)(struct v_superblock* vsb);
136         void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
137         void (*release)(struct v_superblock* vsb);
138     } ops;
139 };
140
141 struct dir_context
142 {
143     void* cb_data;
144     void (*read_complete_callback)(struct dir_context* dctx,
145                                    const char* name,
146                                    const int len,
147                                    const int dtype);
148 };
149
150 struct v_file_ops
151 {
152     int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
153     int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
154
155     // for operatiosn {write|read}_page, following are true:
156     //  + `len` always equals to PG_SIZE
157     //  + `fpos` always PG_SIZE aligned.
158     // These additional operations allow underlying fs to use more specialized
159     // and optimized code.
160
161     int (*write_page)(struct v_inode* inode, void* pg, size_t fpos);
162     int (*read_page)(struct v_inode* inode, void* pg, size_t fpos);
163
164     int (*readdir)(struct v_file* file, struct dir_context* dctx);
165     int (*seek)(struct v_file* file, size_t offset);
166     int (*close)(struct v_file* file);
167     int (*sync)(struct v_file* file);
168 };
169
170 struct v_inode_ops
171 {
172     int (*create)(struct v_inode* this, struct v_dnode* dnode, 
173                   unsigned int itype);
174     
175     int (*open)(struct v_inode* this, struct v_file* file);
176     int (*sync)(struct v_inode* this);
177
178     int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
179     int (*rmdir)(struct v_inode* this, struct v_dnode* dnode);
180     int (*unlink)(struct v_inode* this, struct v_dnode* name);
181     int (*link)(struct v_inode* this, struct v_dnode* new_name);
182
183     int (*read_symlink)(struct v_inode* this, const char** path_out);
184     int (*set_symlink)(struct v_inode* this, const char* target);
185     
186     int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
187
188     int (*rename)(struct v_inode* from_inode,
189                   struct v_dnode* from_dnode,
190                   struct v_dnode* to_dnode);
191
192     int (*getxattr)(struct v_inode* this,
193                     struct v_xattr_entry* entry); // optional
194     int (*setxattr)(struct v_inode* this,
195                     struct v_xattr_entry* entry); // optional
196     int (*delxattr)(struct v_inode* this,
197                     struct v_xattr_entry* entry); // optional
198 };
199
200 struct v_xattr_entry
201 {
202     struct llist_header entries;
203     struct hstr name;
204     const void* value;
205     size_t len;
206 };
207
208 struct v_file
209 {
210     struct v_inode* inode;
211     struct v_dnode* dnode;
212     struct llist_header* f_list;
213     u32_t f_pos;
214     atomic_ulong ref_count;
215     void* data;
216     struct v_file_ops* ops; // for caching
217 };
218
219 struct v_fd
220 {
221     struct v_file* file;
222     int flags;
223 };
224
225 //  [v_inode::aka_nodes]
226 //  how do we invalidate corresponding v_dnodes given the v_inode?
227 /*
228     Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
229     info of every process being accessible via file system. Each process's
230     creation will result a creation of a directory under the root of task fs
231     with it's pid as name. But that dir must delete when process is killed, and
232     such deletion does not mediated by vfs itself, so there is a need of cache
233     syncing.
234     And this is also the case of all ramfs where argumentation to file tree is
235     performed by third party.
236 */
237
238 struct v_inode
239 {
240     inode_t id;
241     mutex_t lock;
242     u32_t itype;
243     time_t ctime;
244     time_t mtime;
245     time_t atime;
246     lba_t lb_addr;
247     u32_t open_count;
248     u32_t link_count;
249     u32_t lb_usage;
250     u32_t fsize;
251     void* data; // 允许底层FS绑定他的一些专有数据
252     struct llist_header aka_dnodes;
253     struct llist_header xattrs;
254     struct v_superblock* sb;
255     struct hlist_node hash_list;
256     struct lru_node lru;
257     struct pcache* pg_cache;
258     struct v_inode_ops* ops;
259     struct v_file_ops* default_fops;
260
261     void (*destruct)(struct v_inode* inode);
262 };
263
264 struct v_mount
265 {
266     mutex_t lock;
267     struct llist_header list;
268     struct llist_header submnts;
269     struct llist_header sibmnts;
270     struct v_mount* parent;
271     struct v_dnode* mnt_point;
272     struct v_superblock* super_block;
273     u32_t busy_counter;
274     int flags;
275 };
276
277 struct v_dnode
278 {
279     mutex_t lock; // sync the path walking
280     struct lru_node lru;
281     struct hstr name;
282     struct v_inode* inode;
283     struct v_dnode* parent;
284     struct hlist_node hash_list;
285     struct llist_header aka_list;
286     struct llist_header children;
287     struct llist_header siblings;
288     struct v_superblock* super_block;
289     struct v_mount* mnt;
290     atomic_ulong ref_count;
291
292     void* data;
293
294     void (*destruct)(struct v_dnode* dnode);
295 };
296
297 struct v_fdtable
298 {
299     struct v_fd* fds[VFS_MAX_FD];
300 };
301
302 struct pcache
303 {
304     struct v_inode* master;
305     struct bcache cache;
306     struct llist_header dirty;
307     u32_t n_dirty;
308     u32_t n_pages;
309 };
310
311 struct pcache_pg
312 {
313     struct llist_header dirty_list;
314
315     union {
316         struct {
317             bool dirty:1;
318         };
319         u32_t flags;
320     };
321
322     void* data;
323     unsigned int index;
324 };
325
326 static inline bool
327 check_itype_any(struct v_inode* inode, unsigned int type_mask)
328 {
329     return !!(inode->itype & type_mask) || !type_mask;
330 }
331
332 void
333 fsm_init();
334
335 void
336 fsm_register_all();
337
338 struct filesystem*
339 fsm_new_fs(char* name, size_t name_len);
340
341 void
342 fsm_register(struct filesystem* fs);
343
344 struct filesystem*
345 fsm_get(const char* fs_name);
346
347 void
348 fsm_itbegin(struct fs_iter* iterator);
349
350 bool
351 fsm_itnext(struct fs_iter* iterator);
352
353 static inline void
354 fsm_itend(struct fs_iter* iterator)
355 {
356     iterator->fs = NULL;
357 }
358
359 void
360 vfs_init();
361
362 void
363 vfs_export_attributes();
364
365 struct v_dnode*
366 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
367
368 void
369 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
370
371 void
372 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
373
374 void
375 vfs_dcache_remove(struct v_dnode* dnode);
376
377 int
378 vfs_walk(struct v_dnode* start,
379          const char* path,
380          struct v_dnode** dentry,
381          struct hstr* component,
382          int walk_options);
383
384 int
385 vfs_walk_proc(const char* path,
386               struct v_dnode** dentry,
387               struct hstr* component,
388               int options);
389
390 int
391 vfs_mount(const char* target,
392           const char* fs_name,
393           struct device* device,
394           int options);
395
396 int
397 vfs_unmount(const char* target);
398
399 int
400 vfs_mount_at(const char* fs_name,
401              struct device* device,
402              struct v_dnode* mnt_point,
403              int options);
404
405 int
406 vfs_unmount_at(struct v_dnode* mnt_point);
407
408 int
409 vfs_mkdir(const char* path, struct v_dnode** dentry);
410
411 int
412 vfs_open(struct v_dnode* dnode, struct v_file** file);
413
414 int
415 vfs_pclose(struct v_file* file, pid_t pid);
416
417 int
418 vfs_close(struct v_file* file);
419
420 void
421 vfs_free_fd(struct v_fd* fd);
422
423 int
424 vfs_fsync(struct v_file* file);
425
426 void
427 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
428
429 struct v_superblock*
430 vfs_sb_alloc();
431
432 void
433 vfs_sb_free(struct v_superblock* sb);
434
435 void
436 vfs_sb_ref(struct v_superblock* sb);
437
438 #define vfs_assign_sb(sb_accessor, sb)      \
439     ({                                      \
440         if (sb_accessor) {                \
441             vfs_sb_free(sb_accessor);       \
442         }                                   \
443         vfs_sb_ref(((sb_accessor) = (sb))); \
444     })
445
446 static inline void
447 vfs_i_assign_sb(struct v_inode* inode, struct v_superblock* sb)
448 {
449     vfs_assign_sb(inode->sb, sb);
450 }
451
452 static inline void
453 vfs_d_assign_sb(struct v_dnode* dnode, struct v_superblock* sb)
454 {
455     vfs_assign_sb(dnode->super_block, sb);
456 }
457
458 static inline void
459 vfs_vmnt_assign_sb(struct v_mount* vmnt, struct v_superblock* sb)
460 {
461     vfs_assign_sb(vmnt->super_block, sb);
462 }
463
464 struct v_dnode*
465 vfs_d_alloc();
466
467 void
468 vfs_d_free(struct v_dnode* dnode);
469
470 struct v_inode*
471 vfs_i_find(struct v_superblock* sb, u32_t i_id);
472
473 void
474 vfs_i_addhash(struct v_inode* inode);
475
476 struct v_inode*
477 vfs_i_alloc(struct v_superblock* sb);
478
479 void
480 vfs_i_free(struct v_inode* inode);
481
482 int
483 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
484
485 int
486 vfs_getfd(int fd, struct v_fd** fd_s);
487
488 int
489 vfs_get_dtype(int itype);
490
491 void
492 vfs_ref_dnode(struct v_dnode* dnode);
493
494 void
495 vfs_ref_file(struct v_file* file);
496
497 void
498 vfs_unref_dnode(struct v_dnode* dnode);
499
500 int
501 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
502
503 void
504 pcache_init(struct pcache* pcache);
505
506 int
507 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
508
509 int
510 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
511
512 void
513 pcache_release(struct pcache* pcache);
514
515 int
516 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
517
518 void
519 pcache_commit_all(struct v_inode* inode);
520
521 void
522 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
523
524 /**
525  * @brief 将挂载点标记为繁忙
526  *
527  * @param mnt
528  */
529 void
530 mnt_mkbusy(struct v_mount* mnt);
531
532 /**
533  * @brief 将挂载点标记为清闲
534  *
535  * @param mnt
536  */
537 void
538 mnt_chillax(struct v_mount* mnt);
539
540 int
541 vfs_mount_root(const char* fs_name, struct device* device);
542
543 struct v_mount*
544 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
545
546 int
547 vfs_check_writable(struct v_dnode* dnode);
548
549 int
550 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
551
552 int
553 default_file_write(struct v_inode* inode,
554                    void* buffer,
555                    size_t len,
556                    size_t fpos);
557
558 int
559 default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
560
561 int
562 default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
563
564 int
565 default_file_readdir(struct v_file* file, struct dir_context* dctx);
566
567 int
568 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
569
570 int
571 default_inode_rename(struct v_inode* from_inode,
572                      struct v_dnode* from_dnode,
573                      struct v_dnode* to_dnode);
574
575 int
576 default_file_close(struct v_file* file);
577
578 int
579 default_file_seek(struct v_file* file, size_t offset);
580
581 int
582 default_inode_open(struct v_inode* this, struct v_file* file);
583
584 int
585 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
586
587 int
588 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
589
590 struct v_xattr_entry*
591 xattr_new(struct hstr* name);
592
593 struct v_xattr_entry*
594 xattr_getcache(struct v_inode* inode, struct hstr* name);
595
596 void
597 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
598
599
600 /* --- misc stuff --- */
601
602 #define check_itype(to_check, itype)    \
603     (((to_check) & (itype)) == (itype))
604
605 /**
606  * @brief Check if node represent a regular file (nothing but a file)
607  * 
608  * @param inode 
609  * @return true 
610  * @return false 
611  */
612 static inline bool
613 check_regfile_node(struct v_inode* inode)
614 {
615     return inode->itype == VFS_IFFILE;
616 }
617
618 /**
619  * @brief Check if node represent a file.
620  *        This is basically everything within file system (dir, dev, etc.)
621  * 
622  * @param inode 
623  * @return true 
624  * @return false 
625  */
626 static inline bool
627 check_file_node(struct v_inode* inode)
628 {
629     return check_itype(inode->itype, VFS_IFFILE);
630 }
631
632 static inline bool
633 check_directory_node(struct v_inode* inode)
634 {
635     return check_itype(inode->itype, VFS_IFDIR);
636 }
637
638 static inline bool
639 check_device_node(struct v_inode* inode)
640 {
641     return check_itype(inode->itype, VFS_IFDEV);
642 }
643
644 static inline bool
645 check_seqdev_node(struct v_inode* inode)
646 {
647     return check_device_node(inode);
648 }
649
650 static inline bool
651 check_voldev_node(struct v_inode* inode)
652 {
653     return check_itype(inode->itype, VFS_IFVOLDEV);
654 }
655
656 static inline bool
657 check_symlink_node(struct v_inode* inode)
658 {
659     return check_itype(inode->itype, VFS_IFSYMLINK);
660 }
661
662 #endif /* __LUNAIX_VFS_H */