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