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>
17 #include <stdatomic.h>
19 #include <usr/lunaix/fstypes.h>
21 #define VFS_NAME_MAXLEN 128
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
31 // Walk, mkdir if component encountered is non-exists.
32 #define VFS_WALK_MKPARENT 0x1
34 // Walk, relative to current FS.
35 #define VFS_WALK_FSRELATIVE 0x2
38 Terminate the walk on the immediate parent,
39 name of child (last component) is returned through `component`
41 #define VFS_WALK_PARENT 0x4
43 // Do not follow the symbolic link
44 #define VFS_WALK_NOFOLLOW 0x8
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)
51 #define VFS_PATH_DELIM '/'
53 #define FSTYPE_ROFS 0b00000001
54 #define FSTYPE_PSEUDO 0x00000010
56 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
58 #define EXPORT_FILE_SYSTEM(fs_id, init_fn) \
59 export_ldga_el(fs, fs_id, ptr_t, init_fn)
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) == ':')
66 #define unlock_inode(inode) mutex_unlock(&inode->lock)
67 #define lock_inode(inode) \
69 mutex_lock(&inode->lock); \
70 lru_use_one(inode_lru, &inode->lru); \
73 #define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
74 #define lock_dnode(dnode) \
76 mutex_lock(&dnode->lock); \
77 lru_use_one(dnode_lru, &dnode->lru); \
80 #define assert_fs(cond) assert_p(cond, "FS")
81 #define fail_fs(msg) fail_p(msg, "FS")
83 typedef u32_t inode_t;
95 extern struct v_file_ops default_file_ops;
96 extern struct v_inode_ops default_inode_ops;
98 extern struct hstr vfs_ddot;
99 extern struct hstr vfs_dot;
100 extern struct v_dnode* vfs_sysroot;
102 typedef int (*mntops_mnt)(struct v_superblock* vsb, struct v_dnode* mount_point);
103 typedef int (*mntops_umnt)(struct v_superblock* vsb);
107 struct llist_header fs_flat;
108 struct hlist_node fs_list;
118 struct llist_header sb_list;
120 struct v_dnode* root;
121 struct filesystem* fs;
122 struct blkbuf_cache* blks;
123 struct hbucket* i_cache;
125 unsigned int ref_count;
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);
139 void (*read_complete_callback)(struct dir_context* dctx,
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);
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.
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);
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);
167 int (*create)(struct v_inode* this, struct v_dnode* dnode,
170 int (*open)(struct v_inode* this, struct v_file* file);
171 int (*sync)(struct v_inode* this);
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);
178 int (*read_symlink)(struct v_inode* this, const char** path_out);
179 int (*set_symlink)(struct v_inode* this, const char* target);
181 int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
183 int (*rename)(struct v_inode* from_inode,
184 struct v_dnode* from_dnode,
185 struct v_dnode* to_dnode);
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
197 struct llist_header entries;
205 struct v_inode* inode;
206 struct v_dnode* dnode;
207 struct llist_header* f_list;
209 atomic_ulong ref_count;
211 struct v_file_ops* ops; // for caching
220 // [v_inode::aka_nodes]
221 // how do we invalidate corresponding v_dnodes given the v_inode?
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
229 And this is also the case of all ramfs where argumentation to file tree is
230 performed by third party.
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;
252 struct pcache* pg_cache;
253 struct v_inode_ops* ops;
254 struct v_file_ops* default_fops;
256 void (*destruct)(struct v_inode* inode);
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;
274 mutex_t lock; // sync the path walking
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;
285 atomic_ulong ref_count;
289 void (*destruct)(struct v_dnode* dnode);
294 struct v_fd* fds[VFS_MAX_FD];
299 struct v_inode* master;
301 struct llist_header dirty;
308 struct llist_header dirty_list;
322 check_itype_any(struct v_inode* inode, unsigned int type_mask)
324 return !!(inode->itype & type_mask) || !type_mask;
334 fsm_new_fs(char* name, size_t name_len);
337 fsm_register(struct filesystem* fs);
340 fsm_get(const char* fs_name);
346 vfs_export_attributes();
349 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
352 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
355 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
358 vfs_dcache_remove(struct v_dnode* dnode);
361 vfs_walk(struct v_dnode* start,
363 struct v_dnode** dentry,
364 struct hstr* component,
368 vfs_walk_proc(const char* path,
369 struct v_dnode** dentry,
370 struct hstr* component,
374 vfs_mount(const char* target,
376 struct device* device,
380 vfs_unmount(const char* target);
383 vfs_mount_at(const char* fs_name,
384 struct device* device,
385 struct v_dnode* mnt_point,
389 vfs_unmount_at(struct v_dnode* mnt_point);
392 vfs_mkdir(const char* path, struct v_dnode** dentry);
395 vfs_open(struct v_dnode* dnode, struct v_file** file);
398 vfs_pclose(struct v_file* file, pid_t pid);
401 vfs_close(struct v_file* file);
404 vfs_free_fd(struct v_fd* fd);
407 vfs_fsync(struct v_file* file);
410 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
416 vfs_sb_free(struct v_superblock* sb);
419 vfs_sb_ref(struct v_superblock* sb);
421 #define vfs_assign_sb(sb_accessor, sb) \
424 vfs_sb_free(sb_accessor); \
426 vfs_sb_ref(((sb_accessor) = (sb))); \
430 vfs_i_assign_sb(struct v_inode* inode, struct v_superblock* sb)
432 vfs_assign_sb(inode->sb, sb);
436 vfs_d_assign_sb(struct v_dnode* dnode, struct v_superblock* sb)
438 vfs_assign_sb(dnode->super_block, sb);
442 vfs_vmnt_assign_sb(struct v_mount* vmnt, struct v_superblock* sb)
444 vfs_assign_sb(vmnt->super_block, sb);
451 vfs_d_free(struct v_dnode* dnode);
454 vfs_i_find(struct v_superblock* sb, u32_t i_id);
457 vfs_i_addhash(struct v_inode* inode);
460 vfs_i_alloc(struct v_superblock* sb);
463 vfs_i_free(struct v_inode* inode);
466 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
469 vfs_getfd(int fd, struct v_fd** fd_s);
472 vfs_get_dtype(int itype);
475 vfs_ref_dnode(struct v_dnode* dnode);
478 vfs_ref_file(struct v_file* file);
481 vfs_unref_dnode(struct v_dnode* dnode);
484 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
487 pcache_init(struct pcache* pcache);
490 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
493 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
496 pcache_release(struct pcache* pcache);
499 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
502 pcache_commit_all(struct v_inode* inode);
505 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
513 mnt_mkbusy(struct v_mount* mnt);
521 mnt_chillax(struct v_mount* mnt);
524 vfs_mount_root(const char* fs_name, struct device* device);
527 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
530 vfs_check_writable(struct v_dnode* dnode);
533 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
536 default_file_write(struct v_inode* inode,
542 default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
545 default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
548 default_file_readdir(struct v_file* file, struct dir_context* dctx);
551 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
554 default_inode_rename(struct v_inode* from_inode,
555 struct v_dnode* from_dnode,
556 struct v_dnode* to_dnode);
559 default_file_close(struct v_file* file);
562 default_file_seek(struct v_file* file, size_t offset);
565 default_inode_open(struct v_inode* this, struct v_file* file);
568 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
571 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
573 struct v_xattr_entry*
574 xattr_new(struct hstr* name);
576 struct v_xattr_entry*
577 xattr_getcache(struct v_inode* inode, struct hstr* name);
580 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
583 /* --- misc stuff --- */
585 #define check_itype(to_check, itype) \
586 (((to_check) & (itype)) == (itype))
589 * @brief Check if node represent a regular file (nothing but a file)
596 check_regfile_node(struct v_inode* inode)
598 return inode->itype == VFS_IFFILE;
602 * @brief Check if node represent a file.
603 * This is basically everything within file system (dir, dev, etc.)
610 check_file_node(struct v_inode* inode)
612 return check_itype(inode->itype, VFS_IFFILE);
616 check_directory_node(struct v_inode* inode)
618 return check_itype(inode->itype, VFS_IFDIR);
622 check_device_node(struct v_inode* inode)
624 return check_itype(inode->itype, VFS_IFDEV);
628 check_seqdev_node(struct v_inode* inode)
630 return check_device_node(inode);
634 check_voldev_node(struct v_inode* inode)
636 return check_itype(inode->itype, VFS_IFVOLDEV);
640 check_symlink_node(struct v_inode* inode)
642 return check_itype(inode->itype, VFS_IFSYMLINK);
645 #endif /* __LUNAIX_VFS_H */