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>
15 #include <stdatomic.h>
17 #include <usr/lunaix/fstypes.h>
19 #define VFS_NAME_MAXLEN 128
22 #define VFS_IFDIR F_DIR
23 #define VFS_IFFILE F_FILE
24 #define VFS_IFDEV (F_DEV | F_FILE)
25 #define VFS_IFSEQDEV (F_SEQDEV | F_FILE)
26 #define VFS_IFVOLDEV (F_VOLDEV | F_FILE)
27 #define VFS_IFSYMLINK (F_SYMLINK | F_FILE)
29 #define VFS_DEVFILE(type) ((type) & F_DEV)
30 #define VFS_DEVTYPE(type) ((type) & ((F_SEQDEV | F_VOLDEV) ^ F_DEV))
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 0x1
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 typedef u32_t inode_t;
92 extern struct v_file_ops default_file_ops;
93 extern struct v_inode_ops default_inode_ops;
95 extern struct hstr vfs_ddot;
96 extern struct hstr vfs_dot;
97 extern struct v_dnode* vfs_sysroot;
101 struct llist_header fs_flat;
102 struct hlist_node fs_list;
106 int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
107 int (*unmount)(struct v_superblock* vsb);
112 struct llist_header sb_list;
114 struct v_dnode* root;
115 struct filesystem* fs;
116 struct hbucket* i_cache;
121 u32_t (*read_capacity)(struct v_superblock* vsb);
122 u32_t (*read_usage)(struct v_superblock* vsb);
123 void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
131 void (*read_complete_callback)(struct dir_context* dctx,
139 int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
140 int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
142 // for operatiosn {write|read}_page, following are true:
143 // + `len` always equals to PG_SIZE
144 // + `fpos` always PG_SIZE aligned.
145 // These additional operations allow underlying fs to use more specialized
146 // and optimized code.
148 int (*write_page)(struct v_inode* inode, void* pg, size_t fpos);
149 int (*read_page)(struct v_inode* inode, void* pg, size_t fpos);
151 int (*readdir)(struct v_file* file, struct dir_context* dctx);
152 int (*seek)(struct v_inode* inode, size_t offset); // optional
153 int (*close)(struct v_file* file);
154 int (*sync)(struct v_file* file);
159 int (*create)(struct v_inode* this, struct v_dnode* dnode);
160 int (*open)(struct v_inode* this, struct v_file* file);
161 int (*sync)(struct v_inode* this);
162 int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
163 int (*rmdir)(struct v_inode* this, struct v_dnode* dir);
164 int (*unlink)(struct v_inode* this);
165 int (*link)(struct v_inode* this, struct v_dnode* new_name);
166 int (*read_symlink)(struct v_inode* this, const char** path_out);
167 int (*set_symlink)(struct v_inode* this, const char* target);
168 int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
169 int (*rename)(struct v_inode* from_inode,
170 struct v_dnode* from_dnode,
171 struct v_dnode* to_dnode);
172 int (*getxattr)(struct v_inode* this,
173 struct v_xattr_entry* entry); // optional
174 int (*setxattr)(struct v_inode* this,
175 struct v_xattr_entry* entry); // optional
176 int (*delxattr)(struct v_inode* this,
177 struct v_xattr_entry* entry); // optional
182 struct llist_header entries;
190 struct v_inode* inode;
191 struct v_dnode* dnode;
192 struct llist_header* f_list;
194 atomic_ulong ref_count;
195 struct v_file_ops* ops; // for caching
204 // [v_inode::aka_nodes]
205 // how do we invalidate corresponding v_dnodes given the v_inode?
207 Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
208 info of every process being accessible via file system. Each process's
209 creation will result a creation of a directory under the root of task fs
210 with it's pid as name. But that dir must delete when process is killed, and
211 such deletion does not mediated by vfs itself, so there is a need of cache
213 And this is also the case of all ramfs where argumentation to file tree is
214 performed by third party.
230 void* data; // 允许底层FS绑定他的一些专有数据
231 struct llist_header aka_dnodes;
232 struct llist_header xattrs;
233 struct v_superblock* sb;
234 struct hlist_node hash_list;
236 struct pcache* pg_cache;
237 struct v_inode_ops* ops;
238 struct v_file_ops* default_fops;
240 void (*destruct)(struct v_inode* inode);
246 struct llist_header list;
247 struct llist_header submnts;
248 struct llist_header sibmnts;
249 struct v_mount* parent;
250 struct v_dnode* mnt_point;
251 struct v_superblock* super_block;
258 mutex_t lock; // sync the path walking
261 struct v_inode* inode;
262 struct v_dnode* parent;
263 struct hlist_node hash_list;
264 struct llist_header aka_list;
265 struct llist_header children;
266 struct llist_header siblings;
267 struct v_superblock* super_block;
269 atomic_ulong ref_count;
276 struct v_fd* fds[VFS_MAX_FD];
281 struct v_inode* master;
283 struct llist_header pages;
284 struct llist_header dirty;
291 struct llist_header pg_list;
292 struct llist_header dirty_list;
294 struct pcache* holder;
308 fsm_new_fs(char* name, size_t name_len);
311 fsm_register(struct filesystem* fs);
314 fsm_get(const char* fs_name);
320 vfs_export_attributes();
323 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
326 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
329 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
332 vfs_dcache_remove(struct v_dnode* dnode);
335 vfs_walk(struct v_dnode* start,
337 struct v_dnode** dentry,
338 struct hstr* component,
342 vfs_walk_proc(const char* path,
343 struct v_dnode** dentry,
344 struct hstr* component,
348 vfs_mount(const char* target,
350 struct device* device,
354 vfs_unmount(const char* target);
357 vfs_mount_at(const char* fs_name,
358 struct device* device,
359 struct v_dnode* mnt_point,
363 vfs_unmount_at(struct v_dnode* mnt_point);
366 vfs_mkdir(const char* path, struct v_dnode** dentry);
369 vfs_open(struct v_dnode* dnode, struct v_file** file);
372 vfs_pclose(struct v_file* file, pid_t pid);
375 vfs_close(struct v_file* file);
378 vfs_free_fd(struct v_fd* fd);
381 vfs_fsync(struct v_file* file);
384 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
390 vfs_sb_free(struct v_superblock* sb);
396 vfs_d_free(struct v_dnode* dnode);
399 vfs_i_find(struct v_superblock* sb, u32_t i_id);
402 vfs_i_addhash(struct v_inode* inode);
405 vfs_i_alloc(struct v_superblock* sb);
408 vfs_i_free(struct v_inode* inode);
411 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
414 vfs_getfd(int fd, struct v_fd** fd_s);
417 vfs_get_dtype(int itype);
420 vfs_ref_dnode(struct v_dnode* dnode);
423 vfs_ref_file(struct v_file* file);
426 vfs_unref_dnode(struct v_dnode* dnode);
429 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
432 pcache_init(struct pcache* pcache);
435 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
438 pcache_new_page(struct pcache* pcache, u32_t index);
441 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
444 pcache_get_page(struct pcache* pcache,
447 struct pcache_pg** page);
450 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
453 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
456 pcache_release(struct pcache* pcache);
459 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
462 pcache_commit_all(struct v_inode* inode);
465 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
473 mnt_mkbusy(struct v_mount* mnt);
481 mnt_chillax(struct v_mount* mnt);
484 vfs_mount_root(const char* fs_name, struct device* device);
487 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
490 vfs_check_writable(struct v_dnode* dnode);
493 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
496 default_file_write(struct v_inode* inode,
502 default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
505 default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
508 default_file_readdir(struct v_file* file, struct dir_context* dctx);
511 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
514 default_inode_rename(struct v_inode* from_inode,
515 struct v_dnode* from_dnode,
516 struct v_dnode* to_dnode);
519 default_file_close(struct v_file* file);
522 default_file_seek(struct v_inode* inode, size_t offset);
525 default_inode_open(struct v_inode* this, struct v_file* file);
528 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
531 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
533 struct v_xattr_entry*
534 xattr_new(struct hstr* name);
536 struct v_xattr_entry*
537 xattr_getcache(struct v_inode* inode, struct hstr* name);
540 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
542 #endif /* __LUNAIX_VFS_H */