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