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