79a61965eec63f22c75f8362ea837fd84fb2c553
[lwext4.git] / include / ext4_extent.h
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_extent.h
39  * @brief More complex filesystem functions.
40  */
41 #ifndef EXT4_EXTENT_H_
42 #define EXT4_EXTENT_H_
43
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47
48 #include "ext4_config.h"
49 #include "ext4_types.h"
50 #include "ext4_inode.h"
51
52
53 /*
54  * Array of ext4_ext_path contains path to some extent.
55  * Creation/lookup routines use it for traversal/splitting/etc.
56  * Truncate uses it to simulate recursive walking.
57  */
58 struct ext4_extent_path {
59         ext4_fsblk_t p_block;
60         struct ext4_block block;
61         int32_t depth;
62         int32_t maxdepth;
63         struct ext4_extent_header *header;
64         struct ext4_extent_index *index;
65         struct ext4_extent *extent;
66
67 };
68
69
70 /**@brief Get logical number of the block covered by extent.
71  * @param extent Extent to load number from
72  * @return Logical number of the first block covered by extent */
73 static inline uint32_t ext4_extent_get_first_block(struct ext4_extent *extent)
74 {
75         return to_le32(extent->first_block);
76 }
77
78 /**@brief Set logical number of the first block covered by extent.
79  * @param extent Extent to set number to
80  * @param iblock Logical number of the first block covered by extent */
81 static inline void ext4_extent_set_first_block(struct ext4_extent *extent,
82                 uint32_t iblock)
83 {
84         extent->first_block = to_le32(iblock);
85 }
86
87 /**@brief Get number of blocks covered by extent.
88  * @param extent Extent to load count from
89  * @return Number of blocks covered by extent */
90 static inline uint16_t ext4_extent_get_block_count(struct ext4_extent *extent)
91 {
92         if (EXT4_EXT_IS_UNWRITTEN(extent))
93                 return EXT4_EXT_GET_LEN_UNWRITTEN(extent);
94         else
95                 return EXT4_EXT_GET_LEN(extent);
96 }
97 /**@brief Set number of blocks covered by extent.
98  * @param extent Extent to load count from
99  * @param count  Number of blocks covered by extent
100  * @param unwritten Whether the extent is unwritten or not */
101 static inline void ext4_extent_set_block_count(struct ext4_extent *extent,
102                                                uint16_t count, bool unwritten)
103 {
104         EXT4_EXT_SET_LEN(extent, count);
105         if (unwritten)
106                 EXT4_EXT_SET_UNWRITTEN(extent);
107 }
108
109 /**@brief Get physical number of the first block covered by extent.
110  * @param extent Extent to load number
111  * @return Physical number of the first block covered by extent */
112 static inline uint64_t ext4_extent_get_start(struct ext4_extent *extent)
113 {
114         return ((uint64_t)to_le16(extent->start_hi)) << 32 |
115                ((uint64_t)to_le32(extent->start_lo));
116 }
117
118
119 /**@brief Set physical number of the first block covered by extent.
120  * @param extent Extent to load number
121  * @param fblock Physical number of the first block covered by extent */
122 static inline void ext4_extent_set_start(struct ext4_extent *extent, uint64_t fblock)
123 {
124         extent->start_lo = to_le32((fblock << 32) >> 32);
125         extent->start_hi = to_le16((uint16_t)(fblock >> 32));
126 }
127
128
129 /**@brief Get logical number of the block covered by extent index.
130  * @param index Extent index to load number from
131  * @return Logical number of the first block covered by extent index */
132 static inline uint32_t
133 ext4_extent_index_get_first_block(struct ext4_extent_index *index)
134 {
135         return to_le32(index->first_block);
136 }
137
138 /**@brief Set logical number of the block covered by extent index.
139  * @param index  Extent index to set number to
140  * @param iblock Logical number of the first block covered by extent index */
141 static inline void
142 ext4_extent_index_set_first_block(struct ext4_extent_index *index,
143                                   uint32_t iblock)
144 {
145         index->first_block = to_le32(iblock);
146 }
147
148 /**@brief Get physical number of block where the child node is located.
149  * @param index Extent index to load number from
150  * @return Physical number of the block with child node */
151 static inline uint64_t
152 ext4_extent_index_get_leaf(struct ext4_extent_index *index)
153 {
154         return ((uint64_t)to_le16(index->leaf_hi)) << 32 |
155                ((uint64_t)to_le32(index->leaf_lo));
156 }
157
158 /**@brief Set physical number of block where the child node is located.
159  * @param index  Extent index to set number to
160  * @param fblock Ohysical number of the block with child node */
161 static inline void ext4_extent_index_set_leaf(struct ext4_extent_index *index,
162                                               uint64_t fblock)
163 {
164         index->leaf_lo = to_le32((fblock << 32) >> 32);
165         index->leaf_hi = to_le16((uint16_t)(fblock >> 32));
166 }
167
168 /**@brief Get magic value from extent header.
169  * @param header Extent header to load value from
170  * @return Magic value of extent header */
171 static inline uint16_t
172 ext4_extent_header_get_magic(struct ext4_extent_header *header)
173 {
174         return to_le16(header->magic);
175 }
176
177 /**@brief Set magic value to extent header.
178  * @param header Extent header to set value to
179  * @param magic  Magic value of extent header */
180 static inline void ext4_extent_header_set_magic(struct ext4_extent_header *header,
181                                                 uint16_t magic)
182 {
183         header->magic = to_le16(magic);
184 }
185
186 /**@brief Get number of entries from extent header
187  * @param header Extent header to get value from
188  * @return Number of entries covered by extent header */
189 static inline uint16_t
190 ext4_extent_header_get_entries_count(struct ext4_extent_header *header)
191 {
192         return to_le16(header->entries_count);
193 }
194
195 /**@brief Set number of entries to extent header
196  * @param header Extent header to set value to
197  * @param count  Number of entries covered by extent header */
198 static inline void
199 ext4_extent_header_set_entries_count(struct ext4_extent_header *header,
200                                      uint16_t count)
201 {
202         header->entries_count = to_le16(count);
203 }
204
205 /**@brief Get maximum number of entries from extent header
206  * @param header Extent header to get value from
207  * @return Maximum number of entries covered by extent header */
208 static inline uint16_t
209 ext4_extent_header_get_max_entries_count(struct ext4_extent_header *header)
210 {
211         return to_le16(header->max_entries_count);
212 }
213
214 /**@brief Set maximum number of entries to extent header
215  * @param header    Extent header to set value to
216  * @param max_count Maximum number of entries covered by extent header */
217 static inline void
218 ext4_extent_header_set_max_entries_count(struct ext4_extent_header *header,
219                                               uint16_t max_count)
220 {
221         header->max_entries_count = to_le16(max_count);
222 }
223
224 /**@brief Get depth of extent subtree.
225  * @param header Extent header to get value from
226  * @return Depth of extent subtree */
227 static inline uint16_t
228 ext4_extent_header_get_depth(struct ext4_extent_header *header)
229 {
230         return to_le16(header->depth);
231 }
232
233 /**@brief Set depth of extent subtree.
234  * @param header Extent header to set value to
235  * @param depth  Depth of extent subtree */
236 static inline void
237 ext4_extent_header_set_depth(struct ext4_extent_header *header, uint16_t depth)
238 {
239         header->depth = to_le16(depth);
240 }
241
242 /**@brief Get generation from extent header
243  * @param header Extent header to get value from
244  * @return Generation */
245 static inline uint32_t
246 ext4_extent_header_get_generation(struct ext4_extent_header *header)
247 {
248         return to_le32(header->generation);
249 }
250
251 /**@brief Set generation to extent header
252  * @param header     Extent header to set value to
253  * @param generation Generation */
254 static inline void
255 ext4_extent_header_set_generation(struct ext4_extent_header *header,
256                                        uint32_t generation)
257 {
258         header->generation = to_le32(generation);
259 }
260
261 /******************************************************************************/
262
263 /**TODO:  */
264 static inline void ext4_extent_tree_init(struct ext4_inode_ref *inode_ref)
265 {
266         /* Initialize extent root header */
267         struct ext4_extent_header *header =
268                         ext4_inode_get_extent_header(inode_ref->inode);
269         ext4_extent_header_set_depth(header, 0);
270         ext4_extent_header_set_entries_count(header, 0);
271         ext4_extent_header_set_generation(header, 0);
272         ext4_extent_header_set_magic(header, EXT4_EXTENT_MAGIC);
273
274         uint16_t max_entries = (EXT4_INODE_BLOCKS * sizeof(uint32_t) -
275                         sizeof(struct ext4_extent_header)) /
276                                         sizeof(struct ext4_extent);
277
278         ext4_extent_header_set_max_entries_count(header, max_entries);
279         inode_ref->dirty  = true;
280 }
281
282
283
284 /**TODO:  */
285 int ext4_extent_get_blocks(struct ext4_inode_ref *inode_ref, ext4_lblk_t iblock,
286                            uint32_t max_blocks, ext4_fsblk_t *result, bool create,
287                            uint32_t *blocks_count);
288
289
290 /**@brief Release all data blocks starting from specified logical block.
291  * @param inode_ref   I-node to release blocks from
292  * @param iblock_from First logical block to release
293  * @return Error code */
294 int ext4_extent_remove_space(struct ext4_inode_ref *inode_ref, ext4_lblk_t from,
295                              ext4_lblk_t to);
296
297
298 #ifdef __cplusplus
299 }
300 #endif
301
302 #endif /* EXT4_EXTENT_H_ */
303 /**
304 * @}
305 */