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