feat: ability to manipulate extended attribute
[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) == '-')
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);
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, struct v_xattr_entry* entry);
144     int (*setxattr)(struct v_inode* this, struct v_xattr_entry* entry);
145     int (*delxattr)(struct v_inode* this, struct v_xattr_entry* entry);
146 };
147
148 struct v_xattr_entry
149 {
150     struct llist_header entries;
151     struct hstr name;
152     const void* value;
153     size_t len;
154 };
155
156 struct v_file
157 {
158     struct v_inode* inode;
159     struct v_dnode* dnode;
160     struct llist_header* f_list;
161     uint32_t f_pos;
162     atomic_ulong ref_count;
163     struct v_file_ops* ops; // for caching
164 };
165
166 struct v_fd
167 {
168     struct v_file* file;
169     int flags;
170 };
171
172 struct v_inode
173 {
174     inode_t id;
175     mutex_t lock;
176     uint32_t itype;
177     time_t ctime;
178     time_t mtime;
179     time_t atime;
180     lba_t lb_addr;
181     uint32_t open_count;
182     uint32_t link_count;
183     uint32_t lb_usage;
184     uint32_t fsize;
185     struct llist_header xattrs;
186     struct v_superblock* sb;
187     struct hlist_node hash_list;
188     struct lru_node lru;
189     struct pcache* pg_cache;
190     void* data; // 允许底层FS绑定他的一些专有数据
191     struct v_inode_ops* ops;
192     struct v_file_ops* default_fops;
193 };
194
195 struct v_mount
196 {
197     mutex_t lock;
198     struct llist_header list;
199     struct llist_header submnts;
200     struct llist_header sibmnts;
201     struct v_mount* parent;
202     struct v_dnode* mnt_point;
203     struct v_superblock* super_block;
204     uint32_t busy_counter;
205 };
206
207 struct v_dnode
208 {
209     mutex_t lock; // sync the path walking
210     struct lru_node lru;
211     struct hstr name;
212     struct v_inode* inode;
213     struct v_dnode* parent;
214     struct hlist_node hash_list;
215     struct llist_header children;
216     struct llist_header siblings;
217     struct v_superblock* super_block;
218     struct v_mount* mnt;
219     atomic_ulong ref_count;
220
221     void* data;
222 };
223
224 struct v_fdtable
225 {
226     struct v_fd* fds[VFS_MAX_FD];
227 };
228
229 struct pcache
230 {
231     struct v_inode* master;
232     struct btrie tree;
233     struct llist_header pages;
234     struct llist_header dirty;
235     uint32_t n_dirty;
236     uint32_t n_pages;
237 };
238
239 struct pcache_pg
240 {
241     struct llist_header pg_list;
242     struct llist_header dirty_list;
243     struct lru_node lru;
244     struct pcache* holder;
245     void* pg;
246     uint32_t flags;
247     uint32_t fpos;
248 };
249 /* --- file system manager --- */
250 void
251 fsm_init();
252
253 void
254 fsm_register_all();
255
256 struct filesystem*
257 fsm_new_fs(char* name, size_t name_len);
258
259 void
260 fsm_register(struct filesystem* fs);
261
262 struct filesystem*
263 fsm_get(const char* fs_name);
264
265 void
266 vfs_init();
267
268 struct v_dnode*
269 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
270
271 void
272 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
273
274 void
275 vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
276
277 void
278 vfs_dcache_remove(struct v_dnode* dnode);
279
280 int
281 vfs_walk(struct v_dnode* start,
282          const char* path,
283          struct v_dnode** dentry,
284          struct hstr* component,
285          int walk_options);
286
287 int
288 vfs_walk_proc(const char* path,
289               struct v_dnode** dentry,
290               struct hstr* component,
291               int options);
292
293 int
294 vfs_mount(const char* target, const char* fs_name, struct device* device);
295
296 int
297 vfs_unmount(const char* target);
298
299 int
300 vfs_mount_at(const char* fs_name,
301              struct device* device,
302              struct v_dnode* mnt_point);
303
304 int
305 vfs_unmount_at(struct v_dnode* mnt_point);
306
307 int
308 vfs_mkdir(const char* path, struct v_dnode** dentry);
309
310 int
311 vfs_open(struct v_dnode* dnode, struct v_file** file);
312
313 int
314 vfs_close(struct v_file* file);
315
316 int
317 vfs_fsync(struct v_file* file);
318
319 void
320 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
321
322 struct v_superblock*
323 vfs_sb_alloc();
324
325 void
326 vfs_sb_free(struct v_superblock* sb);
327
328 struct v_dnode*
329 vfs_d_alloc();
330
331 void
332 vfs_d_free(struct v_dnode* dnode);
333
334 struct v_inode*
335 vfs_i_find(struct v_superblock* sb, uint32_t i_id);
336
337 void
338 vfs_i_addhash(struct v_inode* inode);
339
340 struct v_inode*
341 vfs_i_alloc(struct v_superblock* sb);
342
343 void
344 vfs_i_free(struct v_inode* inode);
345
346 int
347 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
348
349 int
350 vfs_getfd(int fd, struct v_fd** fd_s);
351
352 void
353 pcache_init(struct pcache* pcache);
354
355 void
356 pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
357
358 struct pcache_pg*
359 pcache_new_page(struct pcache* pcache, uint32_t index);
360
361 void
362 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
363
364 struct pcache_pg*
365 pcache_get_page(struct pcache* pcache,
366                 uint32_t index,
367                 uint32_t* offset,
368                 struct pcache_pg** page);
369
370 int
371 pcache_write(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos);
372
373 int
374 pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos);
375
376 void
377 pcache_release(struct pcache* pcache);
378
379 int
380 pcache_commit(struct v_inode* inode, struct pcache_pg* page);
381
382 void
383 pcache_commit_all(struct v_inode* inode);
384
385 void
386 pcache_invalidate(struct pcache* pcache, struct pcache_pg* page);
387
388 /**
389  * @brief 将挂载点标记为繁忙
390  *
391  * @param mnt
392  */
393 void
394 mnt_mkbusy(struct v_mount* mnt);
395
396 /**
397  * @brief 将挂载点标记为清闲
398  *
399  * @param mnt
400  */
401 void
402 mnt_chillax(struct v_mount* mnt);
403
404 int
405 vfs_mount_root(const char* fs_name, struct device* device);
406
407 struct v_mount*
408 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
409
410 int
411 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
412
413 int
414 default_file_write(struct v_inode* inode,
415                    void* buffer,
416                    size_t len,
417                    size_t fpos);
418
419 int
420 default_file_readdir(struct v_file* file, struct dir_context* dctx);
421
422 int
423 default_inode_dirlookup(struct v_inode* this, struct v_dnode* dnode);
424
425 int
426 default_inode_rename(struct v_inode* from_inode,
427                      struct v_dnode* from_dnode,
428                      struct v_dnode* to_dnode);
429
430 int
431 default_file_close(struct v_file* file);
432
433 int
434 default_file_seek(struct v_inode* inode, size_t offset);
435
436 int
437 default_inode_open(struct v_inode* this, struct v_file* file);
438
439 int
440 default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
441
442 int
443 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
444
445 struct v_xattr_entry*
446 xattr_new(struct hstr* name);
447
448 struct v_xattr_entry*
449 xattr_getcache(struct v_inode* inode, struct hstr* name);
450
451 void
452 xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
453
454 #endif /* __LUNAIX_VFS_H */