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