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