fix dependency check logic cause config always disabled
[lunaix-os.git] / lunaix-os / includes / lunaix / fs / api.h
1 #ifndef __LUNAIX_FSAPI_H
2 #define __LUNAIX_FSAPI_H
3
4 #include <lunaix/fs.h>
5 #include <lunaix/blkbuf.h>
6 #include <klibc/string.h>
7
8 #include <usr/lunaix/fcntl.h>
9 #include <usr/lunaix/dirent.h>
10
11 struct fsapi_vsb_ops
12 {
13     size_t (*read_capacity)(struct v_superblock* vsb);
14     size_t (*read_usage)(struct v_superblock* vsb);
15     void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode);
16     void (*release)(struct v_superblock* vsb);
17 };
18
19 static inline struct device* 
20 fsapi_blockdev(struct v_superblock* vsb) 
21 {
22     if (!(vsb->fs->types & FSTYPE_PSEUDO)) {
23         assert_fs(vsb->dev);
24     }
25     
26     return vsb->dev;
27 }
28
29 typedef void (*inode_init)(struct v_superblock* vsb, struct v_inode* inode) ;
30 typedef void (*inode_free)(struct v_inode* inode) ;
31 typedef void (*dnode_free)(struct v_dnode* dnode) ;
32
33 static inline void
34 fsapi_set_inode_initiator(struct v_superblock* vsb, inode_init inode_initiator)
35 {
36     vsb->ops.init_inode = inode_initiator;
37 }
38
39 static inline size_t
40 fsapi_block_size(struct v_superblock* vsb)
41 {
42     return vsb->blksize;
43 }
44
45 static inline void
46 fsapi_set_vsb_ops(struct v_superblock* vsb, struct fsapi_vsb_ops* basic_ops)
47 {
48     vsb->ops.read_capacity = basic_ops->read_capacity;
49     vsb->ops.read_usage = basic_ops->read_usage;
50     vsb->ops.release = basic_ops->release;
51     vsb->ops.init_inode = basic_ops->init_inode;
52 }
53
54 static inline void
55 fsapi_complete_vsb_setup(struct v_superblock* vsb, void* cfs_sb)
56 {
57     assert_fs(vsb->ops.init_inode);
58     assert_fs(vsb->ops.read_capacity);
59     assert_fs(vsb->blksize);
60     assert_fs(vsb->blks);
61
62     vsb->data = cfs_sb;
63 }
64
65 static inline void
66 fsapi_begin_vsb_setup(struct v_superblock* vsb, size_t blksz)
67 {
68     assert(!vsb->blks);
69     assert(blksz);
70     
71     vsb->blksize = blksz;
72     vsb->blks = blkbuf_create(block_dev(vsb->dev), blksz);
73 }
74
75 static inline void
76 fsapi_reset_vsb(struct v_superblock* vsb)
77 {
78     assert(vsb->blks);
79     blkbuf_release(vsb->blks);
80
81     vsb->blks = NULL;
82     vsb->data = NULL;
83     vsb->blksize = 0;
84     vsb->root->mnt->flags = 0;
85     memset(&vsb->ops, 0, sizeof(vsb->ops));
86 }
87
88 static inline bool
89 fsapi_readonly_mount(struct v_superblock* vsb)
90 {
91     return (vsb->root->mnt->flags & MNT_RO);
92 }
93
94 static inline void
95 fsapi_set_readonly_mount(struct v_superblock* vsb)
96 {
97     vsb->root->mnt->flags |= MNT_RO;
98 }
99
100 #define fsapi_impl_data(vfs_obj, type) (type*)((vfs_obj)->data)
101
102 static inline void
103 fsapi_inode_setid(struct v_inode* inode, 
104                   inode_t i_id, unsigned int blk_addr)
105 {
106     inode->id = i_id;
107     inode->lb_addr = blk_addr;
108 }
109
110 static inline void
111 fsapi_inode_settype(struct v_inode* inode, unsigned int type)
112 {
113     inode->itype = type;
114 }
115
116 static inline void
117 fsapi_inode_setsize(struct v_inode* inode, unsigned int fsize)
118 {
119     inode->lb_usage = ICEIL(fsize, inode->sb->blksize);
120     inode->fsize = fsize;
121 }
122
123 static inline void
124 fsapi_inode_setops(struct v_inode* inode, 
125                    struct v_inode_ops* ops)
126 {
127     inode->ops = ops;
128 }
129
130 static inline void
131 fsapi_inode_setfops(struct v_inode* inode, 
132                    struct v_file_ops* fops)
133 {
134     inode->default_fops = fops;
135 }
136
137 static inline void
138 fsapi_inode_setdector(struct v_inode* inode, 
139                       inode_free free_cb)
140 {
141     inode->destruct = free_cb;
142 }
143
144 static inline void
145 fsapi_inode_complete(struct v_inode* inode, void* data)
146 {
147     assert_fs(inode->ops);
148     assert_fs(inode->default_fops);
149     assert_fs(inode->default_fops);
150
151     inode->data = data;
152 }
153
154 static inline void
155 fsapi_inode_settime(struct v_inode* inode, 
156                     time_t ctime, time_t mtime, time_t atime)
157 {
158     inode->ctime = ctime;
159     inode->mtime = mtime;
160     inode->atime = atime;
161 }
162
163 static inline void
164 fsapi_inode_setaccess(struct v_inode* inode, unsigned int acl)
165 {
166     inode->acl = acl;
167 }
168
169 static inline void
170 fsapi_inode_setowner(struct v_inode* inode, uid_t uid, gid_t gid)
171 {
172     inode->uid = uid;
173     inode->gid = gid;
174 }
175
176 static inline void
177 fsapi_dnode_setdector(struct v_dnode* dnode, 
178                       dnode_free free_cb)
179 {
180     dnode->destruct = free_cb;
181 }
182
183 static inline struct v_inode*
184 fsapi_dnode_parent(struct v_dnode* dnode)
185 {
186     assert(dnode->parent);
187     return dnode->parent->inode;
188 }
189
190 static inline void
191 fsapi_dir_report(struct dir_context *dctx, 
192                  const char *name, const int len, const int dtype)
193 {
194     dctx->read_complete_callback(dctx, name, len, dtype);
195 }
196
197 /**
198  * @brief Get a block with file-system defined block size
199  *        from underlying storage medium at given block id
200  *        (block address). Depending on the device attribute,
201  *        it may or may not go through the block cache layer.
202  * 
203  * @param vsb super-block
204  * @param block_id block address
205  * @return bbuf_t 
206  */
207 static inline bbuf_t
208 fsblock_get(struct v_superblock* vsb, unsigned int block_id)
209 {
210     return blkbuf_take(vsb->blks, block_id);
211 }
212
213 /**
214  * @brief put the block back into cache, must to pair with
215  *        fsblock_get. Otherwise memory leakage will occur.
216  * 
217  * @param blkbuf 
218  */
219 static inline void
220 fsblock_put(bbuf_t blkbuf)
221 {
222     return blkbuf_put(blkbuf);
223 }
224
225
226 static inline bbuf_t
227 fsblock_take(bbuf_t blk)
228 {
229     return blkbuf_refonce(blk);
230 }
231
232 static inline unsigned int
233 fsblock_id(bbuf_t blkbuf)
234 {
235     return blkbuf_id(blkbuf);
236 }
237
238 /**
239  * @brief Mark the block dirty and require scheduling a device 
240  *        write request to sync it with underlying medium. Lunaix
241  *        will do the scheduling when it sees fit.
242  * 
243  * @param blkbuf 
244  */
245 static inline void
246 fsblock_dirty(bbuf_t blkbuf)
247 {
248     return blkbuf_dirty(blkbuf);
249 }
250
251 /**
252  * @brief Manually trigger a sync cycle, regardless the
253  *        dirty property.
254  * 
255  * @param blkbuf 
256  */
257 static inline void
258 fsblock_sync(bbuf_t blkbuf)
259 {
260     /*
261         XXX delay the sync for better write aggregation
262         scheduled sync event may happened immediately (i.e., blkio queue is
263         empty or nearly empty), any susequent write to the same blkbuf must
264         schedule another write. Which could thrash the disk IO when intensive
265         workload
266     */
267     return blkbuf_schedule_sync(blkbuf);
268 }
269
270 static inline bool
271 fsapi_handle_pseudo_dirent(struct v_file* file, struct dir_context* dctx) 
272 {
273     if (file->f_pos == 0) {
274         fsapi_dir_report(dctx, ".", 1, vfs_get_dtype(VFS_IFDIR));
275         return true;
276     }
277
278     if (file->f_pos == 1) {
279         fsapi_dir_report(dctx, "..", 2, vfs_get_dtype(VFS_IFDIR));
280         return true;
281     }
282     
283     return false;
284 }
285
286 static inline struct filesystem*
287 fsapi_fs_declare(const char* name, unsigned int type)
288 {
289     struct filesystem* fs;
290
291     fs = fsm_new_fs(name, -1);
292     assert_fs(fs);
293
294     fs->types = type;
295     return fs;
296 }
297
298 static inline void
299 fsapi_fs_set_mntops(struct filesystem* fs, 
300                     mntops_mnt mnt, mntops_umnt umnt)
301 {
302     fs->mount = mnt;
303     fs->unmount = umnt;
304 }
305
306 static inline void
307 fsapi_fs_finalise(struct filesystem* fs)
308 {
309     assert_fs(fs->mount);
310     assert_fs(fs->unmount);
311     fsm_register(fs);
312 }
313
314 #endif /* __LUNAIX_FSAPI_H */