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 <stdatomic.h>
16 #define VFS_NAME_MAXLEN 128
20 #define VFS_IFFILE 0x2
21 #define VFS_IFSEQDEV 0x4
22 #define VFS_IFVOLDEV 0x8
23 #define VFS_IFSYMLINK 0x10
25 // Walk, mkdir if component encountered is non-exists.
26 #define VFS_WALK_MKPARENT 0x1
28 // Walk, relative to current FS.
29 #define VFS_WALK_FSRELATIVE 0x2
32 Terminate the walk on the immediate parent,
33 name of child (last component) is returned through `component`
35 #define VFS_WALK_PARENT 0x4
37 // Do not follow the symbolic link
38 #define VFS_WALK_NOFOLLOW 0x8
40 #define VFS_HASHTABLE_BITS 10
41 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
42 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
43 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
45 #define VFS_PATH_DELIM '/'
47 #define FSTYPE_ROFS 0x1
49 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
51 #define EXPORT_FILE_SYSTEM(fs_id, init_fn) \
52 export_ldga_el(fs, fs_id, ptr_t, init_fn)
54 #define VFS_VALID_CHAR(chr) \
55 (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') || \
56 ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' || \
57 (chr) == '-' || (chr) == ':')
59 #define unlock_inode(inode) mutex_unlock(&inode->lock)
60 #define lock_inode(inode) \
62 mutex_lock(&inode->lock); \
63 lru_use_one(inode_lru, &inode->lru); \
66 #define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
67 #define lock_dnode(dnode) \
69 mutex_lock(&dnode->lock); \
70 lru_use_one(dnode_lru, &dnode->lru); \
73 typedef u32_t inode_t;
85 extern struct v_file_ops default_file_ops;
86 extern struct v_inode_ops default_inode_ops;
88 extern struct hstr vfs_ddot;
89 extern struct hstr vfs_dot;
90 extern struct v_dnode* vfs_sysroot;
94 struct hlist_node fs_list;
98 int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
99 int (*unmount)(struct v_superblock* vsb);
104 struct llist_header sb_list;
106 struct v_dnode* root;
107 struct filesystem* fs;
108 struct hbucket* i_cache;
112 u32_t (*read_capacity)(struct v_superblock* vsb);
113 u32_t (*read_usage)(struct v_superblock* vsb);
114 void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
122 void (*read_complete_callback)(struct dir_context* dctx,
130 int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
131 int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
133 // for operatiosn {write|read}_page, following are true:
134 // + `len` always equals to PG_SIZE
135 // + `fpos` always PG_SIZE aligned.
136 // These additional operations allow underlying fs to use more specialized
137 // and optimized code.
139 int (*write_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
140 int (*read_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
142 int (*readdir)(struct v_file* file, struct dir_context* dctx);
143 int (*seek)(struct v_inode* inode, size_t offset); // optional
144 int (*close)(struct v_file* file);
145 int (*sync)(struct v_file* file);
150 int (*create)(struct v_inode* this, struct v_dnode* dnode);
151 int (*open)(struct v_inode* this, struct v_file* file);
152 int (*sync)(struct v_inode* this);
153 int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
154 int (*rmdir)(struct v_inode* this, struct v_dnode* dir);
155 int (*unlink)(struct v_inode* this);
156 int (*link)(struct v_inode* this, struct v_dnode* new_name);
157 int (*read_symlink)(struct v_inode* this, const char** path_out);
158 int (*set_symlink)(struct v_inode* this, const char* target);
159 int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
160 int (*rename)(struct v_inode* from_inode,
161 struct v_dnode* from_dnode,
162 struct v_dnode* to_dnode);
163 int (*getxattr)(struct v_inode* this,
164 struct v_xattr_entry* entry); // optional
165 int (*setxattr)(struct v_inode* this,
166 struct v_xattr_entry* entry); // optional
167 int (*delxattr)(struct v_inode* this,
168 struct v_xattr_entry* entry); // optional
173 struct llist_header entries;
181 struct v_inode* inode;
182 struct v_dnode* dnode;
183 struct llist_header* f_list;
185 atomic_ulong ref_count;
186 struct v_file_ops* ops; // for caching
195 // [v_inode::aka_nodes]
196 // how do we invalidate corresponding v_dnodes given the v_inode?
198 Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
199 info of every process being accessible via file system. Each process's
200 creation will result a creation of a directory under the root of task fs
201 with it's pid as name. But that dir must delete when process is killed, and
202 such deletion does not mediated by vfs itself, so there is a need of cache
204 And this is also the case of all ramfs where argumentation to file tree is
205 performed by third party.
221 void* data; // 允许底层FS绑定他的一些专有数据
222 struct llist_header aka_dnodes;
223 struct llist_header xattrs;
224 struct v_superblock* sb;
225 struct hlist_node hash_list;
227 struct pcache* pg_cache;
228 struct v_inode_ops* ops;
229 struct v_file_ops* default_fops;
231 void (*destruct)(struct v_inode* inode);
237 struct llist_header list;
238 struct llist_header submnts;
239 struct llist_header sibmnts;
240 struct v_mount* parent;
241 struct v_dnode* mnt_point;
242 struct v_superblock* super_block;
249 mutex_t lock; // sync the path walking
252 struct v_inode* inode;
253 struct v_dnode* parent;
254 struct hlist_node hash_list;
255 struct llist_header aka_list;
256 struct llist_header children;
257 struct llist_header siblings;
258 struct v_superblock* super_block;
260 atomic_ulong ref_count;
267 struct v_fd* fds[VFS_MAX_FD];
272 struct v_inode* master;
274 struct llist_header pages;
275 struct llist_header dirty;
282 struct llist_header pg_list;
283 struct llist_header dirty_list;
285 struct pcache* holder;
299 fsm_new_fs(char* name, size_t name_len);
302 fsm_register(struct filesystem* fs);
305 fsm_get(const char* fs_name);
311 vfs_export_attributes();
314 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
317 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
320 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
323 vfs_dcache_remove(struct v_dnode* dnode);
326 vfs_walk(struct v_dnode* start,
328 struct v_dnode** dentry,
329 struct hstr* component,
333 vfs_walk_proc(const char* path,
334 struct v_dnode** dentry,
335 struct hstr* component,
339 vfs_mount(const char* target,
341 struct device* device,
345 vfs_unmount(const char* target);
348 vfs_mount_at(const char* fs_name,
349 struct device* device,
350 struct v_dnode* mnt_point,
354 vfs_unmount_at(struct v_dnode* mnt_point);
357 vfs_mkdir(const char* path, struct v_dnode** dentry);
360 vfs_open(struct v_dnode* dnode, struct v_file** file);
363 vfs_pclose(struct v_file* file, pid_t pid);
366 vfs_close(struct v_file* file);
369 vfs_free_fd(struct v_fd* fd);
372 vfs_fsync(struct v_file* file);
375 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
381 vfs_sb_free(struct v_superblock* sb);
387 vfs_d_free(struct v_dnode* dnode);
390 vfs_i_find(struct v_superblock* sb, u32_t i_id);
393 vfs_i_addhash(struct v_inode* inode);
396 vfs_i_alloc(struct v_superblock* sb);
399 vfs_i_free(struct v_inode* inode);
402 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
405 vfs_getfd(int fd, struct v_fd** fd_s);
408 vfs_get_dtype(int itype);
411 vfs_ref_dnode(struct v_dnode* dnode);
414 vfs_ref_file(struct v_file* file);
417 vfs_unref_dnode(struct v_dnode* dnode);
420 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
423 pcache_init(struct pcache* pcache);
426 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
429 pcache_new_page(struct pcache* pcache, u32_t index);
432 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
435 pcache_get_page(struct pcache* pcache,
438 struct pcache_pg** page);
441 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
444 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
447 pcache_release(struct pcache* pcache);
450 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
453 pcache_commit_all(struct v_inode* inode);
456 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
464 mnt_mkbusy(struct v_mount* mnt);
472 mnt_chillax(struct v_mount* mnt);
475 vfs_mount_root(const char* fs_name, struct device* device);
478 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
481 vfs_check_writable(struct v_dnode* dnode);
484 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
487 default_file_write(struct v_inode* inode,
493 default_file_readdir(struct v_file* file, struct dir_context* dctx);
496 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
499 default_inode_rename(struct v_inode* from_inode,
500 struct v_dnode* from_dnode,
501 struct v_dnode* to_dnode);
504 default_file_close(struct v_file* file);
507 default_file_seek(struct v_inode* inode, size_t offset);
510 default_inode_open(struct v_inode* this, struct v_file* file);
513 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
516 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
518 struct v_xattr_entry*
519 xattr_new(struct hstr* name);
521 struct v_xattr_entry*
522 xattr_getcache(struct v_inode* inode, struct hstr* name);
525 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
527 #endif /* __LUNAIX_VFS_H */