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