reduce the size of ppage by 8 bytes using signly linked list
[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 <usr/lunaix/fstypes.h>
18
19 #define VFS_NAME_MAXLEN 128
20 #define VFS_MAX_FD 32
21
22 #define VFS_IFFILE       F_FILE
23 #define VFS_IFDIR       (F_FILE | F_DIR    )
24 #define VFS_IFDEV       (F_FILE | F_DEV    )
25 #define VFS_IFSYMLINK   (F_FILE | F_SYMLINK)
26 #define VFS_IFVOLDEV    (F_FILE | F_SVDEV  )
27 #define VFS_IFSEQDEV    VFS_IFDEV
28
29 // Walk, mkdir if component encountered is non-exists.
30 #define VFS_WALK_MKPARENT 0x1
31
32 // Walk, relative to current FS.
33 #define VFS_WALK_FSRELATIVE 0x2
34
35 /*
36     Terminate the walk on the immediate parent,
37     name of child (last component) is returned through `component`
38 */
39 #define VFS_WALK_PARENT 0x4
40
41 // Do not follow the symbolic link
42 #define VFS_WALK_NOFOLLOW 0x8
43
44 #define VFS_HASHTABLE_BITS 10
45 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
46 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
47 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
48
49 #define VFS_PATH_DELIM '/'
50
51 #define FSTYPE_ROFS     0b00000001
52 #define FSTYPE_PSEUDO   0x00000010
53
54 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
55
56 #define EXPORT_FILE_SYSTEM(fs_id, init_fn)                                     \
57     export_ldga_el(fs, fs_id, ptr_t, init_fn)
58
59 #define VFS_VALID_CHAR(chr)                                                    \
60     (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') ||       \
61      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
62      (chr) == '-' || (chr) == ':')
63
64 #define unlock_inode(inode) mutex_unlock(&inode->lock)
65 #define lock_inode(inode)                                                      \
66     ({                                                                         \
67         mutex_lock(&inode->lock);                                              \
68         lru_use_one(inode_lru, &inode->lru);                                   \
69     })
70
71 #define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
72 #define lock_dnode(dnode)                                                      \
73     ({                                                                         \
74         mutex_lock(&dnode->lock);                                              \
75         lru_use_one(dnode_lru, &dnode->lru);                                   \
76     })
77
78 #define assert_fs(cond) assert_p(cond, "FS")
79 #define fail_fs(msg) fail_p(msg, "FS")
80
81 typedef u32_t inode_t;
82
83 struct v_dnode;
84 struct v_inode;
85 struct v_superblock;
86 struct v_file;
87 struct v_file_ops;
88 struct v_inode_ops;
89 struct v_fd;
90 struct pcache;
91 struct v_xattr_entry;
92
93 extern struct v_file_ops default_file_ops;
94 extern struct v_inode_ops default_inode_ops;
95
96 extern struct hstr vfs_ddot;
97 extern struct hstr vfs_dot;
98 extern struct v_dnode* vfs_sysroot;
99
100 typedef int (*mntops_mnt)(struct v_superblock* vsb, struct v_dnode* mount_point);
101 typedef int (*mntops_umnt)(struct v_superblock* vsb);
102
103 struct filesystem
104 {
105     struct llist_header fs_flat;
106     struct hlist_node fs_list;
107     struct hstr fs_name;
108     u32_t types;
109     int fs_id;
110     mntops_mnt mount;
111     mntops_umnt unmount;
112 };
113
114 struct fs_iter
115 {
116     struct filesystem* fs;
117 };
118
119 struct v_superblock
120 {
121     struct llist_header sb_list;
122     struct device* dev;
123     struct v_dnode* root;
124     struct filesystem* fs;
125     struct blkbuf_cache* blks;
126     struct hbucket* i_cache;
127     struct hbucket* d_cache;
128     
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     unsigned long 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     
289     struct v_superblock* super_block;
290     struct v_mount* mnt;
291     
292     unsigned long ref_count;
293
294     void* data;
295
296     void (*destruct)(struct v_dnode* dnode);
297 };
298
299 struct v_fdtable
300 {
301     struct v_fd* fds[VFS_MAX_FD];
302 };
303
304 struct pcache
305 {
306     struct v_inode* master;
307     struct bcache cache;
308     struct llist_header dirty;
309     u32_t n_dirty;
310     u32_t n_pages;
311 };
312
313 struct pcache_pg
314 {
315     struct llist_header dirty_list;
316
317     union {
318         struct {
319             bool dirty:1;
320         };
321         u32_t flags;
322     };
323
324     void* data;
325     unsigned int index;
326 };
327
328 static inline bool
329 check_itype_any(struct v_inode* inode, unsigned int type_mask)
330 {
331     return !!(inode->itype & type_mask) || !type_mask;
332 }
333
334 void
335 fsm_init();
336
337 void
338 fsm_register_all();
339
340 struct filesystem*
341 fsm_new_fs(char* name, size_t name_len);
342
343 void
344 fsm_register(struct filesystem* fs);
345
346 struct filesystem*
347 fsm_get(const char* fs_name);
348
349 void
350 fsm_itbegin(struct fs_iter* iterator);
351
352 bool
353 fsm_itnext(struct fs_iter* iterator);
354
355 static inline void
356 fsm_itend(struct fs_iter* iterator)
357 {
358     iterator->fs = NULL;
359 }
360
361 static inline bool
362 fsm_check_pseudo_fs(struct filesystem* fs)
363 {
364     return !!(fs->types & FSTYPE_PSEUDO);
365 }
366
367 void
368 vfs_init();
369
370 void
371 vfs_export_attributes();
372
373 struct v_dnode*
374 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
375
376 void
377 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
378
379 void
380 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
381
382 void
383 vfs_dcache_remove(struct v_dnode* dnode);
384
385 int
386 vfs_walk(struct v_dnode* start,
387          const char* path,
388          struct v_dnode** dentry,
389          struct hstr* component,
390          int walk_options);
391
392 int
393 vfs_walk_proc(const char* path,
394               struct v_dnode** dentry,
395               struct hstr* component,
396               int options);
397
398 int
399 vfs_mount(const char* target,
400           const char* fs_name,
401           struct device* device,
402           int options);
403
404 int
405 vfs_unmount(const char* target);
406
407 int
408 vfs_mount_at(const char* fs_name,
409              struct device* device,
410              struct v_dnode* mnt_point,
411              int options);
412
413 int
414 vfs_unmount_at(struct v_dnode* mnt_point);
415
416 int
417 vfs_mkdir(const char* path, struct v_dnode** dentry);
418
419 int
420 vfs_open(struct v_dnode* dnode, struct v_file** file);
421
422 int
423 vfs_pclose(struct v_file* file, pid_t pid);
424
425 int
426 vfs_close(struct v_file* file);
427
428 void
429 vfs_free_fd(struct v_fd* fd);
430
431 int
432 vfs_fsync(struct v_file* file);
433
434 void
435 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
436
437 struct v_superblock*
438 vfs_sb_alloc();
439
440 void
441 vfs_sb_unref(struct v_superblock* sb);
442
443 void
444 vfs_sb_ref(struct v_superblock* sb);
445
446 #define vfs_assign_sb(sb_accessor, sb)      \
447     ({                                      \
448         if (likely(sb_accessor)) {          \
449             vfs_sb_unref(sb_accessor);       \
450         }                                   \
451         vfs_sb_ref(((sb_accessor) = (sb))); \
452     })
453
454 static inline void
455 vfs_i_assign_sb(struct v_inode* inode, struct v_superblock* sb)
456 {
457     vfs_assign_sb(inode->sb, sb);
458 }
459
460 static inline void
461 vfs_d_assign_sb(struct v_dnode* dnode, struct v_superblock* sb)
462 {
463     vfs_assign_sb(dnode->super_block, sb);
464 }
465
466 static inline void
467 vfs_d_assign_vmnt(struct v_dnode* dnode, struct v_mount* vmnt)
468 {
469     if (dnode->mnt) {
470         assert_msg(dnode->mnt->mnt_point != dnode, 
471                     "vmnt must be detached first");
472     }
473
474     dnode->mnt = vmnt;
475
476     if (likely(vmnt))
477         vfs_d_assign_sb(dnode, vmnt->super_block);
478 }
479
480 static inline void
481 vfs_vmnt_assign_sb(struct v_mount* vmnt, struct v_superblock* sb)
482 {
483     vfs_assign_sb(vmnt->super_block, sb);
484 }
485
486 struct v_dnode*
487 vfs_d_alloc(struct v_dnode* parent, struct hstr* name);
488
489 void
490 vfs_d_free(struct v_dnode* dnode);
491
492 struct v_inode*
493 vfs_i_find(struct v_superblock* sb, u32_t i_id);
494
495 void
496 vfs_i_addhash(struct v_inode* inode);
497
498 struct v_inode*
499 vfs_i_alloc(struct v_superblock* sb);
500
501 void
502 vfs_i_free(struct v_inode* inode);
503
504 int
505 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
506
507 int
508 vfs_getfd(int fd, struct v_fd** fd_s);
509
510 int
511 vfs_get_dtype(int itype);
512
513 int
514 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
515
516 void
517 pcache_init(struct pcache* pcache);
518
519 int
520 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
521
522 int
523 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
524
525 void
526 pcache_release(struct pcache* pcache);
527
528 int
529 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
530
531 void
532 pcache_commit_all(struct v_inode* inode);
533
534 void
535 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
536
537 /**
538  * @brief 将挂载点标记为繁忙
539  *
540  * @param mnt
541  */
542 void
543 mnt_mkbusy(struct v_mount* mnt);
544
545 /**
546  * @brief 将挂载点标记为清闲
547  *
548  * @param mnt
549  */
550 void
551 mnt_chillax(struct v_mount* mnt);
552
553 int
554 vfs_mount_root(const char* fs_name, struct device* device);
555
556 static inline bool
557 mnt_check_busy(struct v_mount* mnt)
558 {
559     return mnt->busy_counter > 1;
560 }
561
562 static inline void
563 vfs_ref_dnode(struct v_dnode* dnode)
564 {
565     dnode->ref_count++;
566     
567     if (likely(dnode->mnt)) {
568         mnt_mkbusy(dnode->mnt);
569     }
570 }
571
572 static inline void
573 vfs_unref_dnode(struct v_dnode* dnode)
574 {
575     dnode->ref_count--;
576
577     if (likely(dnode->mnt)) {
578         mnt_chillax(dnode->mnt);
579     }
580 }
581
582 static inline void
583 vfs_ref_file(struct v_file* file)
584 {
585     file->ref_count++;
586 }
587
588 static inline void
589 vfs_unref_file(struct v_file* file)
590 {
591     file->ref_count--;
592 }
593
594 static inline bool
595 vfs_check_duped_file(struct v_file* file)
596 {
597     return file->ref_count > 1;
598 }
599
600 int
601 vfs_check_writable(struct v_dnode* dnode);
602
603 int
604 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
605
606 int
607 default_file_write(struct v_inode* inode,
608                    void* buffer,
609                    size_t len,
610                    size_t fpos);
611
612 int
613 default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
614
615 int
616 default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
617
618 int
619 default_file_readdir(struct v_file* file, struct dir_context* dctx);
620
621 int
622 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
623
624 int
625 default_inode_rename(struct v_inode* from_inode,
626                      struct v_dnode* from_dnode,
627                      struct v_dnode* to_dnode);
628
629 int
630 default_file_close(struct v_file* file);
631
632 int
633 default_file_seek(struct v_file* file, size_t offset);
634
635 int
636 default_inode_open(struct v_inode* this, struct v_file* file);
637
638 int
639 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
640
641 int
642 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
643
644 struct v_xattr_entry*
645 xattr_new(struct hstr* name);
646
647 struct v_xattr_entry*
648 xattr_getcache(struct v_inode* inode, struct hstr* name);
649
650 void
651 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
652
653
654 /* --- misc stuff --- */
655
656 #define check_itype(to_check, itype)    \
657     (((to_check) & (itype)) == (itype))
658
659 /**
660  * @brief Check if node represent a regular file (nothing but a file)
661  * 
662  * @param inode 
663  * @return true 
664  * @return false 
665  */
666 static inline bool
667 check_regfile_node(struct v_inode* inode)
668 {
669     return inode->itype == VFS_IFFILE;
670 }
671
672 /**
673  * @brief Check if node represent a file.
674  *        This is basically everything within file system (dir, dev, etc.)
675  * 
676  * @param inode 
677  * @return true 
678  * @return false 
679  */
680 static inline bool
681 check_file_node(struct v_inode* inode)
682 {
683     return check_itype(inode->itype, VFS_IFFILE);
684 }
685
686 static inline bool
687 check_directory_node(struct v_inode* inode)
688 {
689     return check_itype(inode->itype, VFS_IFDIR);
690 }
691
692 static inline bool
693 check_device_node(struct v_inode* inode)
694 {
695     return check_itype(inode->itype, VFS_IFDEV);
696 }
697
698 static inline bool
699 check_seqdev_node(struct v_inode* inode)
700 {
701     return check_device_node(inode);
702 }
703
704 static inline bool
705 check_voldev_node(struct v_inode* inode)
706 {
707     return check_itype(inode->itype, VFS_IFVOLDEV);
708 }
709
710 static inline bool
711 check_symlink_node(struct v_inode* inode)
712 {
713     return check_itype(inode->itype, VFS_IFSYMLINK);
714 }
715
716 #endif /* __LUNAIX_VFS_H */