1 | /* |
2 | * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com) |
3 | * All rights reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * |
9 | * - Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * - Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
14 | * - The name of the author may not be used to endorse or promote products |
15 | * derived from this software without specific prior written permission. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | /** @addtogroup lwext4 |
29 | * @{ |
30 | */ |
31 | /** |
32 | * @file ext4_blockdev.h |
33 | * @brief Block device module. |
34 | */ |
35 | |
36 | #ifndef EXT4_BLOCKDEV_H_ |
37 | #define EXT4_BLOCKDEV_H_ |
38 | |
39 | #ifdef __cplusplus |
40 | extern "C" { |
41 | #endif |
42 | |
43 | #include <ext4_config.h> |
44 | #include <ext4_bcache.h> |
45 | |
46 | #include <stdbool.h> |
47 | #include <stdint.h> |
48 | |
49 | struct ext4_blockdev_iface { |
50 | /**@brief Open device function |
51 | * @param bdev block device.*/ |
52 | int (*open)(struct ext4_blockdev *bdev); |
53 | |
54 | /**@brief Block read function. |
55 | * @param bdev block device |
56 | * @param buf output buffer |
57 | * @param blk_id block id |
58 | * @param blk_cnt block count*/ |
59 | int (*bread)(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id, |
60 | uint32_t blk_cnt); |
61 | |
62 | /**@brief Block write function. |
63 | * @param buf input buffer |
64 | * @param blk_id block id |
65 | * @param blk_cnt block count*/ |
66 | int (*bwrite)(struct ext4_blockdev *bdev, const void *buf, |
67 | uint64_t blk_id, uint32_t blk_cnt); |
68 | |
69 | /**@brief Close device function. |
70 | * @param bdev block device.*/ |
71 | int (*close)(struct ext4_blockdev *bdev); |
72 | |
73 | /**@brief Lock block device. Required in multi partition mode |
74 | * operations. Not mandatory field. |
75 | * @param bdev block device.*/ |
76 | int (*lock)(struct ext4_blockdev *bdev); |
77 | |
78 | /**@brief Unlock block device. Required in multi partition mode |
79 | * operations. Not mandatory field. |
80 | * @param bdev block device.*/ |
81 | int (*unlock)(struct ext4_blockdev *bdev); |
82 | |
83 | /**@brief Block size (bytes): physical*/ |
84 | uint32_t ph_bsize; |
85 | |
86 | /**@brief Block count: physical*/ |
87 | uint64_t ph_bcnt; |
88 | |
89 | /**@brief Block size buffer: physical*/ |
90 | uint8_t *ph_bbuf; |
91 | |
92 | /**@brief Reference counter to block device interface*/ |
93 | uint32_t ph_refctr; |
94 | |
95 | /**@brief Physical read counter*/ |
96 | uint32_t bread_ctr; |
97 | |
98 | /**@brief Physical write counter*/ |
99 | uint32_t bwrite_ctr; |
100 | |
101 | /**@brief User data pointer*/ |
102 | void* p_user; |
103 | }; |
104 | |
105 | /**@brief Definition of the simple block device.*/ |
106 | struct ext4_blockdev { |
107 | /**@brief Block device interface*/ |
108 | struct ext4_blockdev_iface *bdif; |
109 | |
110 | /**@brief Offset in bdif. For multi partition mode.*/ |
111 | uint64_t part_offset; |
112 | |
113 | /**@brief Part size in bdif. For multi partition mode.*/ |
114 | uint64_t part_size; |
115 | |
116 | /**@brief Block cache.*/ |
117 | struct ext4_bcache *bc; |
118 | |
119 | /**@brief Block size (bytes) logical*/ |
120 | uint32_t lg_bsize; |
121 | |
122 | /**@brief Block count: logical*/ |
123 | uint64_t lg_bcnt; |
124 | |
125 | /**@brief Cache write back mode reference counter*/ |
126 | uint32_t cache_write_back; |
127 | |
128 | /**@brief The filesystem this block device belongs to. */ |
129 | struct ext4_fs *fs; |
130 | |
131 | void *journal; |
132 | }; |
133 | |
134 | /**@brief Static initialization of the block device.*/ |
135 | #define EXT4_BLOCKDEV_STATIC_INSTANCE(__name, __bsize, __bcnt, __open, __bread,\ |
136 | __bwrite, __close, __lock, __unlock) \ |
137 | static uint8_t __name##_ph_bbuf[(__bsize)]; \ |
138 | static struct ext4_blockdev_iface __name##_iface = { \ |
139 | .open = __open, \ |
140 | .bread = __bread, \ |
141 | .bwrite = __bwrite, \ |
142 | .close = __close, \ |
143 | .lock = __lock, \ |
144 | .unlock = __unlock, \ |
145 | .ph_bsize = __bsize, \ |
146 | .ph_bcnt = __bcnt, \ |
147 | .ph_bbuf = __name##_ph_bbuf, \ |
148 | }; \ |
149 | static struct ext4_blockdev __name = { \ |
150 | .bdif = &__name##_iface, \ |
151 | .part_offset = 0, \ |
152 | .part_size = (__bcnt) * (__bsize), \ |
153 | } |
154 | |
155 | /**@brief Block device initialization. |
156 | * @param bdev block device descriptor |
157 | * @return standard error code*/ |
158 | int ext4_block_init(struct ext4_blockdev *bdev); |
159 | |
160 | /**@brief Binds a bcache to block device. |
161 | * @param bdev block device descriptor |
162 | * @param bc block cache descriptor |
163 | * @return standard error code*/ |
164 | int ext4_block_bind_bcache(struct ext4_blockdev *bdev, struct ext4_bcache *bc); |
165 | |
166 | /**@brief Close block device |
167 | * @param bdev block device descriptor |
168 | * @return standard error code*/ |
169 | int ext4_block_fini(struct ext4_blockdev *bdev); |
170 | |
171 | /**@brief Flush data in given buffer to disk. |
172 | * @param bdev block device descriptor |
173 | * @param buf buffer |
174 | * @return standard error code*/ |
175 | int ext4_block_flush_buf(struct ext4_blockdev *bdev, struct ext4_buf *buf); |
176 | |
177 | /**@brief Flush data in buffer of given lba to disk, |
178 | * if that buffer exists in block cache. |
179 | * @param bdev block device descriptor |
180 | * @param lba logical block address |
181 | * @return standard error code*/ |
182 | int ext4_block_flush_lba(struct ext4_blockdev *bdev, uint64_t lba); |
183 | |
184 | /**@brief Set logical block size in block device. |
185 | * @param bdev block device descriptor |
186 | * @param lb_bsize logical block size (in bytes)*/ |
187 | void ext4_block_set_lb_size(struct ext4_blockdev *bdev, uint32_t lb_bsize); |
188 | |
189 | /**@brief Block get function (through cache, don't read). |
190 | * @param bdev block device descriptor |
191 | * @param b block descriptor |
192 | * @param lba logical block address |
193 | * @return standard error code*/ |
194 | int ext4_block_get_noread(struct ext4_blockdev *bdev, struct ext4_block *b, |
195 | uint64_t lba); |
196 | |
197 | /**@brief Block get function (through cache). |
198 | * @param bdev block device descriptor |
199 | * @param b block descriptor |
200 | * @param lba logical block address |
201 | * @return standard error code*/ |
202 | int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b, |
203 | uint64_t lba); |
204 | |
205 | /**@brief Block set procedure (through cache). |
206 | * @param bdev block device descriptor |
207 | * @param b block descriptor |
208 | * @return standard error code*/ |
209 | int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b); |
210 | |
211 | /**@brief Block read procedure (without cache) |
212 | * @param bdev block device descriptor |
213 | * @param buf output buffer |
214 | * @param lba logical block address |
215 | * @return standard error code*/ |
216 | int ext4_blocks_get_direct(struct ext4_blockdev *bdev, void *buf, uint64_t lba, |
217 | uint32_t cnt); |
218 | |
219 | /**@brief Block write procedure (without cache) |
220 | * @param bdev block device descriptor |
221 | * @param buf output buffer |
222 | * @param lba logical block address |
223 | * @return standard error code*/ |
224 | int ext4_blocks_set_direct(struct ext4_blockdev *bdev, const void *buf, |
225 | uint64_t lba, uint32_t cnt); |
226 | |
227 | /**@brief Write to block device (by direct address). |
228 | * @param bdev block device descriptor |
229 | * @param off byte offset in block device |
230 | * @param buf input buffer |
231 | * @param len length of the write buffer |
232 | * @return standard error code*/ |
233 | int ext4_block_writebytes(struct ext4_blockdev *bdev, uint64_t off, |
234 | const void *buf, uint32_t len); |
235 | |
236 | /**@brief Read freom block device (by direct address). |
237 | * @param bdev block device descriptor |
238 | * @param off byte offset in block device |
239 | * @param buf input buffer |
240 | * @param len length of the write buffer |
241 | * @return standard error code*/ |
242 | int ext4_block_readbytes(struct ext4_blockdev *bdev, uint64_t off, void *buf, |
243 | uint32_t len); |
244 | |
245 | /**@brief Flush all dirty buffers to disk |
246 | * @param bdev block device descriptor |
247 | * @return standard error code*/ |
248 | int ext4_block_cache_flush(struct ext4_blockdev *bdev); |
249 | |
250 | /**@brief Enable/disable write back cache mode |
251 | * @param bdev block device descriptor |
252 | * @param on_off |
253 | * !0 - ENABLE |
254 | * 0 - DISABLE (all delayed cache buffers will be flushed) |
255 | * @return standard error code*/ |
256 | int ext4_block_cache_write_back(struct ext4_blockdev *bdev, uint8_t on_off); |
257 | |
258 | #ifdef __cplusplus |
259 | } |
260 | #endif |
261 | |
262 | #endif /* EXT4_BLOCKDEV_H_ */ |
263 | |
264 | /** |
265 | * @} |
266 | */ |
267 | |