feat: (iso9660) finishing up unmount
[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/llist.h>
10 #include <lunaix/ds/lru.h>
11 #include <lunaix/ds/mutex.h>
12 #include <lunaix/process.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 0x16
24
25 #define VFS_WALK_MKPARENT 0x1
26 #define VFS_WALK_FSRELATIVE 0x2
27 #define VFS_WALK_PARENT 0x4
28 #define VFS_WALK_NOFOLLOW 0x8
29
30 #define VFS_HASHTABLE_BITS 10
31 #define VFS_HASHTABLE_SIZE (1 << VFS_HASHTABLE_BITS)
32 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
33 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
34
35 #define VFS_PATH_DELIM '/'
36
37 #define FSTYPE_ROFS 0x1
38
39 #define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
40 #define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; })
41
42 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
43
44 #define VFS_VALID_CHAR(chr)                                                    \
45     (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') ||       \
46      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
47      (chr) == '-' || (chr) == ':')
48
49 #define unlock_inode(inode) mutex_unlock(&inode->lock)
50 #define lock_inode(inode)                                                      \
51     ({                                                                         \
52         mutex_lock(&inode->lock);                                              \
53         lru_use_one(inode_lru, &inode->lru);                                   \
54     })
55
56 #define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
57 #define lock_dnode(dnode)                                                      \
58     ({                                                                         \
59         mutex_lock(&dnode->lock);                                              \
60         lru_use_one(dnode_lru, &dnode->lru);                                   \
61     })
62
63 typedef u32_t inode_t;
64
65 struct v_dnode;
66 struct v_inode;
67 struct v_superblock;
68 struct v_file;
69 struct v_file_ops;
70 struct v_inode_ops;
71 struct v_fd;
72 struct pcache;
73 struct v_xattr_entry;
74
75 extern struct v_file_ops default_file_ops;
76 extern struct v_inode_ops default_inode_ops;
77
78 extern struct hstr vfs_ddot;
79 extern struct hstr vfs_dot;
80 extern struct v_dnode* vfs_sysroot;
81
82 struct filesystem
83 {
84     struct hlist_node fs_list;
85     struct hstr fs_name;
86     u32_t types;
87     int fs_id;
88     int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point);
89     int (*unmount)(struct v_superblock* vsb);
90 };
91
92 struct v_superblock
93 {
94     struct llist_header sb_list;
95     struct device* dev;
96     struct v_dnode* root;
97     struct filesystem* fs;
98     u32_t iobuf_size;
99     struct hbucket* i_cache;
100     void* data;
101     struct
102     {
103         u32_t (*read_capacity)(struct v_superblock* vsb);
104         u32_t (*read_usage)(struct v_superblock* vsb);
105         void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
106     } ops;
107 };
108
109 struct dir_context
110 {
111     int index;
112     void* cb_data;
113     void (*read_complete_callback)(struct dir_context* dctx,
114                                    const char* name,
115                                    const int len,
116                                    const int dtype);
117 };
118
119 struct v_file_ops
120 {
121     int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
122     int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
123
124     // for operatiosn {write|read}_page, following are true:
125     //  + `len` always equals to PG_SIZE
126     //  + `fpos` always PG_SIZE aligned.
127     // These additional operations allow underlying fs to use more specialized
128     // and optimized code.
129
130     int (*write_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
131     int (*read_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
132
133     int (*readdir)(struct v_file* file, struct dir_context* dctx);
134     int (*seek)(struct v_inode* inode, size_t offset); // optional
135     int (*close)(struct v_file* file);
136     int (*sync)(struct v_file* file);
137 };
138
139 struct v_inode_ops
140 {
141     int (*create)(struct v_inode* this, struct v_dnode* dnode);
142     int (*open)(struct v_inode* this, struct v_file* file);
143     int (*sync)(struct v_inode* this);
144     int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
145     int (*rmdir)(struct v_inode* this, struct v_dnode* dir);
146     int (*unlink)(struct v_inode* this);
147     int (*link)(struct v_inode* this, struct v_dnode* new_name);
148     int (*read_symlink)(struct v_inode* this, const char** path_out);
149     int (*set_symlink)(struct v_inode* this, const char* target);
150     int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
151     int (*rename)(struct v_inode* from_inode,
152                   struct v_dnode* from_dnode,
153                   struct v_dnode* to_dnode);
154     int (*getxattr)(struct v_inode* this,
155                     struct v_xattr_entry* entry); // optional
156     int (*setxattr)(struct v_inode* this,
157                     struct v_xattr_entry* entry); // optional
158     int (*delxattr)(struct v_inode* this,
159                     struct v_xattr_entry* entry); // optional
160 };
161
162 struct v_xattr_entry
163 {
164     struct llist_header entries;
165     struct hstr name;
166     const void* value;
167     size_t len;
168 };
169
170 struct v_file
171 {
172     struct v_inode* inode;
173     struct v_dnode* dnode;
174     struct llist_header* f_list;
175     u32_t f_pos;
176     atomic_ulong ref_count;
177     struct v_file_ops* ops; // for caching
178 };
179
180 struct v_fd
181 {
182     struct v_file* file;
183     int flags;
184 };
185
186 //  [v_inode::aka_nodes]
187 //  how do we invalidate corresponding v_dnodes given the v_inode?
188 /*
189     Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
190     info of every process being accessible via file system. Each process's
191     creation will result a creation of a directory under the root of task fs
192     with it's pid as name. But that dir must delete when process is killed, and
193     such deletion does not mediated by vfs itself, so there is a need of cache
194     syncing.
195     And this is also the case of all ramfs where argumentation to file tree is
196     performed by third party.
197 */
198
199 struct v_inode
200 {
201     inode_t id;
202     mutex_t lock;
203     u32_t itype;
204     time_t ctime;
205     time_t mtime;
206     time_t atime;
207     lba_t lb_addr;
208     u32_t open_count;
209     u32_t link_count;
210     u32_t lb_usage;
211     u32_t fsize;
212     void* data; // 允许底层FS绑定他的一些专有数据
213     struct llist_header aka_dnodes;
214     struct llist_header xattrs;
215     struct v_superblock* sb;
216     struct hlist_node hash_list;
217     struct lru_node lru;
218     struct pcache* pg_cache;
219     struct v_inode_ops* ops;
220     struct v_file_ops* default_fops;
221
222     void (*destruct)(struct v_inode* inode);
223 };
224
225 struct v_mount
226 {
227     mutex_t lock;
228     struct llist_header list;
229     struct llist_header submnts;
230     struct llist_header sibmnts;
231     struct v_mount* parent;
232     struct v_dnode* mnt_point;
233     struct v_superblock* super_block;
234     u32_t busy_counter;
235     int flags;
236 };
237
238 struct v_dnode
239 {
240     mutex_t lock; // sync the path walking
241     struct lru_node lru;
242     struct hstr name;
243     struct v_inode* inode;
244     struct v_dnode* parent;
245     struct hlist_node hash_list;
246     struct llist_header aka_list;
247     struct llist_header children;
248     struct llist_header siblings;
249     struct v_superblock* super_block;
250     struct v_mount* mnt;
251     atomic_ulong ref_count;
252
253     void* data;
254 };
255
256 struct v_fdtable
257 {
258     struct v_fd* fds[VFS_MAX_FD];
259 };
260
261 struct pcache
262 {
263     struct v_inode* master;
264     struct btrie tree;
265     struct llist_header pages;
266     struct llist_header dirty;
267     u32_t n_dirty;
268     u32_t n_pages;
269 };
270
271 struct pcache_pg
272 {
273     struct llist_header pg_list;
274     struct llist_header dirty_list;
275     struct lru_node lru;
276     struct pcache* holder;
277     void* pg;
278     u32_t flags;
279     u32_t fpos;
280     u32_t len;
281 };
282
283 void
284 fsm_init();
285
286 void
287 fsm_register_all();
288
289 struct filesystem*
290 fsm_new_fs(char* name, size_t name_len);
291
292 void
293 fsm_register(struct filesystem* fs);
294
295 struct filesystem*
296 fsm_get(const char* fs_name);
297
298 void
299 vfs_init();
300
301 void
302 vfs_export_attributes();
303
304 struct v_dnode*
305 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
306
307 void
308 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
309
310 void
311 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
312
313 void
314 vfs_dcache_remove(struct v_dnode* dnode);
315
316 int
317 vfs_walk(struct v_dnode* start,
318          const char* path,
319          struct v_dnode** dentry,
320          struct hstr* component,
321          int walk_options);
322
323 int
324 vfs_walk_proc(const char* path,
325               struct v_dnode** dentry,
326               struct hstr* component,
327               int options);
328
329 int
330 vfs_mount(const char* target,
331           const char* fs_name,
332           struct device* device,
333           int options);
334
335 int
336 vfs_unmount(const char* target);
337
338 int
339 vfs_mount_at(const char* fs_name,
340              struct device* device,
341              struct v_dnode* mnt_point,
342              int options);
343
344 int
345 vfs_unmount_at(struct v_dnode* mnt_point);
346
347 int
348 vfs_mkdir(const char* path, struct v_dnode** dentry);
349
350 int
351 vfs_open(struct v_dnode* dnode, struct v_file** file);
352
353 int
354 vfs_pclose(struct v_file* file, pid_t pid);
355
356 int
357 vfs_close(struct v_file* file);
358
359 void
360 vfs_free_fd(struct v_fd* fd);
361
362 int
363 vfs_fsync(struct v_file* file);
364
365 void
366 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
367
368 struct v_superblock*
369 vfs_sb_alloc();
370
371 void
372 vfs_sb_free(struct v_superblock* sb);
373
374 struct v_dnode*
375 vfs_d_alloc();
376
377 void
378 vfs_d_free(struct v_dnode* dnode);
379
380 struct v_inode*
381 vfs_i_find(struct v_superblock* sb, u32_t i_id);
382
383 void
384 vfs_i_addhash(struct v_inode* inode);
385
386 struct v_inode*
387 vfs_i_alloc(struct v_superblock* sb);
388
389 void
390 vfs_i_free(struct v_inode* inode);
391
392 int
393 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
394
395 int
396 vfs_getfd(int fd, struct v_fd** fd_s);
397
398 int
399 vfs_get_dtype(int itype);
400
401 void
402 vfs_ref_dnode(struct v_dnode* dnode);
403
404 void
405 vfs_unref_dnode(struct v_dnode* dnode);
406
407 int
408 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
409
410 void
411 pcache_init(struct pcache* pcache);
412
413 void
414 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
415
416 struct pcache_pg*
417 pcache_new_page(struct pcache* pcache, u32_t index);
418
419 void
420 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
421
422 int
423 pcache_get_page(struct pcache* pcache,
424                 u32_t index,
425                 u32_t* offset,
426                 struct pcache_pg** page);
427
428 int
429 pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
430
431 int
432 pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos);
433
434 void
435 pcache_release(struct pcache* pcache);
436
437 int
438 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
439
440 void
441 pcache_commit_all(struct v_inode* inode);
442
443 void
444 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
445
446 /**
447  * @brief 将挂载点标记为繁忙
448  *
449  * @param mnt
450  */
451 void
452 mnt_mkbusy(struct v_mount* mnt);
453
454 /**
455  * @brief 将挂载点标记为清闲
456  *
457  * @param mnt
458  */
459 void
460 mnt_chillax(struct v_mount* mnt);
461
462 int
463 vfs_mount_root(const char* fs_name, struct device* device);
464
465 struct v_mount*
466 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
467
468 int
469 vfs_check_writable(struct v_dnode* dnode);
470
471 int
472 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
473
474 int
475 default_file_write(struct v_inode* inode,
476                    void* buffer,
477                    size_t len,
478                    size_t fpos);
479
480 int
481 default_file_readdir(struct v_file* file, struct dir_context* dctx);
482
483 int
484 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
485
486 int
487 default_inode_rename(struct v_inode* from_inode,
488                      struct v_dnode* from_dnode,
489                      struct v_dnode* to_dnode);
490
491 int
492 default_file_close(struct v_file* file);
493
494 int
495 default_file_seek(struct v_inode* inode, size_t offset);
496
497 int
498 default_inode_open(struct v_inode* this, struct v_file* file);
499
500 int
501 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
502
503 int
504 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
505
506 struct v_xattr_entry*
507 xattr_new(struct hstr* name);
508
509 struct v_xattr_entry*
510 xattr_getcache(struct v_inode* inode, struct hstr* name);
511
512 void
513 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
514
515 #endif /* __LUNAIX_VFS_H */