4 #include <lunaix/ds/btrie.h>
5 #include <lunaix/ds/hashtable.h>
6 #include <lunaix/ds/hstr.h>
7 #include <lunaix/ds/ldga.h>
8 #include <lunaix/ds/llist.h>
9 #include <lunaix/ds/lru.h>
10 #include <lunaix/ds/mutex.h>
11 #include <lunaix/ds/rwlock.h>
13 #include <lunaix/clock.h>
14 #include <lunaix/device.h>
15 #include <lunaix/status.h>
16 #include <lunaix/spike.h>
17 #include <lunaix/bcache.h>
18 #include <lunaix/fs_acl.h>
20 #include <usr/lunaix/fstypes.h>
22 #define VFS_NAME_MAXLEN 128
25 #define VFS_IFFILE F_FILE
26 #define VFS_IFDIR (F_FILE | F_DIR )
27 #define VFS_IFDEV (F_FILE | F_DEV )
28 #define VFS_IFSYMLINK (F_FILE | F_SYMLINK)
29 #define VFS_IFVOLDEV (F_FILE | F_SVDEV )
30 #define VFS_IFSEQDEV VFS_IFDEV
32 // Walk, mkdir if component encountered is non-exists.
33 #define VFS_WALK_MKPARENT 0x1
35 // Walk, relative to current FS.
36 #define VFS_WALK_FSRELATIVE 0x2
39 Terminate the walk on the immediate parent,
40 name of child (last component) is returned through `component`
42 #define VFS_WALK_PARENT 0x4
44 // Do not follow the symbolic link
45 #define VFS_WALK_NOFOLLOW 0x8
47 #define VFS_HASHTABLE_BITS 10
48 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
49 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
50 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
52 #define VFS_PATH_DELIM '/'
54 #define FSTYPE_ROFS 0b00000001
55 #define FSTYPE_PSEUDO 0x00000010
57 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
59 #define EXPORT_FILE_SYSTEM(fs_id, init_fn) \
60 export_ldga_el(fs, fs_id, ptr_t, init_fn)
62 #define VFS_VALID_CHAR(chr) \
63 (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') || \
64 ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' || \
65 (chr) == '-' || (chr) == ':')
67 #define unlock_inode(inode) mutex_unlock_nested(&inode->lock)
68 #define lock_inode(inode) \
70 mutex_lock_nested(&inode->lock); \
71 lru_use_one(inode_lru, &inode->lru); \
74 #define unlock_dnode(dnode) mutex_unlock_nested(&dnode->lock)
75 #define lock_dnode(dnode) \
77 mutex_lock_nested(&dnode->lock); \
78 lru_use_one(dnode_lru, &dnode->lru); \
81 #define dnode_atomic(dnode, ops) \
82 do { lock_dnode(dnode); ops; unlock_dnode(dnode); } while(0)
84 #define locked_node(node) mutex_on_hold(&(node)->lock)
86 #define assert_fs(cond) assert_p(cond, "FS")
87 #define fail_fs(msg) fail_p(msg, "FS")
89 typedef u32_t inode_t;
101 extern struct v_file_ops default_file_ops;
102 extern struct v_inode_ops default_inode_ops;
104 extern struct hstr vfs_ddot;
105 extern struct hstr vfs_dot;
106 extern struct v_dnode* vfs_sysroot;
108 typedef int (*mntops_mnt)(struct v_superblock* vsb, struct v_dnode* mount_point);
109 typedef int (*mntops_umnt)(struct v_superblock* vsb);
113 struct llist_header fs_flat;
114 struct hlist_node fs_list;
124 struct filesystem* fs;
129 struct hbucket* pool;
132 #define cache_atomic_read(cache, ops) \
134 rwlock_begin_read(&(cache)->lock); \
136 rwlock_end_read(&(cache)->lock); \
139 #define cache_atomic_write(cache, ops) \
141 rwlock_begin_write(&(cache)->lock); \
143 rwlock_end_write(&(cache)->lock); \
146 #define dnode_cache(dnode) (&(dnode)->super_block->d_cache)
147 #define inode_cache(inode) (&(inode)->sb->i_cache)
151 struct llist_header sb_list;
153 struct v_dnode* root;
154 struct filesystem* fs;
155 struct blkbuf_cache* blks;
156 struct vncache i_cache;
157 struct vncache d_cache;
160 unsigned int ref_count;
164 size_t (*read_capacity)(struct v_superblock* vsb);
165 size_t (*read_usage)(struct v_superblock* vsb);
166 void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
167 void (*release)(struct v_superblock* vsb);
174 void (*read_complete_callback)(struct dir_context* dctx,
182 int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
183 int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
185 // for operatiosn {write|read}_page, following are true:
186 // + `len` always equals to PG_SIZE
187 // + `fpos` always PG_SIZE aligned.
188 // These additional operations allow underlying fs to use more specialized
189 // and optimized code.
191 int (*write_page)(struct v_inode* inode, void* pg, size_t fpos);
192 int (*read_page)(struct v_inode* inode, void* pg, size_t fpos);
194 int (*readdir)(struct v_file* file, struct dir_context* dctx);
195 int (*seek)(struct v_file* file, size_t offset);
196 int (*close)(struct v_file* file);
197 int (*sync)(struct v_file* file);
202 int (*create)(struct v_inode* this, struct v_dnode* dnode,
205 int (*open)(struct v_inode* this, struct v_file* file);
206 int (*sync)(struct v_inode* this);
208 int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
209 int (*rmdir)(struct v_inode* this, struct v_dnode* dnode);
210 int (*unlink)(struct v_inode* this, struct v_dnode* name);
211 int (*link)(struct v_inode* this, struct v_dnode* new_name);
213 int (*read_symlink)(struct v_inode* this, const char** path_out);
214 int (*set_symlink)(struct v_inode* this, const char* target);
216 int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
218 int (*rename)(struct v_inode* from_inode,
219 struct v_dnode* from_dnode,
220 struct v_dnode* to_dnode);
222 int (*getxattr)(struct v_inode* this,
223 struct v_xattr_entry* entry); // optional
224 int (*setxattr)(struct v_inode* this,
225 struct v_xattr_entry* entry); // optional
226 int (*delxattr)(struct v_inode* this,
227 struct v_xattr_entry* entry); // optional
232 struct llist_header entries;
240 struct v_inode* inode;
241 struct v_dnode* dnode;
242 struct llist_header* f_list;
244 unsigned long ref_count;
246 struct v_file_ops* ops; // for caching
255 // [v_inode::aka_nodes]
256 // how do we invalidate corresponding v_dnodes given the v_inode?
258 Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
259 info of every process being accessible via file system. Each process's
260 creation will result a creation of a directory under the root of task fs
261 with it's pid as name. But that dir must delete when process is killed, and
262 such deletion does not mediated by vfs itself, so there is a need of cache
264 And this is also the case of all ramfs where argumentation to file tree is
265 performed by third party.
286 void* data; // 允许底层FS绑定他的一些专有数据
287 struct llist_header aka_dnodes;
288 struct llist_header xattrs;
289 struct v_superblock* sb;
290 struct hlist_node hash_list;
292 struct pcache* pg_cache;
293 struct v_inode_ops* ops;
294 struct v_file_ops* default_fops;
296 void (*destruct)(struct v_inode* inode);
302 struct llist_header list;
303 struct llist_header submnts;
304 struct llist_header sibmnts;
305 struct v_mount* parent;
306 struct v_dnode* mnt_point;
307 struct v_superblock* super_block;
314 mutex_t lock; // sync the path walking
317 struct v_inode* inode;
318 struct v_dnode* parent;
319 struct hlist_node hash_list;
320 struct llist_header aka_list;
321 struct llist_header children;
322 struct llist_header siblings;
324 struct v_superblock* super_block;
327 unsigned long ref_count;
331 void (*destruct)(struct v_dnode* dnode);
336 struct v_fd* fds[VFS_MAX_FD];
337 mutex_t lock; // inter-threads contention
339 #define lock_fdtable(fdtab) mutex_lock(&(fdtab)->lock)
340 #define unlock_fdtable(fdtab) mutex_unlock(&(fdtab)->lock)
344 struct v_inode* master;
346 struct llist_header dirty;
353 struct llist_header dirty_list;
367 check_itype_any(struct v_inode* inode, unsigned int type_mask)
369 return !!(inode->itype & type_mask) || !type_mask;
379 fsm_new_fs(char* name, size_t name_len);
382 fsm_register(struct filesystem* fs);
385 fsm_get(const char* fs_name);
388 fsm_itbegin(struct fs_iter* iterator);
391 fsm_itnext(struct fs_iter* iterator);
394 fsm_itend(struct fs_iter* iterator)
400 vfs_vncache_init(struct vncache* cache);
403 vfs_vncache_free(struct vncache* cache);
406 vfs_vncache_add(struct vncache* cache, size_t key, struct hlist_node* node);
408 #define vncache_lock_read(cache) rwlock_begin_read(&(cache)->lock);
409 #define vncache_unlock_read(cache) rwlock_end_read(&(cache)->lock);
411 #define vncache_lock_write(cache) rwlock_begin_write(&(cache)->lock);
412 #define vncache_unlock_write(cache) rwlock_end_write(&(cache)->lock);
418 vfs_export_attributes();
421 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
424 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
427 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
430 vfs_dcache_remove(struct v_dnode* dnode);
433 vfs_walk(struct v_dnode* start,
435 struct v_dnode** dentry,
436 struct hstr* component,
440 vfs_walk_proc(const char* path,
441 struct v_dnode** dentry,
442 struct hstr* component,
446 vfs_walkat(int fd, const char* path, int at_opts,
447 struct v_dnode** dnode_out);
450 vfs_mount(const char* target,
452 struct device* device,
456 vfs_unmount(const char* target);
459 vfs_mount_at(const char* fs_name,
460 struct device* device,
461 struct v_dnode* mnt_point,
465 vfs_unmount_at(struct v_dnode* mnt_point);
468 vfs_mkdir(const char* path, struct v_dnode** dentry);
471 vfs_open(struct v_dnode* dnode, struct v_file** file);
474 vfs_pclose(struct v_file* file, pid_t pid);
477 vfs_close(struct v_file* file);
480 vfs_free_fd(struct v_fd* fd);
483 vfs_fsync(struct v_file* file);
486 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
492 vfs_sb_unref(struct v_superblock* sb);
495 vfs_sb_ref(struct v_superblock* sb);
497 #define vfs_assign_sb(sb_accessor, sb) \
499 if (likely(sb_accessor)) { \
500 vfs_sb_unref(sb_accessor); \
502 vfs_sb_ref(((sb_accessor) = (sb))); \
506 vfs_i_assign_sb(struct v_inode* inode, struct v_superblock* sb)
508 vfs_assign_sb(inode->sb, sb);
512 vfs_d_assign_sb(struct v_dnode* dnode, struct v_superblock* sb)
514 vfs_assign_sb(dnode->super_block, sb);
518 vfs_d_assign_vmnt(struct v_dnode* dnode, struct v_mount* vmnt)
521 assert_msg(dnode->mnt->mnt_point != dnode,
522 "vmnt must be detached first");
528 vfs_d_assign_sb(dnode, vmnt->super_block);
532 vfs_vmnt_assign_sb(struct v_mount* vmnt, struct v_superblock* sb)
534 vfs_assign_sb(vmnt->super_block, sb);
538 vfs_d_alloc(struct v_dnode* parent, struct hstr* name);
541 vfs_d_free(struct v_dnode* dnode);
544 vfs_i_find(struct v_superblock* sb, u32_t i_id);
547 vfs_i_addhash(struct v_inode* inode);
550 vfs_i_alloc(struct v_superblock* sb);
553 vfs_i_free(struct v_inode* inode);
556 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
559 vfs_getfd(int fd, struct v_fd** fd_s);
562 vfs_get_dtype(int itype);
565 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
568 pcache_init(struct pcache* pcache);
571 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
574 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
577 pcache_release(struct pcache* pcache);
580 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
583 pcache_commit_all(struct v_inode* inode);
586 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
594 mnt_mkbusy(struct v_mount* mnt);
602 mnt_chillax(struct v_mount* mnt);
605 vfs_mount_root(const char* fs_name, struct device* device);
608 mnt_check_busy(struct v_mount* mnt)
610 return mnt->busy_counter > 1;
614 vfs_ref_dnode(struct v_dnode* dnode)
618 if (likely(dnode->mnt)) {
619 mnt_mkbusy(dnode->mnt);
624 vfs_unref_dnode(struct v_dnode* dnode)
628 if (likely(dnode->mnt)) {
629 mnt_chillax(dnode->mnt);
634 vfs_ref_file(struct v_file* file)
640 vfs_unref_file(struct v_file* file)
646 vfs_check_duped_file(struct v_file* file)
648 return file->ref_count > 1;
652 vfs_check_writable(struct v_dnode* dnode);
655 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
658 default_file_write(struct v_inode* inode,
664 default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
667 default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
670 default_file_readdir(struct v_file* file, struct dir_context* dctx);
673 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
676 default_inode_rename(struct v_inode* from_inode,
677 struct v_dnode* from_dnode,
678 struct v_dnode* to_dnode);
681 default_file_close(struct v_file* file);
684 default_file_seek(struct v_file* file, size_t offset);
687 default_inode_open(struct v_inode* this, struct v_file* file);
690 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
693 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
695 struct v_xattr_entry*
696 xattr_new(struct hstr* name);
698 struct v_xattr_entry*
699 xattr_getcache(struct v_inode* inode, struct hstr* name);
702 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
705 /* --- fdtable --- */
711 fdtable_copy(struct v_fdtable* dest, struct v_fdtable* src);
714 fdtable_free(struct v_fdtable* table);
717 /* --- misc stuff --- */
719 #define check_itype(to_check, itype) \
720 (((to_check) & (itype)) == (itype))
723 * @brief Check if node represent a regular file (nothing but a file)
730 check_regfile_node(struct v_inode* inode)
732 return inode->itype == VFS_IFFILE;
736 * @brief Check if node represent a file.
737 * This is basically everything within file system (dir, dev, etc.)
744 check_file_node(struct v_inode* inode)
746 return check_itype(inode->itype, VFS_IFFILE);
750 check_directory_node(struct v_inode* inode)
752 return check_itype(inode->itype, VFS_IFDIR);
756 check_device_node(struct v_inode* inode)
758 return check_itype(inode->itype, VFS_IFDEV);
762 check_seqdev_node(struct v_inode* inode)
764 return check_device_node(inode);
768 check_voldev_node(struct v_inode* inode)
770 return check_itype(inode->itype, VFS_IFVOLDEV);
774 check_symlink_node(struct v_inode* inode)
776 return check_itype(inode->itype, VFS_IFSYMLINK);
780 check_allow_ops(struct v_inode* inode, unsigned int perm)
782 return fsacl_allow_ops(perm, inode->acl, inode->uid, inode->gid);
786 check_allow_read(struct v_inode* inode)
788 return check_allow_ops(inode, FSACL_aR);
792 check_allow_write(struct v_inode* inode)
794 return check_allow_ops(inode, FSACL_aW);
798 check_allow_execute(struct v_inode* inode)
800 return check_allow_ops(inode, FSACL_aX);
803 #endif /* __LUNAIX_VFS_H */