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 hlist_node fs_list;
105 int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
106 int (*unmount)(struct v_superblock* vsb);
111 struct llist_header sb_list;
113 struct v_dnode* root;
114 struct filesystem* fs;
115 struct hbucket* i_cache;
120 u32_t (*read_capacity)(struct v_superblock* vsb);
121 u32_t (*read_usage)(struct v_superblock* vsb);
122 void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
130 void (*read_complete_callback)(struct dir_context* dctx,
138 int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
139 int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
141 // for operatiosn {write|read}_page, following are true:
142 // + `len` always equals to PG_SIZE
143 // + `fpos` always PG_SIZE aligned.
144 // These additional operations allow underlying fs to use more specialized
145 // and optimized code.
147 int (*write_page)(struct v_inode* inode, void* pg, size_t fpos);
148 int (*read_page)(struct v_inode* inode, void* pg, size_t fpos);
150 int (*readdir)(struct v_file* file, struct dir_context* dctx);
151 int (*seek)(struct v_inode* inode, size_t offset); // optional
152 int (*close)(struct v_file* file);
153 int (*sync)(struct v_file* file);
158 int (*create)(struct v_inode* this, struct v_dnode* dnode);
159 int (*open)(struct v_inode* this, struct v_file* file);
160 int (*sync)(struct v_inode* this);
161 int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
162 int (*rmdir)(struct v_inode* this, struct v_dnode* dir);
163 int (*unlink)(struct v_inode* this);
164 int (*link)(struct v_inode* this, struct v_dnode* new_name);
165 int (*read_symlink)(struct v_inode* this, const char** path_out);
166 int (*set_symlink)(struct v_inode* this, const char* target);
167 int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
168 int (*rename)(struct v_inode* from_inode,
169 struct v_dnode* from_dnode,
170 struct v_dnode* to_dnode);
171 int (*getxattr)(struct v_inode* this,
172 struct v_xattr_entry* entry); // optional
173 int (*setxattr)(struct v_inode* this,
174 struct v_xattr_entry* entry); // optional
175 int (*delxattr)(struct v_inode* this,
176 struct v_xattr_entry* entry); // optional
181 struct llist_header entries;
189 struct v_inode* inode;
190 struct v_dnode* dnode;
191 struct llist_header* f_list;
193 atomic_ulong ref_count;
194 struct v_file_ops* ops; // for caching
203 // [v_inode::aka_nodes]
204 // how do we invalidate corresponding v_dnodes given the v_inode?
206 Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
207 info of every process being accessible via file system. Each process's
208 creation will result a creation of a directory under the root of task fs
209 with it's pid as name. But that dir must delete when process is killed, and
210 such deletion does not mediated by vfs itself, so there is a need of cache
212 And this is also the case of all ramfs where argumentation to file tree is
213 performed by third party.
229 void* data; // 允许底层FS绑定他的一些专有数据
230 struct llist_header aka_dnodes;
231 struct llist_header xattrs;
232 struct v_superblock* sb;
233 struct hlist_node hash_list;
235 struct pcache* pg_cache;
236 struct v_inode_ops* ops;
237 struct v_file_ops* default_fops;
239 void (*destruct)(struct v_inode* inode);
245 struct llist_header list;
246 struct llist_header submnts;
247 struct llist_header sibmnts;
248 struct v_mount* parent;
249 struct v_dnode* mnt_point;
250 struct v_superblock* super_block;
257 mutex_t lock; // sync the path walking
260 struct v_inode* inode;
261 struct v_dnode* parent;
262 struct hlist_node hash_list;
263 struct llist_header aka_list;
264 struct llist_header children;
265 struct llist_header siblings;
266 struct v_superblock* super_block;
268 atomic_ulong ref_count;
275 struct v_fd* fds[VFS_MAX_FD];
280 struct v_inode* master;
282 struct llist_header pages;
283 struct llist_header dirty;
290 struct llist_header pg_list;
291 struct llist_header dirty_list;
293 struct pcache* holder;
307 fsm_new_fs(char* name, size_t name_len);
310 fsm_register(struct filesystem* fs);
313 fsm_get(const char* fs_name);
319 vfs_export_attributes();
322 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
325 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
328 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
331 vfs_dcache_remove(struct v_dnode* dnode);
334 vfs_walk(struct v_dnode* start,
336 struct v_dnode** dentry,
337 struct hstr* component,
341 vfs_walk_proc(const char* path,
342 struct v_dnode** dentry,
343 struct hstr* component,
347 vfs_mount(const char* target,
349 struct device* device,
353 vfs_unmount(const char* target);
356 vfs_mount_at(const char* fs_name,
357 struct device* device,
358 struct v_dnode* mnt_point,
362 vfs_unmount_at(struct v_dnode* mnt_point);
365 vfs_mkdir(const char* path, struct v_dnode** dentry);
368 vfs_open(struct v_dnode* dnode, struct v_file** file);
371 vfs_pclose(struct v_file* file, pid_t pid);
374 vfs_close(struct v_file* file);
377 vfs_free_fd(struct v_fd* fd);
380 vfs_fsync(struct v_file* file);
383 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
389 vfs_sb_free(struct v_superblock* sb);
395 vfs_d_free(struct v_dnode* dnode);
398 vfs_i_find(struct v_superblock* sb, u32_t i_id);
401 vfs_i_addhash(struct v_inode* inode);
404 vfs_i_alloc(struct v_superblock* sb);
407 vfs_i_free(struct v_inode* inode);
410 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
413 vfs_getfd(int fd, struct v_fd** fd_s);
416 vfs_get_dtype(int itype);
419 vfs_ref_dnode(struct v_dnode* dnode);
422 vfs_ref_file(struct v_file* file);
425 vfs_unref_dnode(struct v_dnode* dnode);
428 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
431 pcache_init(struct pcache* pcache);
434 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
437 pcache_new_page(struct pcache* pcache, u32_t index);
440 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
443 pcache_get_page(struct pcache* pcache,
446 struct pcache_pg** page);
449 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
452 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
455 pcache_release(struct pcache* pcache);
458 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
461 pcache_commit_all(struct v_inode* inode);
464 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
472 mnt_mkbusy(struct v_mount* mnt);
480 mnt_chillax(struct v_mount* mnt);
483 vfs_mount_root(const char* fs_name, struct device* device);
486 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
489 vfs_check_writable(struct v_dnode* dnode);
492 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
495 default_file_write(struct v_inode* inode,
501 default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
504 default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
507 default_file_readdir(struct v_file* file, struct dir_context* dctx);
510 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
513 default_inode_rename(struct v_inode* from_inode,
514 struct v_dnode* from_dnode,
515 struct v_dnode* to_dnode);
518 default_file_close(struct v_file* file);
521 default_file_seek(struct v_inode* inode, size_t offset);
524 default_inode_open(struct v_inode* this, struct v_file* file);
527 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
530 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
532 struct v_xattr_entry*
533 xattr_new(struct hstr* name);
535 struct v_xattr_entry*
536 xattr_getcache(struct v_inode* inode, struct hstr* name);
539 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
541 #endif /* __LUNAIX_VFS_H */