feat: support ioctl() syscall for direct control to devices
[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 struct v_dnode*
285 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
286
287 void
288 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
289
290 void
291 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
292
293 void
294 vfs_dcache_remove(struct v_dnode* dnode);
295
296 int
297 vfs_walk(struct v_dnode* start,
298          const char* path,
299          struct v_dnode** dentry,
300          struct hstr* component,
301          int walk_options);
302
303 int
304 vfs_walk_proc(const char* path,
305               struct v_dnode** dentry,
306               struct hstr* component,
307               int options);
308
309 int
310 vfs_mount(const char* target,
311           const char* fs_name,
312           struct device* device,
313           int options);
314
315 int
316 vfs_unmount(const char* target);
317
318 int
319 vfs_mount_at(const char* fs_name,
320              struct device* device,
321              struct v_dnode* mnt_point,
322              int options);
323
324 int
325 vfs_unmount_at(struct v_dnode* mnt_point);
326
327 int
328 vfs_mkdir(const char* path, struct v_dnode** dentry);
329
330 int
331 vfs_open(struct v_dnode* dnode, struct v_file** file);
332
333 int
334 vfs_close(struct v_file* file);
335
336 int
337 vfs_fsync(struct v_file* file);
338
339 void
340 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
341
342 struct v_superblock*
343 vfs_sb_alloc();
344
345 void
346 vfs_sb_free(struct v_superblock* sb);
347
348 struct v_dnode*
349 vfs_d_alloc();
350
351 void
352 vfs_d_free(struct v_dnode* dnode);
353
354 struct v_inode*
355 vfs_i_find(struct v_superblock* sb, uint32_t i_id);
356
357 void
358 vfs_i_addhash(struct v_inode* inode);
359
360 struct v_inode*
361 vfs_i_alloc(struct v_superblock* sb);
362
363 void
364 vfs_i_free(struct v_inode* inode);
365
366 int
367 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
368
369 int
370 vfs_getfd(int fd, struct v_fd** fd_s);
371
372 int
373 vfs_get_dtype(int itype);
374
375 void
376 vfs_ref_dnode(struct v_dnode* dnode);
377
378 void
379 vfs_unref_dnode(struct v_dnode* dnode);
380
381 void
382 pcache_init(struct pcache* pcache);
383
384 void
385 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
386
387 struct pcache_pg*
388 pcache_new_page(struct pcache* pcache, uint32_t index);
389
390 void
391 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
392
393 int
394 pcache_get_page(struct pcache* pcache,
395                 uint32_t index,
396                 uint32_t* offset,
397                 struct pcache_pg** page);
398
399 int
400 pcache_write(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos);
401
402 int
403 pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos);
404
405 void
406 pcache_release(struct pcache* pcache);
407
408 int
409 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
410
411 void
412 pcache_commit_all(struct v_inode* inode);
413
414 void
415 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
416
417 /**
418  * @brief 将挂载点标记为繁忙
419  *
420  * @param mnt
421  */
422 void
423 mnt_mkbusy(struct v_mount* mnt);
424
425 /**
426  * @brief 将挂载点标记为清闲
427  *
428  * @param mnt
429  */
430 void
431 mnt_chillax(struct v_mount* mnt);
432
433 int
434 vfs_mount_root(const char* fs_name, struct device* device);
435
436 struct v_mount*
437 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
438
439 int
440 vfs_check_writable(struct v_dnode* dnode);
441
442 int
443 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
444
445 int
446 default_file_write(struct v_inode* inode,
447                    void* buffer,
448                    size_t len,
449                    size_t fpos);
450
451 int
452 default_file_readdir(struct v_file* file, struct dir_context* dctx);
453
454 int
455 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
456
457 int
458 default_inode_rename(struct v_inode* from_inode,
459                      struct v_dnode* from_dnode,
460                      struct v_dnode* to_dnode);
461
462 int
463 default_file_close(struct v_file* file);
464
465 int
466 default_file_seek(struct v_inode* inode, size_t offset);
467
468 int
469 default_inode_open(struct v_inode* this, struct v_file* file);
470
471 int
472 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
473
474 int
475 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
476
477 struct v_xattr_entry*
478 xattr_new(struct hstr* name);
479
480 struct v_xattr_entry*
481 xattr_getcache(struct v_inode* inode, struct hstr* name);
482
483 void
484 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
485
486 #endif /* __LUNAIX_VFS_H */