feat: device subsystem rework
[lunaix-os.git] / lunaix-os / includes / lunaix / fs.h
1 #ifndef __LUNAIX_VFS_H
2 #define __LUNAIX_VFS_H
3
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>
15
16 #define VFS_NAME_MAXLEN 128
17 #define VFS_MAX_FD 32
18
19 #define VFS_IFDIR 0x1
20 #define VFS_IFFILE 0x2
21 #define VFS_IFSEQDEV 0x4
22 #define VFS_IFVOLDEV 0x8
23 #define VFS_IFSYMLINK 0x10
24
25 // Walk, mkdir if component encountered is non-exists.
26 #define VFS_WALK_MKPARENT 0x1
27
28 // Walk, relative to current FS.
29 #define VFS_WALK_FSRELATIVE 0x2
30
31 /*
32     Terminate the walk on the immediate parent,
33     name of child (last component) is returned through `component`
34 */
35 #define VFS_WALK_PARENT 0x4
36
37 // Do not follow the symbolic link
38 #define VFS_WALK_NOFOLLOW 0x8
39
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)
44
45 #define VFS_PATH_DELIM '/'
46
47 #define FSTYPE_ROFS 0x1
48
49 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
50
51 #define EXPORT_FILE_SYSTEM(fs_id, init_fn)                                        \
52     export_ldga_el(fs, fs_id, ptr_t, init_fn)
53
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) == ':')
58
59 #define unlock_inode(inode) mutex_unlock(&inode->lock)
60 #define lock_inode(inode)                                                      \
61     ({                                                                         \
62         mutex_lock(&inode->lock);                                              \
63         lru_use_one(inode_lru, &inode->lru);                                   \
64     })
65
66 #define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
67 #define lock_dnode(dnode)                                                      \
68     ({                                                                         \
69         mutex_lock(&dnode->lock);                                              \
70         lru_use_one(dnode_lru, &dnode->lru);                                   \
71     })
72
73 typedef u32_t inode_t;
74
75 struct v_dnode;
76 struct v_inode;
77 struct v_superblock;
78 struct v_file;
79 struct v_file_ops;
80 struct v_inode_ops;
81 struct v_fd;
82 struct pcache;
83 struct v_xattr_entry;
84
85 extern struct v_file_ops default_file_ops;
86 extern struct v_inode_ops default_inode_ops;
87
88 extern struct hstr vfs_ddot;
89 extern struct hstr vfs_dot;
90 extern struct v_dnode* vfs_sysroot;
91
92 struct filesystem
93 {
94     struct hlist_node fs_list;
95     struct hstr fs_name;
96     u32_t types;
97     int fs_id;
98     int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
99     int (*unmount)(struct v_superblock* vsb);
100 };
101
102 struct v_superblock
103 {
104     struct llist_header sb_list;
105     struct device* dev;
106     struct v_dnode* root;
107     struct filesystem* fs;
108     struct hbucket* i_cache;
109     void* data;
110     struct
111     {
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);
115     } ops;
116 };
117
118 struct dir_context
119 {
120     int index;
121     void* cb_data;
122     void (*read_complete_callback)(struct dir_context* dctx,
123                                    const char* name,
124                                    const int len,
125                                    const int dtype);
126 };
127
128 struct v_file_ops
129 {
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);
132
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.
138
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);
141
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);
146 };
147
148 struct v_inode_ops
149 {
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
169 };
170
171 struct v_xattr_entry
172 {
173     struct llist_header entries;
174     struct hstr name;
175     const void* value;
176     size_t len;
177 };
178
179 struct v_file
180 {
181     struct v_inode* inode;
182     struct v_dnode* dnode;
183     struct llist_header* f_list;
184     u32_t f_pos;
185     atomic_ulong ref_count;
186     struct v_file_ops* ops; // for caching
187 };
188
189 struct v_fd
190 {
191     struct v_file* file;
192     int flags;
193 };
194
195 //  [v_inode::aka_nodes]
196 //  how do we invalidate corresponding v_dnodes given the v_inode?
197 /*
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
203     syncing.
204     And this is also the case of all ramfs where argumentation to file tree is
205     performed by third party.
206 */
207
208 struct v_inode
209 {
210     inode_t id;
211     mutex_t lock;
212     u32_t itype;
213     time_t ctime;
214     time_t mtime;
215     time_t atime;
216     lba_t lb_addr;
217     u32_t open_count;
218     u32_t link_count;
219     u32_t lb_usage;
220     u32_t fsize;
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;
226     struct lru_node lru;
227     struct pcache* pg_cache;
228     struct v_inode_ops* ops;
229     struct v_file_ops* default_fops;
230
231     void (*destruct)(struct v_inode* inode);
232 };
233
234 struct v_mount
235 {
236     mutex_t lock;
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;
243     u32_t busy_counter;
244     int flags;
245 };
246
247 struct v_dnode
248 {
249     mutex_t lock; // sync the path walking
250     struct lru_node lru;
251     struct hstr name;
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;
259     struct v_mount* mnt;
260     atomic_ulong ref_count;
261
262     void* data;
263 };
264
265 struct v_fdtable
266 {
267     struct v_fd* fds[VFS_MAX_FD];
268 };
269
270 struct pcache
271 {
272     struct v_inode* master;
273     struct btrie tree;
274     struct llist_header pages;
275     struct llist_header dirty;
276     u32_t n_dirty;
277     u32_t n_pages;
278 };
279
280 struct pcache_pg
281 {
282     struct llist_header pg_list;
283     struct llist_header dirty_list;
284     struct lru_node lru;
285     struct pcache* holder;
286     void* pg;
287     u32_t flags;
288     u32_t fpos;
289     u32_t len;
290 };
291
292 void
293 fsm_init();
294
295 void
296 fsm_register_all();
297
298 struct filesystem*
299 fsm_new_fs(char* name, size_t name_len);
300
301 void
302 fsm_register(struct filesystem* fs);
303
304 struct filesystem*
305 fsm_get(const char* fs_name);
306
307 void
308 vfs_init();
309
310 void
311 vfs_export_attributes();
312
313 struct v_dnode*
314 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
315
316 void
317 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
318
319 void
320 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
321
322 void
323 vfs_dcache_remove(struct v_dnode* dnode);
324
325 int
326 vfs_walk(struct v_dnode* start,
327          const char* path,
328          struct v_dnode** dentry,
329          struct hstr* component,
330          int walk_options);
331
332 int
333 vfs_walk_proc(const char* path,
334               struct v_dnode** dentry,
335               struct hstr* component,
336               int options);
337
338 int
339 vfs_mount(const char* target,
340           const char* fs_name,
341           struct device* device,
342           int options);
343
344 int
345 vfs_unmount(const char* target);
346
347 int
348 vfs_mount_at(const char* fs_name,
349              struct device* device,
350              struct v_dnode* mnt_point,
351              int options);
352
353 int
354 vfs_unmount_at(struct v_dnode* mnt_point);
355
356 int
357 vfs_mkdir(const char* path, struct v_dnode** dentry);
358
359 int
360 vfs_open(struct v_dnode* dnode, struct v_file** file);
361
362 int
363 vfs_pclose(struct v_file* file, pid_t pid);
364
365 int
366 vfs_close(struct v_file* file);
367
368 void
369 vfs_free_fd(struct v_fd* fd);
370
371 int
372 vfs_fsync(struct v_file* file);
373
374 void
375 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
376
377 struct v_superblock*
378 vfs_sb_alloc();
379
380 void
381 vfs_sb_free(struct v_superblock* sb);
382
383 struct v_dnode*
384 vfs_d_alloc();
385
386 void
387 vfs_d_free(struct v_dnode* dnode);
388
389 struct v_inode*
390 vfs_i_find(struct v_superblock* sb, u32_t i_id);
391
392 void
393 vfs_i_addhash(struct v_inode* inode);
394
395 struct v_inode*
396 vfs_i_alloc(struct v_superblock* sb);
397
398 void
399 vfs_i_free(struct v_inode* inode);
400
401 int
402 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
403
404 int
405 vfs_getfd(int fd, struct v_fd** fd_s);
406
407 int
408 vfs_get_dtype(int itype);
409
410 void
411 vfs_ref_dnode(struct v_dnode* dnode);
412
413 void
414 vfs_ref_file(struct v_file* file);
415
416 void
417 vfs_unref_dnode(struct v_dnode* dnode);
418
419 int
420 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
421
422 void
423 pcache_init(struct pcache* pcache);
424
425 void
426 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
427
428 struct pcache_pg*
429 pcache_new_page(struct pcache* pcache, u32_t index);
430
431 void
432 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
433
434 int
435 pcache_get_page(struct pcache* pcache,
436                 u32_t index,
437                 u32_t* offset,
438                 struct pcache_pg** page);
439
440 int
441 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
442
443 int
444 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
445
446 void
447 pcache_release(struct pcache* pcache);
448
449 int
450 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
451
452 void
453 pcache_commit_all(struct v_inode* inode);
454
455 void
456 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
457
458 /**
459  * @brief 将挂载点标记为繁忙
460  *
461  * @param mnt
462  */
463 void
464 mnt_mkbusy(struct v_mount* mnt);
465
466 /**
467  * @brief 将挂载点标记为清闲
468  *
469  * @param mnt
470  */
471 void
472 mnt_chillax(struct v_mount* mnt);
473
474 int
475 vfs_mount_root(const char* fs_name, struct device* device);
476
477 struct v_mount*
478 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
479
480 int
481 vfs_check_writable(struct v_dnode* dnode);
482
483 int
484 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
485
486 int
487 default_file_write(struct v_inode* inode,
488                    void* buffer,
489                    size_t len,
490                    size_t fpos);
491
492 int
493 default_file_readdir(struct v_file* file, struct dir_context* dctx);
494
495 int
496 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
497
498 int
499 default_inode_rename(struct v_inode* from_inode,
500                      struct v_dnode* from_dnode,
501                      struct v_dnode* to_dnode);
502
503 int
504 default_file_close(struct v_file* file);
505
506 int
507 default_file_seek(struct v_inode* inode, size_t offset);
508
509 int
510 default_inode_open(struct v_inode* this, struct v_file* file);
511
512 int
513 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
514
515 int
516 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
517
518 struct v_xattr_entry*
519 xattr_new(struct hstr* name);
520
521 struct v_xattr_entry*
522 xattr_getcache(struct v_inode* inode, struct hstr* name);
523
524 void
525 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
526
527 #endif /* __LUNAIX_VFS_H */