1 | /* |
2 | * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com) |
3 | * |
4 | * |
5 | * HelenOS: |
6 | * Copyright (c) 2012 Martin Sucha |
7 | * Copyright (c) 2012 Frantisek Princ |
8 | * All rights reserved. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * |
14 | * - Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. |
16 | * - Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. |
19 | * - The name of the author may not be used to endorse or promote products |
20 | * derived from this software without specific prior written permission. |
21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | |
34 | /** @addtogroup lwext4 |
35 | * @{ |
36 | */ |
37 | /** |
38 | * @file ext4_fs.c |
39 | * @brief More complex filesystem functions. |
40 | */ |
41 | |
42 | #ifndef EXT4_FS_H_ |
43 | #define EXT4_FS_H_ |
44 | |
45 | #ifdef __cplusplus |
46 | extern "C" { |
47 | #endif |
48 | |
49 | #include <ext4_config.h> |
50 | #include <ext4_types.h> |
51 | #include <ext4_misc.h> |
52 | |
53 | #include <stdint.h> |
54 | #include <stdbool.h> |
55 | |
56 | struct ext4_fs { |
57 | bool read_only; |
58 | |
59 | struct ext4_blockdev *bdev; |
60 | struct ext4_sblock sb; |
61 | |
62 | uint64_t inode_block_limits[4]; |
63 | uint64_t inode_blocks_per_level[4]; |
64 | |
65 | uint32_t last_inode_bg_id; |
66 | |
67 | struct jbd_fs *jbd_fs; |
68 | struct jbd_journal *jbd_journal; |
69 | struct jbd_trans *curr_trans; |
70 | }; |
71 | |
72 | struct ext4_block_group_ref { |
73 | struct ext4_block block; |
74 | struct ext4_bgroup *block_group; |
75 | struct ext4_fs *fs; |
76 | uint32_t index; |
77 | bool dirty; |
78 | }; |
79 | |
80 | struct ext4_inode_ref { |
81 | struct ext4_block block; |
82 | struct ext4_inode *inode; |
83 | struct ext4_fs *fs; |
84 | uint32_t index; |
85 | bool dirty; |
86 | }; |
87 | |
88 | |
89 | /**@brief Convert block address to relative index in block group. |
90 | * @param s Superblock pointer |
91 | * @param baddr Block number to convert |
92 | * @return Relative number of block |
93 | */ |
94 | static inline uint32_t ext4_fs_addr_to_idx_bg(struct ext4_sblock *s, |
95 | ext4_fsblk_t baddr) |
96 | { |
97 | if (ext4_get32(s, first_data_block) && baddr) |
98 | baddr--; |
99 | |
100 | return baddr % ext4_get32(s, blocks_per_group); |
101 | } |
102 | |
103 | /**@brief Convert relative block address in group to absolute address. |
104 | * @param s Superblock pointer |
105 | * @param index Relative block address |
106 | * @param bgid Block group |
107 | * @return Absolute block address |
108 | */ |
109 | static inline ext4_fsblk_t ext4_fs_bg_idx_to_addr(struct ext4_sblock *s, |
110 | uint32_t index, |
111 | uint32_t bgid) |
112 | { |
113 | if (ext4_get32(s, first_data_block)) |
114 | index++; |
115 | |
116 | return ext4_get32(s, blocks_per_group) * bgid + index; |
117 | } |
118 | |
119 | /**@brief TODO: */ |
120 | static inline ext4_fsblk_t ext4_fs_first_bg_block_no(struct ext4_sblock *s, |
121 | uint32_t bgid) |
122 | { |
123 | return (uint64_t)bgid * ext4_get32(s, blocks_per_group) + |
124 | ext4_get32(s, first_data_block); |
125 | } |
126 | |
127 | /**@brief Initialize filesystem and read all needed data. |
128 | * @param fs Filesystem instance to be initialized |
129 | * @param bdev Identifier if device with the filesystem |
130 | * @param read_only Mark the filesystem as read-only. |
131 | * @return Error code |
132 | */ |
133 | int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev, |
134 | bool read_only); |
135 | |
136 | /**@brief Destroy filesystem instance (used by unmount operation). |
137 | * @param fs Filesystem to be destroyed |
138 | * @return Error code |
139 | */ |
140 | int ext4_fs_fini(struct ext4_fs *fs); |
141 | |
142 | /**@brief Check filesystem's features, if supported by this driver |
143 | * Function can return EOK and set read_only flag. It mean's that |
144 | * there are some not-supported features, that can cause problems |
145 | * during some write operations. |
146 | * @param fs Filesystem to be checked |
147 | * @param read_only Flag if filesystem should be mounted only for reading |
148 | * @return Error code |
149 | */ |
150 | int ext4_fs_check_features(struct ext4_fs *fs, bool *read_only); |
151 | |
152 | /**@brief Get reference to block group specified by index. |
153 | * @param fs Filesystem to find block group on |
154 | * @param bgid Index of block group to load |
155 | * @param ref Output pointer for reference |
156 | * @return Error code |
157 | */ |
158 | int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid, |
159 | struct ext4_block_group_ref *ref); |
160 | |
161 | /**@brief Put reference to block group. |
162 | * @param ref Pointer for reference to be put back |
163 | * @return Error code |
164 | */ |
165 | int ext4_fs_put_block_group_ref(struct ext4_block_group_ref *ref); |
166 | |
167 | /**@brief Get reference to i-node specified by index. |
168 | * @param fs Filesystem to find i-node on |
169 | * @param index Index of i-node to load |
170 | * @param ref Output pointer for reference |
171 | * @return Error code |
172 | */ |
173 | int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index, |
174 | struct ext4_inode_ref *ref); |
175 | |
176 | /**@brief Reset blocks field of i-node. |
177 | * @param fs Filesystem to reset blocks field of i-inode on |
178 | * @param inode_ref ref Pointer for inode to be operated on |
179 | */ |
180 | void ext4_fs_inode_blocks_init(struct ext4_fs *fs, |
181 | struct ext4_inode_ref *inode_ref); |
182 | |
183 | /**@brief Put reference to i-node. |
184 | * @param ref Pointer for reference to be put back |
185 | * @return Error code |
186 | */ |
187 | int ext4_fs_put_inode_ref(struct ext4_inode_ref *ref); |
188 | |
189 | /**@brief Convert filetype to inode mode. |
190 | * @param filetype File type |
191 | * @return inode mode |
192 | */ |
193 | uint32_t ext4_fs_correspond_inode_mode(int filetype); |
194 | |
195 | /**@brief Allocate new i-node in the filesystem. |
196 | * @param fs Filesystem to allocated i-node on |
197 | * @param inode_ref Output pointer to return reference to allocated i-node |
198 | * @param filetype File type of newly created i-node |
199 | * @return Error code |
200 | */ |
201 | int ext4_fs_alloc_inode(struct ext4_fs *fs, struct ext4_inode_ref *inode_ref, |
202 | int filetype); |
203 | |
204 | /**@brief Release i-node and mark it as free. |
205 | * @param inode_ref I-node to be released |
206 | * @return Error code |
207 | */ |
208 | int ext4_fs_free_inode(struct ext4_inode_ref *inode_ref); |
209 | |
210 | /**@brief Truncate i-node data blocks. |
211 | * @param inode_ref I-node to be truncated |
212 | * @param new_size New size of inode (must be < current size) |
213 | * @return Error code |
214 | */ |
215 | int ext4_fs_truncate_inode(struct ext4_inode_ref *inode_ref, uint64_t new_size); |
216 | |
217 | /**@brief Compute 'goal' for inode index |
218 | * @param inode_ref Reference to inode, to allocate block for |
219 | * @return goal |
220 | */ |
221 | ext4_fsblk_t ext4_fs_inode_to_goal_block(struct ext4_inode_ref *inode_ref); |
222 | |
223 | /**@brief Compute 'goal' for allocation algorithm (For blockmap). |
224 | * @param inode_ref Reference to inode, to allocate block for |
225 | * @return error code |
226 | */ |
227 | int ext4_fs_indirect_find_goal(struct ext4_inode_ref *inode_ref, |
228 | ext4_fsblk_t *goal); |
229 | |
230 | /**@brief Get physical block address by logical index of the block. |
231 | * @param inode_ref I-node to read block address from |
232 | * @param iblock Logical index of block |
233 | * @param fblock Output pointer for return physical |
234 | * block address |
235 | * @param support_unwritten Indicate whether unwritten block range |
236 | * is supported under the current context |
237 | * @return Error code |
238 | */ |
239 | int ext4_fs_get_inode_dblk_idx(struct ext4_inode_ref *inode_ref, |
240 | ext4_lblk_t iblock, ext4_fsblk_t *fblock, |
241 | bool support_unwritten); |
242 | |
243 | /**@brief Initialize a part of unwritten range of the inode. |
244 | * @param inode_ref I-node to proceed on. |
245 | * @param iblock Logical index of block |
246 | * @param fblock Output pointer for return physical block address |
247 | * @return Error code |
248 | */ |
249 | int ext4_fs_init_inode_dblk_idx(struct ext4_inode_ref *inode_ref, |
250 | ext4_lblk_t iblock, ext4_fsblk_t *fblock); |
251 | |
252 | /**@brief Append following logical block to the i-node. |
253 | * @param inode_ref I-node to append block to |
254 | * @param fblock Output physical block address of newly allocated block |
255 | * @param iblock Output logical number of newly allocated block |
256 | * @return Error code |
257 | */ |
258 | int ext4_fs_append_inode_dblk(struct ext4_inode_ref *inode_ref, |
259 | ext4_fsblk_t *fblock, ext4_lblk_t *iblock); |
260 | |
261 | /**@brief Increment inode link count. |
262 | * @param inode_ref none handle |
263 | */ |
264 | void ext4_fs_inode_links_count_inc(struct ext4_inode_ref *inode_ref); |
265 | |
266 | /**@brief Decrement inode link count. |
267 | * @param inode_ref none handle |
268 | */ |
269 | void ext4_fs_inode_links_count_dec(struct ext4_inode_ref *inode_ref); |
270 | |
271 | #ifdef __cplusplus |
272 | } |
273 | #endif |
274 | |
275 | #endif /* EXT4_FS_H_ */ |
276 | |
277 | /** |
278 | * @} |
279 | */ |
280 | |