Second Extended Filesystem (ext2) and other improvements (#33)
[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/fcntl_defs.h>
6 #include <lunaix/blkbuf.h>
7 #include <klibc/string.h>
8
9 #include <usr/lunaix/dirent_defs.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_dnode_setdector(struct v_dnode* dnode, 
165                       dnode_free free_cb)
166 {
167     dnode->destruct = free_cb;
168 }
169
170 static inline struct v_inode*
171 fsapi_dnode_parent(struct v_dnode* dnode)
172 {
173     assert(dnode->parent);
174     return dnode->parent->inode;
175 }
176
177 static inline void
178 fsapi_dir_report(struct dir_context *dctx, 
179                  const char *name, const int len, const int dtype)
180 {
181     dctx->read_complete_callback(dctx, name, len, dtype);
182 }
183
184 /**
185  * @brief Get a block with file-system defined block size
186  *        from underlying storage medium at given block id
187  *        (block address). Depending on the device attribute,
188  *        it may or may not go through the block cache layer.
189  * 
190  * @param vsb super-block
191  * @param block_id block address
192  * @return bbuf_t 
193  */
194 static inline bbuf_t
195 fsblock_get(struct v_superblock* vsb, unsigned int block_id)
196 {
197     return blkbuf_take(vsb->blks, block_id);
198 }
199
200 /**
201  * @brief put the block back into cache, must to pair with
202  *        fsblock_get. Otherwise memory leakage will occur.
203  * 
204  * @param blkbuf 
205  */
206 static inline void
207 fsblock_put(bbuf_t blkbuf)
208 {
209     return blkbuf_put(blkbuf);
210 }
211
212
213 static inline bbuf_t
214 fsblock_take(bbuf_t blk)
215 {
216     return blkbuf_refonce(blk);
217 }
218
219 static inline unsigned int
220 fsblock_id(bbuf_t blkbuf)
221 {
222     return blkbuf_id(blkbuf);
223 }
224
225 /**
226  * @brief Mark the block dirty and require scheduling a device 
227  *        write request to sync it with underlying medium. Lunaix
228  *        will do the scheduling when it sees fit.
229  * 
230  * @param blkbuf 
231  */
232 static inline void
233 fsblock_dirty(bbuf_t blkbuf)
234 {
235     return blkbuf_dirty(blkbuf);
236 }
237
238 /**
239  * @brief Manually trigger a sync cycle, regardless the
240  *        dirty property.
241  * 
242  * @param blkbuf 
243  */
244 static inline void
245 fsblock_sync(bbuf_t blkbuf)
246 {
247     /*
248         XXX delay the sync for better write aggregation
249         scheduled sync event may happened immediately (i.e., blkio queue is
250         empty or nearly empty), any susequent write to the same blkbuf must
251         schedule another write. Which could thrash the disk IO when intensive
252         workload
253     */
254     return blkbuf_schedule_sync(blkbuf);
255 }
256
257 static inline bool
258 fsapi_handle_pseudo_dirent(struct v_file* file, struct dir_context* dctx) 
259 {
260     if (file->f_pos == 0) {
261         fsapi_dir_report(dctx, ".", 1, vfs_get_dtype(VFS_IFDIR));
262         return true;
263     }
264
265     if (file->f_pos == 1) {
266         fsapi_dir_report(dctx, "..", 2, vfs_get_dtype(VFS_IFDIR));
267         return true;
268     }
269     
270     return false;
271 }
272
273 static inline struct filesystem*
274 fsapi_fs_declare(const char* name, unsigned int type)
275 {
276     struct filesystem* fs;
277
278     fs = fsm_new_fs(name, -1);
279     assert_fs(fs);
280
281     fs->types = type;
282     return fs;
283 }
284
285 static inline void
286 fsapi_fs_set_mntops(struct filesystem* fs, 
287                     mntops_mnt mnt, mntops_umnt umnt)
288 {
289     fs->mount = mnt;
290     fs->unmount = umnt;
291 }
292
293 static inline void
294 fsapi_fs_finalise(struct filesystem* fs)
295 {
296     assert_fs(fs->mount);
297     assert_fs(fs->unmount);
298     fsm_register(fs);
299 }
300
301 #endif /* __LUNAIX_FSAPI_H */