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