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