source: mainline/uspace/lib/ext4/libext4_extent.c@ 47faec1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 47faec1 was 47faec1, checked in by Frantisek Princ <frantisek.princ@…>, 13 years ago

introduced binary search in extent index node

  • Property mode set to 100644
File size: 8.9 KB
RevLine 
[829d238]1/*
2 * Copyright (c) 2011 Frantisek Princ
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
29/** @addtogroup libext4
30 * @{
31 */
32
33/**
34 * @file libext4_extent.c
[c25e39b]35 * @brief Ext4 extent structures operations.
[829d238]36 */
37
[acd869e]38#include <byteorder.h>
[e2629b08]39#include <errno.h>
40#include <malloc.h>
41#include "libext4.h"
[829d238]42
[8958a26]43uint32_t ext4_extent_get_first_block(ext4_extent_t *extent)
44{
45 return uint32_t_le2host(extent->first_block);
46}
47
[343ccfd]48void ext4_extent_set_first_block(ext4_extent_t *extent, uint32_t first_block)
49{
50 extent->first_block = host2uint32_t_le(first_block);
51}
52
[8958a26]53uint16_t ext4_extent_get_block_count(ext4_extent_t *extent)
54{
55 return uint16_t_le2host(extent->block_count);
56}
57
[343ccfd]58void ext4_extent_set_block_count(ext4_extent_t *extent, uint16_t block_count)
59{
60 extent->block_count = host2uint16_t_le(block_count);
61}
62
[8958a26]63uint64_t ext4_extent_get_start(ext4_extent_t *extent)
64{
65 return ((uint64_t)uint16_t_le2host(extent->start_hi)) << 32 |
66 ((uint64_t)uint32_t_le2host(extent->start_lo));
[343ccfd]67}
[8958a26]68
[343ccfd]69void ext4_extent_set_start(ext4_extent_t *extent, uint64_t start)
70{
71 extent->start_lo = host2uint32_t_le((start << 32) >> 32);
72 extent->start_hi = host2uint16_t_le((uint16_t)(start >> 32));
[8958a26]73}
74
[1a7756a]75uint32_t ext4_extent_index_get_first_block(ext4_extent_index_t *index)
76{
77 return uint32_t_le2host(index->first_block);
78}
79
[343ccfd]80void ext4_extent_index_set_first_block(ext4_extent_index_t *index,
81 uint32_t first)
82{
83 index->first_block = host2uint32_t_le(first);
84}
85
[1a7756a]86uint64_t ext4_extent_index_get_leaf(ext4_extent_index_t *index)
87{
88 return ((uint64_t)uint16_t_le2host(index->leaf_hi)) << 32 |
[343ccfd]89 ((uint64_t)uint32_t_le2host(index->leaf_lo));
90}
91
92void ext4_extent_index_set_leaf(ext4_extent_index_t *index, uint64_t leaf)
93{
94 index->leaf_lo = host2uint32_t_le((leaf << 32) >> 32);
95 index->leaf_hi = host2uint16_t_le((uint16_t)(leaf >> 32));
[1a7756a]96}
97
[acd869e]98uint16_t ext4_extent_header_get_magic(ext4_extent_header_t *header)
99{
100 return uint16_t_le2host(header->magic);
101}
102
[343ccfd]103void ext4_extent_header_set_magic(ext4_extent_header_t *header, uint16_t magic)
104{
105 header->magic = host2uint16_t_le(magic);
106}
107
[acd869e]108uint16_t ext4_extent_header_get_entries_count(ext4_extent_header_t *header)
109{
110 return uint16_t_le2host(header->entries_count);
111}
112
[343ccfd]113void ext4_extent_header_set_entries_count(ext4_extent_header_t *header,
114 uint16_t count)
115{
116 header->entries_count = host2uint16_t_le(count);
117}
118
[acd869e]119uint16_t ext4_extent_header_get_max_entries_count(ext4_extent_header_t *header)
120{
121 return uint16_t_le2host(header->max_entries_count);
122}
123
[343ccfd]124void ext4_extent_header_set_max_entries_count(ext4_extent_header_t *header,
125 uint16_t max_count)
126{
127 header->max_entries_count = host2uint16_t_le(max_count);
128}
129
[acd869e]130uint16_t ext4_extent_header_get_depth(ext4_extent_header_t *header)
131{
132 return uint16_t_le2host(header->depth);
133}
134
[343ccfd]135void ext4_extent_header_set_depth(ext4_extent_header_t *header, uint16_t depth)
136{
137 header->depth = host2uint16_t_le(depth);
138}
139
[acd869e]140uint32_t ext4_extent_header_get_generation(ext4_extent_header_t *header)
141{
142 return uint32_t_le2host(header->generation);
143}
[829d238]144
[343ccfd]145void ext4_extent_header_set_generation(ext4_extent_header_t *header,
146 uint32_t generation)
147{
148 header->generation = host2uint32_t_le(generation);
149}
150
[47faec1]151static void ext4_extent_binsearch_idx(ext4_extent_header_t *header,
152 ext4_extent_index_t **index, uint32_t iblock)
153{
154 ext4_extent_index_t *r, *l, *m;
155
156 uint16_t entries_count = ext4_extent_header_get_entries_count(header);
157
158 if (entries_count == 1) {
159 *index = EXT4_EXTENT_FIRST_INDEX(header);
160 return;
161 }
162
163 l = EXT4_EXTENT_FIRST_INDEX(header) + 1;
164 r = l + entries_count - 1;
165
166 while (l <= r) {
167 m = l + (r - l) / 2;
168 uint32_t first_block = ext4_extent_index_get_first_block(m);
169 if (iblock < first_block) {
170 r = m - 1;
171 } else {
172 l = m + 1;
173 }
174 }
175
176 *index = l - 1;
177}
178
[30ac3c3]179static void ext4_extent_binsearch(ext4_extent_header_t *header,
180 ext4_extent_t **extent, uint32_t iblock)
[a4419e7]181{
182 ext4_extent_t *r, *l, *m;
183
184 uint16_t entries_count = ext4_extent_header_get_entries_count(header);
185
186 if (entries_count == 0) {
187 // this leaf is empty
[47faec1]188 EXT4FS_DBG("EMPTY LEAF");
189 *extent = NULL;
190 return;
191 }
192
193 if (entries_count == 1) {
194 *extent = EXT4_EXTENT_FIRST(header);
[a4419e7]195 return;
196 }
197
198 l = EXT4_EXTENT_FIRST(header) + 1;
199 r = l + entries_count - 1;
[9104bb5]200
[a4419e7]201 while (l <= r) {
202 m = l + (r - l) / 2;
[47faec1]203 uint32_t first_block = ext4_extent_get_first_block(m);
204 if (iblock < first_block) {
[a4419e7]205 r = m - 1;
206 } else {
207 l = m + 1;
208 }
209 }
210
[30ac3c3]211 *extent = l - 1;
[a4419e7]212}
213
214static int ext4_extent_find_extent(ext4_filesystem_t *fs,
215 ext4_inode_ref_t *inode_ref, uint32_t iblock, ext4_extent_t **ret_extent)
[e2629b08]216{
[9104bb5]217 int rc;
[e2629b08]218
[9104bb5]219 block_t* block = NULL;
[e2629b08]220
[9104bb5]221 ext4_extent_header_t *header = ext4_inode_get_extent_header(inode_ref->inode);
222 while (ext4_extent_header_get_depth(header) != 0) {
[e2629b08]223
[47faec1]224 ext4_extent_index_t *index;
225 ext4_extent_binsearch_idx(header, &index, iblock);
[e2629b08]226
[47faec1]227 uint64_t child = ext4_extent_index_get_leaf(index);
[e2629b08]228
[47faec1]229 if (block != NULL) {
230 block_put(block);
[9104bb5]231 }
[e2629b08]232
[47faec1]233 rc = block_get(&block, fs->device, child, BLOCK_FLAGS_NONE);
234 if (rc != EOK) {
235 return rc;
236 }
[e2629b08]237
[47faec1]238 header = (ext4_extent_header_t *)block->data;
239 }
[e2629b08]240
241
[47faec1]242 ext4_extent_t *extent = NULL;
243 ext4_extent_binsearch(header, &extent, iblock);
244 *ret_extent = extent;
[a4419e7]245
[9104bb5]246 return EOK;
247}
[e2629b08]248
[9104bb5]249int ext4_extent_find_block(ext4_filesystem_t *fs,
250 ext4_inode_ref_t *inode_ref, uint32_t iblock, uint32_t *fblock)
251{
252 int rc;
[e2629b08]253
[9104bb5]254 ext4_extent_t *extent = NULL;
255 rc = ext4_extent_find_extent(fs, inode_ref, iblock, &extent);
256 if (rc != EOK) {
257 return rc;
[e2629b08]258 }
259
[9104bb5]260 uint32_t phys_block;
261 phys_block = ext4_extent_get_start(extent) + iblock;
262 phys_block -= ext4_extent_get_first_block(extent);
[e2629b08]263
264
[9104bb5]265 *fblock = phys_block;
[e2629b08]266
267 return EOK;
[9104bb5]268
269
270// ext4_extent_header_t *eh =
271// ext4_inode_get_extent_header(inode_ref->inode);
272//
273// uint16_t depth = ext4_extent_header_get_depth(eh);
274//
275// ext4_extent_path_t *tmp_path;
276//
277// // Added 2 for possible tree growing
278// tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2));
279// if (tmp_path == NULL) {
280// *path = NULL;
281// return ENOMEM;
282// }
283//
284// tmp_path[0].block = inode_ref->block;
285// tmp_path[0].header = eh;
286//
287// uint16_t pos = 0;
288// while (ext4_extent_header_get_depth(eh) != 0) {
289//
290// EXT4FS_DBG("count == \%u", ext4_extent_header_get_entries_count(eh));
291//
292// ext4_extent_binsearch_idx(tmp_path + pos, iblock);
293//
294// uint32_t offset = (void *)tmp_path[pos].index - (void *)EXT4_EXTENT_FIRST_INDEX(eh);
295//
296// EXT4FS_DBG("offset = \%u", offset);
297//
298// EXT4FS_DBG("first block = \%u, leaf = \%u",
299// ext4_extent_index_get_first_block(tmp_path[pos].index),
300// (uint32_t)ext4_extent_index_get_leaf(tmp_path[pos].index));
301//
302// tmp_path[pos].depth = depth;
303// tmp_path[pos].extent = NULL;
304//
305// assert(tmp_path[pos].index != NULL);
306//
307// uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);
308//
309// EXT4FS_DBG("fblock = \%u", (uint32_t)fblock);
310//
311// block_t *block;
312// rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
313// if (rc != EOK) {
314// // TODO cleanup
315// EXT4FS_DBG("ERRRR");
316// return rc;
317// }
318//
319// EXT4FS_DBG("block loaded");
320//
321// pos++;
322//
323// eh = (ext4_extent_header_t *)block->data;
324// tmp_path[pos].block = block;
325// tmp_path[pos].header = eh;
326//
327// }
328//
329// tmp_path[pos].depth = 0;
330// tmp_path[pos].extent = NULL;
331// tmp_path[pos].index = NULL;
332//
333// EXT4FS_DBG("pos = \%u", pos);
334//
335// /* find extent */
336// ext4_extent_binsearch(tmp_path + pos, iblock);
337//
338// EXT4FS_DBG("after binsearch in extent");
339//
340// /* if not an empty leaf */
341// if (tmp_path[pos].extent) {
342// EXT4FS_DBG("nonempty leaf");
343//
344//// uint64_t fblock = ext4_extent_get_start(tmp_path[pos].extent);
345//// block_t *block;
346//// rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
347//// if (rc != EOK) {
348//// // TODO cleanup
349//// }
350//// tmp_path[pos].block = block;
351// }
352//
353// *path = tmp_path;
354//
355// return EOK;
[e2629b08]356}
357
[829d238]358/**
359 * @}
360 */
Note: See TracBrowser for help on using the repository browser.