patch file systems with the acl checks
[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 #include <lunaix/fs_acl.h>
17
18 #include <usr/lunaix/fstypes.h>
19
20 #define VFS_NAME_MAXLEN 128
21 #define VFS_MAX_FD 32
22
23 #define VFS_IFFILE       F_FILE
24 #define VFS_IFDIR       (F_FILE | F_DIR    )
25 #define VFS_IFDEV       (F_FILE | F_DEV    )
26 #define VFS_IFSYMLINK   (F_FILE | F_SYMLINK)
27 #define VFS_IFVOLDEV    (F_FILE | F_SVDEV  )
28 #define VFS_IFSEQDEV    VFS_IFDEV
29
30 // Walk, mkdir if component encountered is non-exists.
31 #define VFS_WALK_MKPARENT 0x1
32
33 // Walk, relative to current FS.
34 #define VFS_WALK_FSRELATIVE 0x2
35
36 /*
37     Terminate the walk on the immediate parent,
38     name of child (last component) is returned through `component`
39 */
40 #define VFS_WALK_PARENT 0x4
41
42 // Do not follow the symbolic link
43 #define VFS_WALK_NOFOLLOW 0x8
44
45 #define VFS_HASHTABLE_BITS 10
46 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
47 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
48 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
49
50 #define VFS_PATH_DELIM '/'
51
52 #define FSTYPE_ROFS     0b00000001
53 #define FSTYPE_PSEUDO   0x00000010
54
55 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
56
57 #define EXPORT_FILE_SYSTEM(fs_id, init_fn)                                     \
58     export_ldga_el(fs, fs_id, ptr_t, init_fn)
59
60 #define VFS_VALID_CHAR(chr)                                                    \
61     (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') ||       \
62      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
63      (chr) == '-' || (chr) == ':')
64
65 #define unlock_inode(inode) mutex_unlock(&inode->lock)
66 #define lock_inode(inode)                                                      \
67     ({                                                                         \
68         mutex_lock(&inode->lock);                                              \
69         lru_use_one(inode_lru, &inode->lru);                                   \
70     })
71
72 #define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
73 #define lock_dnode(dnode)                                                      \
74     ({                                                                         \
75         mutex_lock(&dnode->lock);                                              \
76         lru_use_one(dnode_lru, &dnode->lru);                                   \
77     })
78
79 #define assert_fs(cond) assert_p(cond, "FS")
80 #define fail_fs(msg) fail_p(msg, "FS")
81
82 typedef u32_t inode_t;
83
84 struct v_dnode;
85 struct v_inode;
86 struct v_superblock;
87 struct v_file;
88 struct v_file_ops;
89 struct v_inode_ops;
90 struct v_fd;
91 struct pcache;
92 struct v_xattr_entry;
93
94 extern struct v_file_ops default_file_ops;
95 extern struct v_inode_ops default_inode_ops;
96
97 extern struct hstr vfs_ddot;
98 extern struct hstr vfs_dot;
99 extern struct v_dnode* vfs_sysroot;
100
101 typedef int (*mntops_mnt)(struct v_superblock* vsb, struct v_dnode* mount_point);
102 typedef int (*mntops_umnt)(struct v_superblock* vsb);
103
104 struct filesystem
105 {
106     struct llist_header fs_flat;
107     struct hlist_node fs_list;
108     struct hstr fs_name;
109     u32_t types;
110     int fs_id;
111     mntops_mnt mount;
112     mntops_umnt unmount;
113 };
114
115 struct fs_iter
116 {
117     struct filesystem* fs;
118 };
119
120 struct v_superblock
121 {
122     struct llist_header sb_list;
123     struct device* dev;
124     struct v_dnode* root;
125     struct filesystem* fs;
126     struct blkbuf_cache* blks;
127     struct hbucket* i_cache;
128     struct hbucket* d_cache;
129     
130     void* data;
131     unsigned int ref_count;
132     size_t blksize;
133     struct
134     {
135         size_t (*read_capacity)(struct v_superblock* vsb);
136         size_t (*read_usage)(struct v_superblock* vsb);
137         void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
138         void (*release)(struct v_superblock* vsb);
139     } ops;
140 };
141
142 struct dir_context
143 {
144     void* cb_data;
145     void (*read_complete_callback)(struct dir_context* dctx,
146                                    const char* name,
147                                    const int len,
148                                    const int dtype);
149 };
150
151 struct v_file_ops
152 {
153     int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
154     int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
155
156     // for operatiosn {write|read}_page, following are true:
157     //  + `len` always equals to PG_SIZE
158     //  + `fpos` always PG_SIZE aligned.
159     // These additional operations allow underlying fs to use more specialized
160     // and optimized code.
161
162     int (*write_page)(struct v_inode* inode, void* pg, size_t fpos);
163     int (*read_page)(struct v_inode* inode, void* pg, size_t fpos);
164
165     int (*readdir)(struct v_file* file, struct dir_context* dctx);
166     int (*seek)(struct v_file* file, size_t offset);
167     int (*close)(struct v_file* file);
168     int (*sync)(struct v_file* file);
169 };
170
171 struct v_inode_ops
172 {
173     int (*create)(struct v_inode* this, struct v_dnode* dnode, 
174                   unsigned int itype);
175     
176     int (*open)(struct v_inode* this, struct v_file* file);
177     int (*sync)(struct v_inode* this);
178
179     int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
180     int (*rmdir)(struct v_inode* this, struct v_dnode* dnode);
181     int (*unlink)(struct v_inode* this, struct v_dnode* name);
182     int (*link)(struct v_inode* this, struct v_dnode* new_name);
183
184     int (*read_symlink)(struct v_inode* this, const char** path_out);
185     int (*set_symlink)(struct v_inode* this, const char* target);
186     
187     int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
188
189     int (*rename)(struct v_inode* from_inode,
190                   struct v_dnode* from_dnode,
191                   struct v_dnode* to_dnode);
192
193     int (*getxattr)(struct v_inode* this,
194                     struct v_xattr_entry* entry); // optional
195     int (*setxattr)(struct v_inode* this,
196                     struct v_xattr_entry* entry); // optional
197     int (*delxattr)(struct v_inode* this,
198                     struct v_xattr_entry* entry); // optional
199 };
200
201 struct v_xattr_entry
202 {
203     struct llist_header entries;
204     struct hstr name;
205     const void* value;
206     size_t len;
207 };
208
209 struct v_file
210 {
211     struct v_inode* inode;
212     struct v_dnode* dnode;
213     struct llist_header* f_list;
214     u32_t f_pos;
215     unsigned long ref_count;
216     void* data;
217     struct v_file_ops* ops; // for caching
218 };
219
220 struct v_fd
221 {
222     struct v_file* file;
223     int flags;
224 };
225
226 //  [v_inode::aka_nodes]
227 //  how do we invalidate corresponding v_dnodes given the v_inode?
228 /*
229     Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
230     info of every process being accessible via file system. Each process's
231     creation will result a creation of a directory under the root of task fs
232     with it's pid as name. But that dir must delete when process is killed, and
233     such deletion does not mediated by vfs itself, so there is a need of cache
234     syncing.
235     And this is also the case of all ramfs where argumentation to file tree is
236     performed by third party.
237 */
238
239 struct v_inode
240 {
241     inode_t id;
242     mutex_t lock;
243     u32_t itype;
244     time_t ctime;
245     time_t mtime;
246     time_t atime;
247     lba_t lb_addr;
248     u32_t open_count;
249     u32_t link_count;
250     u32_t lb_usage;
251     u32_t fsize;
252
253     u32_t acl;
254     uid_t uid;
255     gid_t gid;
256
257     void* data; // 允许底层FS绑定他的一些专有数据
258     struct llist_header aka_dnodes;
259     struct llist_header xattrs;
260     struct v_superblock* sb;
261     struct hlist_node hash_list;
262     struct lru_node lru;
263     struct pcache* pg_cache;
264     struct v_inode_ops* ops;
265     struct v_file_ops* default_fops;
266
267     void (*destruct)(struct v_inode* inode);
268 };
269
270 struct v_mount
271 {
272     mutex_t lock;
273     struct llist_header list;
274     struct llist_header submnts;
275     struct llist_header sibmnts;
276     struct v_mount* parent;
277     struct v_dnode* mnt_point;
278     struct v_superblock* super_block;
279     u32_t busy_counter;
280     int flags;
281 };
282
283 struct v_dnode
284 {
285     mutex_t lock; // sync the path walking
286     struct lru_node lru;
287     struct hstr name;
288     struct v_inode* inode;
289     struct v_dnode* parent;
290     struct hlist_node hash_list;
291     struct llist_header aka_list;
292     struct llist_header children;
293     struct llist_header siblings;
294     
295     struct v_superblock* super_block;
296     struct v_mount* mnt;
297     
298     unsigned long ref_count;
299
300     void* data;
301
302     void (*destruct)(struct v_dnode* dnode);
303 };
304
305 struct v_fdtable
306 {
307     struct v_fd* fds[VFS_MAX_FD];
308 };
309
310 struct pcache
311 {
312     struct v_inode* master;
313     struct bcache cache;
314     struct llist_header dirty;
315     u32_t n_dirty;
316     u32_t n_pages;
317 };
318
319 struct pcache_pg
320 {
321     struct llist_header dirty_list;
322
323     union {
324         struct {
325             bool dirty:1;
326         };
327         u32_t flags;
328     };
329
330     void* data;
331     unsigned int index;
332 };
333
334 static inline bool
335 check_itype_any(struct v_inode* inode, unsigned int type_mask)
336 {
337     return !!(inode->itype & type_mask) || !type_mask;
338 }
339
340 void
341 fsm_init();
342
343 void
344 fsm_register_all();
345
346 struct filesystem*
347 fsm_new_fs(char* name, size_t name_len);
348
349 void
350 fsm_register(struct filesystem* fs);
351
352 struct filesystem*
353 fsm_get(const char* fs_name);
354
355 void
356 fsm_itbegin(struct fs_iter* iterator);
357
358 bool
359 fsm_itnext(struct fs_iter* iterator);
360
361 static inline void
362 fsm_itend(struct fs_iter* iterator)
363 {
364     iterator->fs = NULL;
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 static inline bool
717 check_allow_ops(struct v_inode* inode, unsigned int perm)
718 {
719     return fsacl_allow_ops(perm, inode->acl, inode->uid, inode->gid);
720 }
721
722 static inline bool
723 check_allow_read(struct v_inode* inode)
724 {
725     return check_allow_ops(inode, FSACL_aR);
726 }
727
728 static inline bool
729 check_allow_write(struct v_inode* inode)
730 {
731     return check_allow_ops(inode, FSACL_aW);
732 }
733
734 static inline bool
735 check_allow_execute(struct v_inode* inode)
736 {
737     return check_allow_ops(inode, FSACL_aX);
738 }
739
740 #endif /* __LUNAIX_VFS_H */